本文大幅度借鑑dino.c大佬的文章html
https://www.cnblogs.com/dino623/p/uielements_of_window.htmlshell
https://www.cnblogs.com/dino623/p/problems_of_WindowChrome.htmlexpress
https://www.cnblogs.com/dino623/p/custom_window_style_using_WindowChrome.htmlwindows
我在這裏彙總一下,屬於粘了就能用那種。在預設100,125,150,175DPI下最大化也能正常顯示。api
不懂的地方能夠閱讀上面的文章框架
說到原生窗體的特性都有什麼 咱來作個對比 你們來感覺下函數
使用WindowChrome測試
使用WindowStyle="None"動畫
使用WindowChrome的時候 無需設置就保留了原生陰影、拖拽、交互動畫ui
而使用WindowStyle="None"的話,會發現最大化的時候會覆蓋任務欄。
想要實現原生的樣式就須要本身手寫。
這些功能能夠實現嗎?能實現。效果好嗎? 不必定,像我這種WPF玩的不專業的人很難實現這些功能,啥玩意都得上網扒拉,對不對路還不必定,那百度上一人一種寫法,這就很鬧心。
<Window x:Class="WpfApp1.MainWindow" 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" mc:Ignorable="d" Title="MainWindow" SnapsToDevicePixels="True" StateChanged="Window_StateChanged" Loaded="Window_Loaded"> <WindowChrome.WindowChrome> <WindowChrome UseAeroCaptionButtons="False" NonClientFrameEdges="None" CaptionHeight="40" /> </WindowChrome.WindowChrome> <Grid x:Name="grdMain" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="0" Background="#C62F2F"> <WrapPanel Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,10,0"> <Button x:Name="btnMin" Style="{DynamicResource MinButton}" Click="BtnMin_Click"/> <Button x:Name="btnNorm" Style="{DynamicResource MaxButton}" Margin="3,0,0,0" Click="BtnNorm_Click"/> <Button x:Name="btnClose" Style="{DynamicResource CloseButton}" Margin="3,0,0,0" Click="BtnClose_Click"/> </WrapPanel> </Grid> <Grid Grid.Row="1" Background="#FFFFFF"> <Border BorderThickness="1" BorderBrush="#C62F2F"/> </Grid> </Grid> </Window>
UseAeroCaptionButtons 表示是對 Windows Aero 標題按鈕啓用的命中測試是否可用,默認值爲True。
NonClientFrameEdges 獲取或設置一個值,該值表示窗口框架邊緣是否歸客戶端全部,默認值爲None。
CaptionHeight 表示窗體菜單欄高度,我這裏設置跟Gird裏第一行高度一致,表明自定義的菜單欄。
注意下,我在放置按鈕的WrapPanel容器中設置了 WindowChrome.IsHitTestVisibleInChrome,該值表示 WPF 命中測試在窗口非工做區中的元素是否可用,默認值爲False。
接下來是後臺代碼
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WpfApp1 { /// <summary> /// MainWindow.xaml 的交互邏輯 /// </summary> public partial class MainWindow : Window { int paddings = 0; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { paddings = 4; } private void Window_StateChanged(object sender, EventArgs e) { if (WindowState == WindowState.Maximized) { Thickness thickness = SystemParameters.WindowResizeBorderThickness; grdMain.Margin = new Thickness(thickness.Left + paddings, thickness.Top + paddings, thickness.Right + paddings, thickness.Bottom + paddings); } else { grdMain.Margin = new Thickness(0); } } private void BtnMin_Click(object sender, RoutedEventArgs e) { WindowState = WindowState.Minimized; } private void BtnClose_Click(object sender, RoutedEventArgs e) { Close(); } private void BtnNorm_Click(object sender, RoutedEventArgs e) { if (WindowState == WindowState.Normal) { btnNorm.Style = (Style)FindResource("NormButton"); WindowState = WindowState.Maximized; } else { btnNorm.Style = (Style)FindResource("MaxButton"); WindowState = WindowState.Normal; } } } }
這裏的paddings我默認設置爲4,這裏須要借鑑下大佬的第1、二篇文章,裏面很清晰的解釋道爲啥設置爲4。
完整看過第二篇文章的會發現沒法直接獲取SM_CXPADDEDBORDER的值。
我查了官網文檔user32.dll裏面有函數能夠取值。https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getsystemmetrics
[DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetSystemMetrics(int index);
只不過按照這個取值來的話125往上的DPI最大化顯示不正常,邊框會比以前厚,咱就默認4就行。