[WPF] 自定義窗體樣式
阿新 • • 發佈:2019-02-14
效果圖如下:
實現思路:
1.繼承Window類
2.為自定義的CustomWindow類設計窗體樣式(使用Blend很方便!)
3.為窗體增加最大最小化和關閉按鈕,並實現滑鼠拖拽改變窗體大小(使用的WindowResizer.dll庫)
程式碼說明:
1.繼承Window類
建立CustomWindow類,繼承自System.Window
程式碼 publicclass CustomWindow : Window{
public CustomWindow()
{
// 載入樣式 InitializeStyle();
// 載入事件委託
// 解決最大化覆蓋工作列問題this.SourceInitialized +=new EventHandler(win_SourceInitialized);
}
}
程式碼 <src:CustomWindow
x:Class="windowStyle1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:windowStyle1"
Title="CustomWindow"
Height="358" Width="649" AllowsTransparency="True" WindowStyle="None">
2.為自定義的CustomWindow類設計窗體樣式
窗體樣式的設計可以使用Expression Blend來進行視覺化開發,非常方便
Blend會自動生成樣式的xmal檔案:
程式碼 <ResourceDictionary 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" xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"><ControlTemplate x:Key="WindowTemplateKey" TargetType="{x:Type Window}"><Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"><Grid><AdornerDecorator><ContentPresenter/></AdornerDecorator><ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsTabStop="false" Visibility="Collapsed"/></Grid></Border><ControlTemplate.Triggers><MultiTrigger><MultiTrigger.Conditions><Condition Property="ResizeMode" Value="CanResizeWithGrip"/><Condition Property="WindowState" Value="Normal"/></MultiTrigger.Conditions><Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/></MultiTrigger></ControlTemplate.Triggers></ControlTemplate>
3.為窗體增加最大最小化和關閉按鈕,並實現滑鼠拖拽改變窗體大小
按鈕事件比較簡單,通過分別為三個按鈕新增Click事件即可
程式碼 ///<summary>/// 載入按鈕事件委託///</summary>privatevoid InitializeEvent()
{
ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["CustomWindowControlTemplate"];
Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);
minBtn.Click +=delegate
{
this.WindowState = WindowState.Minimized;
};
Button maxBtn = (Button)baseWindowTemplate.FindName("btnMax", this);
maxBtn.Click +=delegate
{
this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
};
Button closeBtn = (Button)baseWindowTemplate.FindName("btnClose", this);
closeBtn.Click +=delegate
{
this.Close();
};
Border tp = (Border)baseWindowTemplate.FindName("topborder", this);
tp.MouseLeftButtonDown +=delegate
{
this.DragMove();
};
}
僅僅這樣實現的話還不夠,因為窗體最大化後會覆蓋工作列,這是我們不希望看到的,所以還必須通過WINDOW API的視窗控制代碼來定義最大化後的尺寸
程式碼 ///<summary>/// 重繪窗體大小///</summary>void win_SourceInitialized(object sender, EventArgs e)
{
System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
WinInterop.HwndSource.FromHwnd(handle).AddHook(new WinInterop.HwndSourceHook(WindowProc));
}
...
[DllImport("user32")]
internalstaticexternbool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("User32")]
internalstaticextern IntPtr MonitorFromWindow(IntPtr handle, int flags);
...
privatestatic System.IntPtr WindowProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, refbool handled)
{
switch (msg)
{
case0x0024:
WmGetMinMaxInfo(hwnd, lParam);
handled =true;
break;
}
return (System.IntPtr)0;
}
具體程式碼請看附件
最後是實現用滑鼠拖拽改變窗體大小
首先將封裝好的WindowResizer.dll檔案拷到工程目錄下,並在工程中新增對它的引用
然後在Windows1這個CustomWindow類的例項中繪製左右及底部5個拖拽熱區(矩形)
最後在Window1.xaml.cs中新增事件委託即可
程式碼 ///<summary>/// 載入Resize委託///</summary>publicvoid InitializeResizeHandle()
{
WindowResizer wr =new WindowResizer(this);
wr.addResizerRight(right);
wr.addResizerLeft(left);
wr.addResizerDown(bottom);
wr.addResizerLeftDown(leftbottom);
wr.addResizerRightDown(rightbottom);
//wr.addResizerUp(topSizeGrip);
//wr.addResizerLeftUp(topLeftSizeGrip);
//wr.addResizerRightUp(topRightSizeGrip);}
大功告成了!