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

WPF通用窗体样式【3】

2017-09-21 00:00 169 查看
摘要: 与WindowsFormsHost控件无冲突的通用窗体样式。需重写功能函数。

wei接上两篇内容,这篇讲的是重写窗体样式及功能,实现与WindowsFormsHost控件不冲突的标题居中通用窗体样式。

跟《通用窗体样式【2】》一样新建window窗体文件,然后修改成资源文件,在xaml文件中写自定义样式:

<DataTemplate x:Key="RestoreWhite">
<Grid UseLayoutRounding="True"
RenderTransform="1,0,0,1,.5,.5">
<Path Data="M2,0 L8,0 L8,6 M0,3 L6,3 M0,2 L6,2 L6,8 L0,8 Z"
Width="8"
Height="8"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="Black"
StrokeThickness="1" />
</Grid>
</DataTemplate>

<DataTemplate x:Key="CloseWhite">
<Grid Margin="1,0,0,0">
<Rectangle Stroke="Black"
Height="2"
RenderTransformOrigin="0.5,0.5"
Width="11"
UseLayoutRounding="True">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="45" />
<TranslateTransform />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Stroke="Black"
Height="2"
RenderTransformOrigin="0.5,0.5"
Width="11"
UseLayoutRounding="True">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="-45" />
<TranslateTransform />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</DataTemplate>

<DataTemplate x:Key="MaximizeWhite">
<Grid>
<Path Data="M0,1 L9,1 L9,8 L0,8 Z"
Width="9"
Height="8"
Margin="0,2,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="Black"
StrokeThickness="2" />
</Grid>
</DataTemplate>

<DataTemplate x:Key="MinimizeWhite">
<Grid>
<Path Data="M0,6 L8,6 Z"
Width="8"
Height="7"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="Black"
StrokeThickness="2" />
</Grid>
</DataTemplate>

<Style x:Key="TitleBarButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2"
SnapsToDevicePixels="True"
Stroke="Transparent"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style x:Key="TitleBarButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="Focusable"
Value="False" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Padding"
Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="LayoutRoot">
<Rectangle x:Name="ButtonBackground"
Width="28"
Height="28"
Fill="#FFFFFFFF"
Opacity="0" />
<Border x:Name="ButtonBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<ContentPresenter x:Name="TitleBarButtonContentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid>

<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Opacity"
Value="0.2"
TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsPressed"
Value="True">
<Setter Property="Opacity"
Value="0.4"
TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="TitleBarButtonContentPresenter"
Property="Opacity"
Value=".5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<!-- 通用窗口模板-标题居中-无冲突 -->
<ControlTemplate x:Key="MiddleWindowTemplate" TargetType="{x:Type Window}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
x:Name="WindowBorder">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid x:Name="PART_WindowTitleGrid"
Grid.Row="0"
Height="22"
Background="{TemplateBinding BorderBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="60,0,0,0">
<!--<Image Source="{TemplateBinding Icon}"
Margin="7,0,5,0"
VerticalAlignment="Center"
/>-->
<Button VerticalAlignment="Center"
Margin="5,0"
Content="{TemplateBinding Icon}"
Height="{x:Static SystemParameters.SmallIconHeight}"
Width="{x:Static SystemParameters.SmallIconWidth}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsTabStop="False">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Image Source="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>

</Button>
<ContentControl IsTabStop="False"
Foreground="Black"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{DynamicResource {x:Static SystemFonts.CaptionFontSize}}"
Content="{TemplateBinding Title}" FontFamily="Microsoft YaHei" />
</StackPanel>
<StackPanel x:Name="WindowCommandButtonsStackPanel"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="Transparent"
Orientation="Horizontal"
WindowChrome.IsHitTestVisibleInChrome="True">
<Button x:Name="Minimize"
ToolTip="Minimize"
WindowChrome.IsHitTestVisibleInChrome="True"

Click="CustomWindowBtnMinimized_Click"
ContentTemplate="{StaticResource MinimizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
<Grid Margin="1,0,1,0">
<Button x:Name="Restore"
ToolTip="Restore"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}"
ContentTemplate="{StaticResource RestoreWhite}"
Style="{StaticResource TitleBarButtonStyle}"
Visibility="Collapsed"
IsTabStop="False" />
<Button x:Name="Maximize"
ToolTip="Maximize"
WindowChrome.IsHitTestVisibleInChrome="True"

Click="CustomWindowBtnMaxNormal_Click"
ContentTemplate="{StaticResource MaximizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</Grid>
<Button x:Name="Close"
ToolTip="Close"
WindowChrome.IsHitTestVisibleInChrome="True"

Click="CustomWindowBtnClose_Click"
ContentTemplate="{StaticResource CloseWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</StackPanel>
</Grid>
<AdornerDecorator Grid.Row="1" KeyboardNavigation.IsTabStop="False">
<!--<ContentPresenter x:Name="MainContentPresenter"
KeyboardNavigation.TabNavigation="Cycle" />-->
<Border Background="White" Opacity="1">
<ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
</AdornerDecorator>
<ResizeGrip x:Name="ResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Grid.Row="1"
IsTabStop="False"
Visibility="Hidden"
WindowChrome.ResizeGripDirection="BottomRight" />
</Grid>
</Border>

<ControlTemplate.Triggers>
<!--设置窗体未激活状态的颜色-->
<!--<Trigger Property="IsActive" Value="False">
<Setter Property="BorderBrush" Value="#FF6F7785" />
</Trigger>-->
<Trigger Property="WindowState" Value="Maximized">
<Setter TargetName="Maximize"
Property="Visibility"
Value="Visible" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Visible" />
<Setter TargetName="LayoutRoot"
Property="Margin"
Value="7" />
</Trigger>
<Trigger Property="WindowState" Value="Normal">
<Setter TargetName="Maximize"
Property="Visibility"
Value="Visible" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<Trigger Property="ResizeMode" Value="NoResize">
<Setter TargetName="Minimize"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="Maximize"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Collapsed" />
</Trigger>

<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip" />
<Condition Property="WindowState" Value="Normal" />
</MultiTrigger.Conditions>
<Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- 通用窗口样式-标题居中-无冲突 -->
<Style x:Key="MiddleWindowStyle" TargetType="Window">
<Setter Property="Template" Value="{StaticResource MiddleWindowTemplate}"></Setter>
<Setter Property="ResizeMode"
Value="CanResizeWithGrip" />
<Setter Property="UseLayoutRounding"
Value="True" />
<Setter Property="TextOptions.TextFormattingMode"
Value="Display" />
<Setter Property="WindowStyle"
Value="SingleBorderWindow" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CornerRadius="0"
GlassFrameThickness="1"
UseAeroCaptionButtons="False"
NonClientFrameEdges="None" />
</Setter.Value>
</Setter>
</Style>

这个窗体样式跟上一篇的不同点是这个窗体重写了按钮样式,相对来说好看一点;这个窗体的双击窗口放大缩小、鼠标左键拖动边框改变大小、鼠标左键拖动窗体等都不用重写;而且页面默认是显示全屏但不遮挡状态栏的,所以在window窗体应用时,也不用再页面的onload函数中再写代码。

相同点是需要重写放大、缩小、关闭按钮,在cs文件中添加相应的函数(请参考上一篇代码)。如下:

// 关闭
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;
//解决MiddleCustomWindow窗体样式中的页面放大缩小右边和下方出现9px的黑边问题。
win.MaxWidth = SystemParameters.MaximumWindowTrackWidth;
win.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
win.WindowState = WindowState.Maximized;
}
}

注意窗体最大化函数有一点修改,不覆盖任务栏的写法有修改,为了解决当前的自定义窗体样式最大化后右下角和下方出现黑边的问题。

查询微软的文档https://msdn.microsoft.com/zh-cn/library/system.windows.systemparameters.aspx

SystemParameters.WorkArea获取主监视器上工作区域的尺寸。

SystemParameters.MaximumWindowTrackWidth获取一个值,该值指示窗口的最大宽度(以像素为单位),该窗口具有标题和可调整大小的边框。

具体原理还没搞清楚,不过修改后问题解决了,不知道有没有大神交流一下这个问题?

最后就是在窗体中应用这个自定义样式了,只需在window.xaml文件中添加:

Style="{DynamicResource MiddleWindowStyle}" //window中添加,引用通用窗口样式

<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/路径/Dictionary1.xaml" />//引用资源文件
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息