您的位置:首页 > Web前端 > CSS

WPF通用窗体模板【2】

2017-09-20 00:00 302 查看
摘要: 通用窗口模板-标题居中,窗体功能全部重写。

接上一篇的通用窗体模板,这个模板是重写窗体样式的自定义模板,与上篇不同的是它将窗体的一些基本功能全部清空(放大、缩小、关闭按钮,窗体双击放大缩小,窗体可拖拉大小,标题和logo等)。我们需要重写函数来实现这些功能。

首先是新建窗体文件window.xaml,为何不用资源字典文件呢?因为我们需要写函数所以需要cs文件,而窗体文件新建后会自动生成window.xaml.cs,只需将window标签修改为ResourceDictionary即可。





cs文件中修改:



然后开始写窗体样式,在xaml中添加:

<!-- 菜单按钮组模板 -->
<Style x:Key="WindowCenterMenuBtn" TargetType="Button">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Opacity" Value="0.2"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock FontSize="25" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1.0"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 通用窗口模板-标题居中 -->
<ControlTemplate x:Key="WindowCenterTemplate" TargetType="Window">
<Border x:Name="WindowCenterFrame" Margin="0" CornerRadius="0" BorderThickness="1" BorderBrush="DodgerBlue"  Background="#FFFFFF" MouseLeftButtonDown="CustomWindow_MouseLeftButtonDown" >
<Border.Effect>
<DropShadowEffect BlurRadius="3" RenderingBias="Performance" ShadowDepth="0" Opacity="1"/>
</Border.Effect>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Row="0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="0.6">
<GradientStop Color="#FFFBFBFC" Offset="1"/>
<GradientStop Color="#FFF3F7FB" Offset="0.021"/>
</LinearGradientBrush>
</Border.Background>
<Grid MouseDown="CustomWindow_MouseDoubleDown">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="60,0,0,0">
<Button   Width="22"  HorizontalAlignment="Center" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{x:Static SystemCommands.ShowSystemMenuCommand}"
CommandParameter="{Binding ElementName=_MainWindow}">
<!-- Make sure there is a resource with name Icon in MainWindow -->
<Image
Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}"
WindowChrome.IsHitTestVisibleInChrome="True"/>
</Button>
<TextBlock   VerticalAlignment="Center" Text="{Binding Title, RelativeSource={RelativeSource TemplatedParent}}"  FontSize="13"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,20,0" VerticalAlignment="Center">
<Button x:Name="MinBtn" Height="20" Width="30" Content="-"
Style="{StaticResource ResourceKey=WindowCenterMenuBtn}" Click="CustomWindowBtnMinimized_Click" />
<Button x:Name="MaxBtn" Height="20" Width="30" Content="□"
Style="{StaticResource ResourceKey=WindowCenterMenuBtn}" Click="CustomWindowBtnMaxNormal_Click" />
<Button x:Name="CloseBtn" Height="20" Width="30" Content="×"
Style="{StaticResource ResourceKey=WindowCenterMenuBtn}" Click="CustomWindowBtnClose_Click" />
</StackPanel>
</Grid>
</Border>
<Grid Grid.Row="1">
<AdornerDecorator>
<ContentPresenter></ContentPresenter>
</AdornerDecorator>
</Grid>
</Grid>
</Border>
</ControlTemplate>

<!-- 通用窗口样式-标题居中 -->
<Style x:Key="WindowCenterChrome" TargetType="Window">
<Setter Property="AllowsTransparency" Value="True"></Setter>
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="WindowStyle" Value="None"></Setter>
<Setter Property="ResizeMode" Value="NoResize"></Setter>
<Setter Property="Template" Value="{StaticResource WindowCenterTemplate}"></Setter>
</Style>

接下来是功能函数,在cs文件中添加代码,实现窗口的放大、缩小、关闭、双击放大缩小、鼠标拖动窗口等。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Resource.Styles.Base
{
public partial class CustomWindow : ResourceDictionary
{
public class Tools
{
//双击事件定时器
private static DispatcherTimer _timer;
//是否单击过一次
private static bool _isFirst;

static Tools()
{
_timer = new DispatcherTimer();
_timer.Interval = new TimeSpan(0, 0, 0, 0, 400);
_timer.Tick += new EventHandler(_timer_Tick);
}

/// <summary>
/// 判断是否双击
/// </summary>
/// <returns></returns>
public static bool IsDoubleClick()
{
if (!_isFirst)
{
_isFirst = true;
_timer.Start();
return false;
}
else
{
return true;
}
}

//间隔时间
private static void _timer_Tick(object sender, EventArgs e)
{
_isFirst = false;
_timer.Stop();
}
}

// 拖动
private void CustomWindow_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
Window win = (Window) ((FrameworkElement) sender).TemplatedParent;
if (e.LeftButton == MouseButtonState.Pressed)
{
win.DragMove();
}

}

//双击放大缩小
private void CustomWindow_MouseDoubleDown(object sender, MouseEventArgs e)
{
Window win = (Window) ((FrameworkElement) sender).TemplatedParent;
if (Tools.IsDoubleClick())
{
win.WindowState = win.WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
}

// 关闭
private void CustomWindowBtnClose_Click(object sender, RoutedEventArgs e)
{
Window win = (Window) ((FrameworkElement) sender).TemplatedParent;
//提示是否要关闭
if (MessageBox.Show("确定要退出系统?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question) ==
MessageBoxResult.Yes)
{
System.Windows.Application.Current.Shutdown();
}
}

// 最小化
private void CustomWindowBtnMinimized_Click(object sender, RoutedEventArgs e)
{
Window win = (Window) ((FrameworkElement) sender).TemplatedParent;
win.WindowState = WindowState.Minimized;
}

// 最大化、还原
private void CustomWindowBtnMaxNormal_Click(object sender, RoutedEventArgs e)
{
Window win = (Window) ((FrameworkElement) sender).TemplatedParent;
if (win.WindowState == WindowState.Maximized)
{
win.WindowState = WindowState.Normal;
}
else
{
// 不覆盖任务栏
win.MaxWidth = SystemParameters.WorkArea.Width;
win.MaxHeight = SystemParameters.WorkArea.Height;
win.WindowState = WindowState.Maximized;
}
}
}
}

最后在你要应用自定义样式的window窗体中添加引用:

<Window x:Class="EGIS.Main.UI.OPWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Style="{DynamicResource WindowCenterChrome}"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
Loaded="OPWindow_Loaded" >
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/EGIS.Resource;component/Resource/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

在这个窗体的cs文件中的OPWindow_Loaded函数中添加如下语句(实现页面加载全屏不遮挡任务栏):

private void OPWindow_Loaded(object sender, RoutedEventArgs e)
{
try
{
//使页面全屏化但不遮挡任务栏
this.MaxWidth = SystemParameters.WorkArea.Width;
this.MaxHeight = SystemParameters.WorkArea.Height;
this.WindowState = WindowState.Maximized;
}
catch (Exception ex)
{
LogService.WriteExceptionLog(ex, "");
}

}

还有一个窗体事件为鼠标拖动改变窗口大小,这个查询了网上的一些方法,最终用下面的代码实现:

#region 重写页面,鼠标左键拖动改变窗口大小
#region 这一部分是四个边加上四个角
public enum ResizeDirection
{
Left = 1,
Right = 2,
Top = 3,
TopLeft = 4,
TopRight = 5,
Bottom = 6,
BottomLeft = 7,
BottomRight = 8,
}
#endregion

#region 用于改变窗体大小
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

private void ResizeWindow(ResizeDirection direction)
{
SendMessage(hs.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);
}
#endregion

#region 为元素注册事件
private void InitializeEvent()
{
//获取当前窗口调用的style样式
Style temStyle = this.Resources["CustomWindowChrome"] as Style;
if (temStyle!=null)
{
Setter temSetter = null;
foreach (Setter item in temStyle.Setters)
{
if (item.Value == Template)
temSetter = item;
}

ControlTemplate baseWindowTemplate = (ControlTemplate)temSetter.Value;
Border borderClip = (Border)baseWindowTemplate.FindName("CustomWindowFrame", this);

borderClip.MouseMove += delegate
{
DisplayResizeCursor(null, null);
};

borderClip.PreviewMouseDown += delegate
{
Resize(null, null);
};

borderClip.MouseLeftButtonDown += delegate
{
DragMove();
};

this.PreviewMouseMove += delegate
{
ResetCursor(null, null);
};
}

}
#endregion

#region 重写的DragMove,以便解决利用系统自带的DragMove出现Exception的情况
public new void DragMove()
{
if (this.WindowState == WindowState.Normal)
{
SendMessage(hs.Handle, WM_SYSCOMMAND, (IntPtr)0xf012, IntPtr.Zero);
SendMessage(hs.Handle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
}
}
#endregion

#region 显示拖拉鼠标形状
private void DisplayResizeCursor(object sender, MouseEventArgs e)
{
Point pos = Mouse.GetPosition(this);
double x = pos.X;
double y = pos.Y;
double w = this.ActualWidth;  //注意这个地方使用ActualWidth,才能够实时显示宽度变化
double h = this.ActualHeight;

if (x <= relativeClip & y <= relativeClip) // left top
{
this.Cursor = Cursors.SizeNWSE;
}
if (x >= w - relativeClip & y <= relativeClip) //right top
{
this.Cursor = Cursors.SizeNESW;
}

if (x >= w - relativeClip & y >= h - relativeClip) //bottom right
{
this.Cursor = Cursors.SizeNWSE;
}

if (x <= relativeClip & y >= h - relativeClip)  // bottom left
{
this.Cursor = Cursors.SizeNESW;
}

if ((x >= relativeClip & x <= w - relativeClip) & y <= relativeClip) //top
{
this.Cursor = Cursors.SizeNS;
}

if (x >= w - relativeClip & (y >= relativeClip & y <= h - relativeClip)) //right
{
this.Cursor = Cursors.SizeWE;
}

if ((x >= relativeClip & x <= w - relativeClip) & y > h - relativeClip) //bottom
{
this.Cursor = Cursors.SizeNS;
}

if (x <= relativeClip & (y <= h - relativeClip & y >= relativeClip)) //left
{
this.Cursor = Cursors.SizeWE;
}
}
#endregion

#region  还原鼠标形状
private void ResetCursor(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton != MouseButtonState.Pressed)
{
this.Cursor = Cursors.Arrow;
}
}
#endregion

#region 判断区域,改变窗体大小
private void Resize(object sender, MouseButtonEventArgs e)
{
Point pos = Mouse.GetPosition(this);
double x = pos.X;
double y = pos.Y;
double w = this.ActualWidth;
double h = this.ActualHeight;

if (x <= relativeClip & y <= relativeClip) // left top
{
this.Cursor = Cursors.SizeNWSE;
ResizeWindow(ResizeDirection.TopLeft);
}
if (x >= w - relativeClip & y <= relativeClip) //right top
{
this.Cursor = Cursors.SizeNESW;
ResizeWindow(ResizeDirection.TopRight);
}

if (x >= w - relativeClip & y >= h - relativeClip) //bottom right
{
this.Cursor = Cursors.SizeNWSE;
ResizeWindow(ResizeDirection.BottomRight);
}

if (x <= relativeClip & y >= h - relativeClip)  // bottom left
{
this.Cursor = Cursors.SizeNESW;
ResizeWindow(ResizeDirection.BottomLeft);
}

if ((x >= relativeClip & x <= w - relativeClip) & y <= relativeClip) //top
{
this.Cursor = Cursors.SizeNS;
ResizeWindow(ResizeDirection.Top);
}

if (x >= w - relativeClip & (y >= relativeClip & y <= h - relativeClip)) //right
{
this.Cursor = Cursors.SizeWE;
ResizeWindow(ResizeDirection.Right);
}

if ((x >= relativeClip & x <= w - relativeClip) & y > h - relativeClip) //bottom
{
this.Cursor = Cursors.SizeNS;
ResizeWindow(ResizeDirection.Bottom);
}

if (x <= relativeClip & (y <= h - relativeClip & y >= relativeClip)) //left
{
this.Cursor = Cursors.SizeWE;
ResizeWindow(ResizeDirection.Left);
}
}
#endregion

#endregion

代码中注意修改一下,将CustomWindowChrome改为通用窗体的名称WindowCenterChrome。CustomWindowFrame修改为WindowCenterFrame。

到此,一个完全重写的自定义样式就完成了,还有一点和上篇的通用窗体样式一样,会与WindowsFormsHost控件有冲突。

注意代码中的标签或样式名称问题,可能会有没有统一的部分,使用时自己排查一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息