wei接上兩篇內容,這篇講的是重寫窗體樣式及功能,實現與WindowsFormsHost控件不衝突的標題居中通用窗體樣式。windows
跟《通用窗體樣式【2】》同樣新建window窗體文件,而後修改爲資源文件,在xaml文件中寫自定義樣式:app
<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文件中添加相應的函數(請參考上一篇代碼)。以下:spa
// 關閉 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; } }
注意窗體最大化函數有一點修改,不覆蓋任務欄的寫法有修改,爲了解決當前的自定義窗體樣式最大化後右下角和下方出現黑邊的問題。code
查詢微軟的文檔https://msdn.microsoft.com/zh-cn/library/system.windows.systemparameters.aspxorm
SystemParameters.WorkArea獲取主監視器上工做區域的尺寸。ip
SystemParameters.MaximumWindowTrackWidth獲取一個值,該值指示窗口的最大寬度(以像素爲單位),該窗口具備標題和可調整大小的邊框。ci
具體原理還沒搞清楚,不過修改後問題解決了,不知道有沒有大神交流一下這個問題?資源
最後就是在窗體中應用這個自定義樣式了,只需在window.xaml文件中添加:文檔
Style="{DynamicResource MiddleWindowStyle}" //window中添加,引用通用窗口樣式 <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/路徑/Dictionary1.xaml" />//引用資源文件 </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources>