WPF设计の自定义窗体

简介: 原文:WPF设计の自定义窗体  效果图如下:     实现思路:  1.继承Window类 2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!) 3.为窗体增加最大最小化和关闭按钮,并实现鼠标拖拽改变窗体大小(使用Derek Bartram的WindowResizer.
原文: WPF设计の自定义窗体

 

效果图如下:

 

 

实现思路: 

1.继承Window类

2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!)

3.为窗体增加最大最小化和关闭按钮,并实现鼠标拖拽改变窗体大小(使用Derek Bartram的WindowResizer.dll库) 

 

代码说明:

1.继承Window类

创建CustomWindow类,继承自System.Window 

代码
public class 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>
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>
/// 重绘窗体大小
/// </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;
}

 

最后是实现用鼠标拖拽改变窗体大小

然后在Windows1这个CustomWindow类的实例中绘制左右及底部5个拖拽热区(矩形)

 

最后在Window1.xaml.cs中添加事件委托即可 

代码
/// <summary>
/// 加载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);
}

 

 大功告成了!

 

目录
相关文章
|
C# 虚拟化 索引
【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
原文:【WPF】UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而ListBox又定义了两种样式的ItemsPanelTemplate。
2045 0
|
C# 数据安全/隐私保护
【WPF】右下角弹出自定义通知样式(Notification)——简单教程
原文:【WPF】右下角弹出自定义通知样式(Notification)——简单教程 1.先看效果 2.实现 1.主界面是MainWindow 上面就只摆放一个Button即可。
2835 0
|
10月前
|
C#
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
185 0
|
10月前
|
C# 容器
WPF框架下,窗体的嵌套显示
WPF框架下,窗体的嵌套显示
179 0
|
前端开发 C# 图形学
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了。用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架。依赖属性(DependencyProperty)是为用户控件提供可支持双向绑定的必备技巧之一,同样用处也非常广泛。
801 0
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
|
C#
WPF 控件自定义背景
<!--控件要设置尺寸的话,设置的尺寸必须比下面的图形的尺寸要小,不然显示不开--> <Label Content="直角测试" Width="90" Height="90" HorizontalContentAlignment="Center" Vert...
988 0
|
C#
WPF开发-Label自定义背景-Decorator
首先在App.xaml文件当中添加样式和模板
1967 0
|
C#
wpf 开发 -TextBox背景自定义-Decorator
首先在app.xaml文件的下面添加以下样式
1639 0
|
.NET C# Windows
WPF 自定义路由事件
原文:WPF 自定义路由事件 WPF中的路由事件 as U know,和以前Windows消息事件区别不再多讲,这篇博文中,将首先回顾下WPF内置的路由事件的用法,然后在此基础上自定义一个路由事件。 1.WPF内置路由事件   WPF中的大多数事件都是路由事件,WPF有3中路由策略: 具体不多讲,单需要注意的是WPF路由事件是沿着VIsualTree传递的。
1112 0
|
C# 前端开发
【C#】wpf自定义calendar日期选择控件的样式
原文:【C#】wpf自定义calendar日期选择控件的样式 首先上图看下样式 原理 总览 ItemsControl内容的生成 实现 界面的实现 后台ViewModel的实现 首先上图,看下样式 原理 1. 总览: Calendar本质上是一个6x7的列表,这个列表可以用ItemsControl来实现。
1091 0