[WPF] 自定义窗体样式
效果图如下:
Code: /Files/lovebread/CustomWindow.rar
实现思路:
1.继承Window类
2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!)
3.为窗体增加最大最小化和关闭按钮,并实现鼠标拖拽改变窗体大小(使用Derek Bartram的WindowResizer.dll库)
代码说明:
1.继承Window类
创建CustomWindow类,继承自System.Window

{
public CustomWindow()
{
// 加载样式
InitializeStyle();
// 加载事件委托
this .Loaded += delegate { InitializeEvent(); };
// 解决最大化覆盖任务栏问题
this .SourceInitialized += new EventHandler(win_SourceInitialized);
}
}

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文件:

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>
private void 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>
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 " )]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport( " User32 " )]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
...
private static System.IntPtr WindowProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0024 :
WmGetMinMaxInfo(hwnd, lParam);
handled = true ;
break ;
}
return (System.IntPtr) 0 ;
}
具体代码请看附件
最后是实现用鼠标拖拽改变窗体大小
这部分可以参考Derek Bartram的文章http://www.codeproject.com/KB/WPF/WPF_Window_Resizing.aspx
首先将封装好的WindowResizer.dll文件拷到工程目录下,并在工程中添加对它的引用
然后在Windows1这个CustomWindow类的实例中绘制左右及底部5个拖拽热区(矩形)
最后在Window1.xaml.cs中添加事件委托即可

/// 加载Resize委托
/// </summary>
public void 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);
}
大功告成了!