zoukankan      html  css  js  c++  java
  • 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);
    }

     大功告成了!

     

  • 相关阅读:
    Texture转Texture2D
    虚拟化 -- kvm简介
    虚拟化
    数据库
    openstack共享组件(1)------ NTP 时间同步服务
    openstack
    Linux基础命令
    第七章 Python文件操作
    第六章 Python流程控制
    老吴Python宝典之——Python字典&集合(第五章 )
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/7641666.html
Copyright © 2011-2022 走看看