1. 程式人生 > >[WPF] 自定義窗體樣式

[WPF] 自定義窗體樣式

效果圖如下:

 

實現思路:

1.繼承Window類

2.為自定義的CustomWindow類設計窗體樣式(使用Blend很方便!)

3.為窗體增加最大最小化和關閉按鈕,並實現滑鼠拖拽改變窗體大小(使用的WindowResizer.dll庫)

程式碼說明:

1.繼承Window類

建立CustomWindow類,繼承自System.Window

程式碼 publicclass CustomWindow : Window
{
    
public CustomWindow()
    {
        
// 載入樣式        InitializeStyle(); 

        
// 載入事件委託
this.Loaded +=delegate { InitializeEvent(); };

        
// 解決最大化覆蓋工作列問題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);}

 大功告成了!