WPF利用WindowChrome實(shí)現(xiàn)自定義窗口
簡(jiǎn)介
Microsoft官網(wǎng)關(guān)于 WindowChome 的介紹
截取Microsoft文章的一段話:
若要在保留其標(biāo)準(zhǔn)功能時(shí)自定義窗口,可以使用該 WindowChrome 類(lèi)。 該 WindowChrome 類(lèi)將窗口框架的功能與視覺(jué)對(duì)象分開(kāi),并允許你控制應(yīng)用程序窗口的客戶端和非客戶端區(qū)域之間的邊界。 通過(guò) WindowChrome 該類(lèi),可以通過(guò)擴(kuò)展工作區(qū)來(lái)覆蓋非工作區(qū),將 WPF 內(nèi)容置于窗口框架中。 同時(shí),它通過(guò)兩個(gè)不可見(jiàn)區(qū)域保留系統(tǒng)行為: 調(diào)整邊框 和 標(biāo)題 區(qū)域的大小。
效果圖
自定義最小化、最大化、關(guān)閉按鈕
最小化按鈕
<Style x:Key="SystemCloseButtonStyle" BasedOn="{StaticResource SystemButtonStyleBase}" TargetType="{x:Type Button}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid Background="{TemplateBinding Background}"> <Viewbox Width="12" Height="12"> <Path Data="M550.848 502.496l308.64-308.896a31.968 31.968 0 1 0-45.248-45.248l-308.608 308.896-308.64-308.928a31.968 31.968 0 1 0-45.248 45.248l308.64 308.896-308.64 308.896a31.968 31.968 0 1 0 45.248 45.248l308.64-308.896 308.608 308.896a31.968 31.968 0 1 0 45.248-45.248l-308.64-308.864z" Fill="{TemplateBinding BorderBrush}" /> </Viewbox> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="{StaticResource CloseColor}" /> <Setter Property="BorderBrush" Value="{StaticResource DominantColor}" /> </Trigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
最大化按鈕
<Style x:Key="SystemMaxButtonStyle" BasedOn="{StaticResource SystemButtonStyleBase}" TargetType="{x:Type Button}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid Background="{TemplateBinding Background}"> <Viewbox Width="12" Height="12"> <Path Data="M959.72 0H294.216a63.96 63.96 0 0 0-63.96 63.96v127.92H64.28A63.96 63.96 0 0 0 0.32 255.84V959.4a63.96 63.96 0 0 0 63.96 63.96h703.56a63.96 63.96 0 0 0 63.96-63.96V792.465h127.92a63.96 63.96 0 0 0 63.96-63.96V63.96A63.96 63.96 0 0 0 959.72 0zM767.84 728.505V959.4H64.28V255.84h703.56z m189.322 0H831.8V255.84a63.96 63.96 0 0 0-63.96-63.96H294.216V63.96H959.72z" Fill="{TemplateBinding BorderBrush}" /> </Viewbox> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="{StaticResource SuspensionColor}" /> </Trigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
關(guān)閉按鈕
<Style x:Key="SystemMinButtonStyle" BasedOn="{StaticResource SystemButtonStyleBase}" TargetType="{x:Type Button}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid Background="{TemplateBinding Background}"> <Viewbox Width="12" Height="10"> <Path Data="M928.2 548h-832c-17.7 0-32-14.3-32-32s14.3-32 32-32h832c17.7 0 32 14.3 32 32s-14.3 32-32 32z" Fill="{TemplateBinding BorderBrush}" /> </Viewbox> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="{StaticResource SuspensionColor}" /> </Trigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusVisualStyle" Value="{x:Null}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
/// <summary> /// 窗口移動(dòng) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Move_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) => this.DragMove(); /// <summary> /// 最小化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMin_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized; /// <summary> /// 最大化/還原 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnMax_Click(object sender, RoutedEventArgs e) => WindowState = WindowState is WindowState.Normal ? WindowState.Maximized : WindowState.Normal; /// <summary> /// 關(guān)閉 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnClose_Click(object sender, RoutedEventArgs e) => Application.Current.Shutdown();
布局實(shí)現(xiàn)
首先我們需要在 MainWindow 也就是我們的主窗口中的 Window.Resources 中實(shí)現(xiàn) WindowChrome 的基本樣式:
WindowChrome.ResizeBorderThickness 設(shè)置不可見(jiàn)邊框?qū)挾?/p>
WindowChrome.CaptionHeight> 設(shè)置屬于標(biāo)題欄的范圍——高度
WindowChrome.UseAeroCaptionButtons 是否啟用默認(rèn)系統(tǒng)按鈕功能——三大金剛鍵
WindowChrome.NonClientFrameEdges 設(shè)置客戶區(qū)域,使用 bottom 可以實(shí)現(xiàn)加載時(shí)空白窗口而不顯示默認(rèn)窗口,提升用戶體驗(yàn)
<Window x:Class="SignalRClient.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:local="clr-namespace:SignalRClient" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="" Width="880" Height="620" MinWidth="700" MinHeight="500" Style="{StaticResource mainWindow}" WindowChrome.WindowChrome="{DynamicResource WindowChromeKey}" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> <Window.Resources> <WindowChrome x:Key="WindowChromeKey"> <WindowChrome.ResizeBorderThickness> <Thickness>5</Thickness> </WindowChrome.ResizeBorderThickness> <WindowChrome.CaptionHeight>60</WindowChrome.CaptionHeight> <WindowChrome.UseAeroCaptionButtons>false</WindowChrome.UseAeroCaptionButtons> <WindowChrome.NonClientFrameEdges>bottom</WindowChrome.NonClientFrameEdges> </WindowChrome> </Window.Resources> </Window>
重寫(xiě)窗口,實(shí)現(xiàn)最大化窗口下,標(biāo)題欄及客戶區(qū)域偏移問(wèn)題的修正。
通過(guò)代碼獲取當(dāng)前窗口的工作區(qū)域,及任務(wù)欄以外的其他區(qū)域
System.Windows.SystemParameters.WorkArea.Width 獲取工作區(qū)域的寬
System.Windows.SystemParameters.WorkArea.Height 獲取工作區(qū)域的高
為什么要使用 ValueConverter 主要是因?yàn)?WorkArea 返回的類(lèi)型無(wú)法直接 binding xaml
<ValueConverters:WorkAreaWidth x:Key="workAreaWidth" /> <ValueConverters:WorkAreaHeight x:Key="workAreaHeight" /> <Style x:Key="mainWindow" TargetType="{x:Type Window}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Window"> <ContentControl x:Name="window" Content="{TemplateBinding Content}" /> <ControlTemplate.Triggers> <Trigger Property="WindowState" Value="Maximized"> <Setter TargetName="window" Property="MaxHeight" Value="{Binding Converter={StaticResource workAreaHeight}}" /> <Setter TargetName="window" Property="MaxWidth" Value="{Binding Converter={StaticResource workAreaWidth}}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
using System; using System.Globalization; using System.Windows.Data; namespace SignalRClient.ValueConverters { internal class WorkAreaWidth : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return System.Windows.SystemParameters.WorkArea.Width; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
using System; using System.Globalization; using System.Windows.Data; namespace SignalRClient.ValueConverters { internal class WorkAreaHeight : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return System.Windows.SystemParameters.WorkArea.Height; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
結(jié)語(yǔ)
一開(kāi)始,確實(shí)很難搞,Microsoft 的文檔,里面也并沒(méi)有,詳細(xì)介紹窗口內(nèi)容溢出的問(wèn)題,但是只要仔細(xì)研究過(guò) WPF 的同學(xué)都知道,很多東西是可以通過(guò) Trigger
來(lái)實(shí)現(xiàn)的。Get 到這一點(diǎn)很多問(wèn)題就迎刃而解了。
到此這篇關(guān)于WPF利用WindowChrome實(shí)現(xiàn)自定義窗口的文章就介紹到這了,更多相關(guān)WPF WindowChrome自定義窗口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用handle實(shí)現(xiàn)獲取占用指定文件或文件夾的進(jìn)程
很多時(shí)候,一些不知道啥進(jìn)程,把你的文件給占用了,然后就沒(méi)辦法刪掉或者做其他操作,如果使用Locksmith功能,就可以實(shí)現(xiàn)快速鎖定是哪個(gè)進(jìn)程在搞事情,把對(duì)應(yīng)進(jìn)程干掉就可以了,下面內(nèi)容演示C#使用幾行代碼實(shí)現(xiàn)File?Locksmith功能,需要的朋友可以參考下2024-09-09C#使用自定義的泛型節(jié)點(diǎn)類(lèi)實(shí)現(xiàn)二叉樹(shù)類(lèi)
這篇文章主要為大家詳細(xì)介紹了C#如何使用自定義的泛型節(jié)點(diǎn)類(lèi) Node<T>實(shí)現(xiàn)二叉樹(shù)類(lèi)BinaryTree<T>及其方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03C#實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘和日歷
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘和日歷的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06C# 創(chuàng)建、部署和調(diào)用WebService簡(jiǎn)單示例
這篇文章主要為大家詳細(xì)介紹了C# 創(chuàng)建、部署和調(diào)用WebService的簡(jiǎn)單示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05適用于WebForm Mvc的Pager分頁(yè)組件C#實(shí)現(xiàn)
這篇文章主要為大家分享了適用于WebForm Mvc的Pager分頁(yè)組件,由C#實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2016-04-04C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼
這篇文章主要介紹了C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-04-04.Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例
下面小編就為大家?guī)?lái)一篇.Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02通過(guò)實(shí)例解析c# yield關(guān)鍵字使用方法
這篇文章主要介紹了通過(guò)實(shí)例解析c# yield關(guān)鍵字使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09