原文:WPF无边框捕获消息改变窗口大小

文章大部分转载自http://blog.csdn.net/fwj380891124,如有问题,请联系删除

 最近一直在学习 WPF,看着别人做的WPF程序那么漂亮,眼红啊~ 很多漂亮的程序都是无边框的。于是无边框窗口操作就是最重要的了。无边框窗口的操作一直以来相关的资料就很少。WPF 下的就更少了,有的大多是无边框窗体的移动。在得到群里高人的指点,再查了一些资料之后,终于把问题解决了。

      废话不多说,直接来看看如何实现吧!其实现原理很简单:拦截并处理 Windows 消息:WM_NCHITTEST。

      WPF 处理 Windows 消息的模式和 WinForm 不一样了。Window 类里没有 WndProc 函数了,想要截取 Windows 消息必须借助 HwndSource 添加 Hook。

  1. protected override void OnSourceInitialized(EventArgs e)  
  2. {  
  3.     base.OnSourceInitialized(e);  
  4.     HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;  
  5.     if (hwndSource != null)  
  6.     {  
  7.         hwndSource.AddHook(new HwndSourceHook(this.WndProc));  
  8.     }  
  9. }  
  10.   
  11. protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)  
  12. {  
  13.     return IntPtr.Zero;  
  14. }  

    OK,WndProc 注册完成之后就可以通过 WndProc 函数完成对Windows消息的处理了。可以发现,这里的 WndProc 和标准的 Win32 消息循环很像,只是多了一个 ref bool handled 参数,对于该参数MSDN是这样说明的:指示该消息是否已处理的值。如果该消息已处理,请将值设置为 true;否则请将其设置为 false。 在下面我们将会使用到这个参数数。

  1. private const int WM_NCHITTEST = 0x0084;  
  2. private readonly int agWidth = 12; //拐角宽度  
  3. private readonly int bThickness = 4; // 边框宽度  
  4. private Point mousePoint = new Point(); //鼠标坐标  
  5.    
  6. protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)  
  7. {  
  8.     switch (msg)  
  9.     {  
  10.         case WM_NCHITTEST:  
  11.         this.mousePoint.X = (lParam.ToInt32() &0xFFFF);  
  12.         this.mousePoint.Y = (lParam.ToInt32() >> 16);  
  13.   
  14.         测试鼠标位置#region 测试鼠标位置  
  15.   
  16.          // 窗口左上角  
  17.          if (this.mousePoint.Y - this.Top <= this.agWidth   
  18.             && this.mousePoint.X - this.Left <= this.agWidth)   
  19.         {  
  20.             handled = true;  
  21.             return new IntPtr((int)HitTest.HTTOPLEFT);  
  22.         }  
  23.         // 窗口左下角      
  24.          else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth   
  25.             && this.mousePoint.X - this.Left <= this.agWidth)  
  26.         {  
  27.             handled = true;  
  28.             return new IntPtr((int)HitTest.HTBOTTOMLEFT);  
  29.         }  
  30.         // 窗口右上角  
  31.          else if (this.mousePoint.Y - this.Top <= this.agWidth   
  32.             && this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth)  
  33.         {  
  34.             handled = true;  
  35.             return new IntPtr((int)HitTest.HTTOPRIGHT);  
  36.         }  
  37.         // 窗口右下角  
  38.          else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth   
  39.             && this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth)  
  40.         {  
  41.             handled = true;  
  42.             return new IntPtr((int)HitTest.HTBOTTOMRIGHT);  
  43.         }  
  44.         // 窗口左侧  
  45.          else if (this.mousePoint.X - this.Left <= this.bThickness)  
  46.         {  
  47.             handled = true;  
  48.             return new IntPtr((int)HitTest.HTLEFT);  
  49.         }  
  50.         // 窗口右侧  
  51.          else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.bThickness)  
  52.         {  
  53.             handled = true;  
  54.             return new IntPtr((int)HitTest.HTRIGHT);  
  55.         }  
  56.         // 窗口上方  
  57.          else if (this.mousePoint.Y - this.Top <= this.bThickness)  
  58.         {  
  59.             handled = true;  
  60.             return new IntPtr((int)HitTest.HTTOP);  
  61.         }  
  62.         // 窗口下方  
  63.          else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.bThickness)  
  64.         {  
  65.             handled = true;  
  66.             return new IntPtr((int)HitTest.HTBOTTOM);  
  67.         }  
  68.         else // 窗口移动  
  69.         {  
  70.             handled = true;  
  71.             return new IntPtr((int)HitTest.HTCAPTION);  
  72.         }  
  73.         #endregion  
  74.     }  
  75.     return IntPtr.Zero;  
  76. }  

     从上面的代码可以看出,工作原理很简单:截取 WM_NCHITTEST 消息,获得鼠标坐标,再在你希望的地方返回不同的消息以模拟鼠标的状态即可。需要注意的是,返回消息之前必须将handled 设为 true。告诉系统你已经处理过该消息,不然无效果。

    关于 HitTest 是自定义的枚举类,里面包含了鼠标的各种消息。

  1. 1public enum HitTest:int  
  2. {  
  3.     HTERROR = -2,  
  4.     HTTRANSPARENT = -1,  
  5.     HTNOWHERE = 0,  
  6.     HTCLIENT = 1,  
  7.     HTCAPTION = 2,  
  8.     HTSYSMENU = 3,  
  9.     HTGROWBOX = 4,  
  10.     HTSIZE = HTGROWBOX,  
  11.     HTMENU = 5,  
  12.     HTHSCROLL = 6,  
  13.     HTVSCROLL = 7,  
  14.     HTMINBUTTON = 8,  
  15.     HTMAXBUTTON = 9,  
  16.     HTLEFT = 10,  
  17.     HTRIGHT = 11,  
  18.     HTTOP = 12,  
  19.     HTTOPLEFT = 13,  
  20.     HTTOPRIGHT = 14,  
  21.     HTBOTTOM = 15,  
  22.     HTBOTTOMLEFT = 16,  
  23.     HTBOTTOMRIGHT = 17,  
  24.     HTBORDER = 18,  
  25.     HTREDUCE = HTMINBUTTON,  
  26.     HTZOOM = HTMAXBUTTON,  
  27.     HTSIZEFIRST = HTLEFT,  
  28.     HTSIZELAST = HTBOTTOMRIGHT,  
  29.     HTOBJECT = 19,  
  30.     HTCLOSE = 20,  
  31.     HTHELP = 21,  
  32. }  
  33.  HTBORDER 在不具有可变大小边框的窗口的边框上。 
    · HTBOTTOM 在窗口的水平边框的底部。 
    · HTBOTTOMLEFT 在窗口边框的左下角。  
    · HTBOTTOMRIGHT 在窗口边框的右下角。  
    · HTCAPTION 在标题条中。  
    · HTCLIENT 在客户区中。  
    · HTERROR 在屏幕背景或窗口之间的分隔线上(与HTNOWHERE相同,除了Windows的DefWndProc函数产生一个系统响声以指明错误)。  
    · HTGROWBOX 在尺寸框中。  
    · HTHSCROLL 在水平滚动条上。  
    · HTLEFT 在窗口的左边框上。  
    · HTMAXBUTTON 在最大化按钮上。  
    · HTMENU 在菜单区域。  
    · HTMINBUTTON 在最小化按钮上。  
    · HTNOWHERE 在屏幕背景或窗口之间的分隔线上。  
    · HTREDUCE 在最小化按钮上。  
    · HTRIGHT 在窗口的右边框上。  
    · HTSIZE 在尺寸框中。(与HTGROWBOX相同)  
    · HTSYSMENU 在控制菜单或子窗口的关闭按钮上。  
    · HTTOP 在窗口水平边框的上方。  
    · HTTOPLEFT 在窗口边框的左上角。  
    · HTTOPRIGHT 在窗口边框的右上角。  
    · HTTRANSPARENT 在一个被其它窗口覆盖的窗口中。  
    · HTVSCROLL 在垂直滚动条中。  
    · HTZOOM 在最大化按钮上。

WPF无边框捕获消息改变窗口大小的更多相关文章

  1. wpf无边框窗体移动和大小调整

    原文:wpf无边框窗体移动和大小调整   using System; using System.Windows; using System.Windows.Interop; namespace Wpf ...

  2. C# .net WPF无边框移动窗体

    转自 http://download.csdn.net/detail/xiang348352/3095084 WPF无边框移动窗体,先在<Window>里添加 MouseLeftButto ...

  3. WPF无边框拖动、全屏、缩放

    原文:WPF无边框拖动.全屏.缩放 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/lwwl12/article/details/78059361 先看效果 ...

  4. WPF无边框移动窗体

    WPF无边框移动窗体,先在<Window>里添加 MouseLeftButtonDown=”Window_MouseLeftButtonDown” 然后导航到事件,在事件里添加 if (e ...

  5. WPFの无边框窗体以及控件的移动

    对于WPF,一旦隐藏了标题栏,就无法移动,这时候需要重写移动方法,下面列举常见的三种方式方式. 方式一:重写OnMouseLeftButtonDown protected override void ...

  6. 【转载】 wpf无边框的方法以及拖拽的问题

    今天在做wpf程序的时候遇到了一个制作无边框的窗体并且有透明圆角的问题,我把解决的过程写下来,和大家学习 正常窗体必须把WindowStyle="None"这个属性加上去,但是加上 ...

  7. WPF 无边框透明按钮

    在实际开发过程中,有时候要设置一个无边框的按钮,或者无边框的透明按钮. 按钮效果如下: 1.当你应用telerik组件中的Button时,这个直接就可以设置 telerik:StyleManager. ...

  8. WPF 无边框拖动

    无边框之后的拖动方法有三种. 我个人是喜欢第一和第三的方法,看个人去需求. 第三种代码比较仓促,有需要者可以立马用,或者稍作整理修改. 对于WIN10 .NET 4.5以上的框架可以使用 WIndow ...

  9. C# WPF 无窗体传递消息

    WPF如果存在窗体(或至少,在任务栏有图标显示),互相传递消息是很容易的. 寻找目标窗体句柄->WindowsAPI SendMessage/PostMessage->目标窗体AddHoo ...

随机推荐

  1. POJ 3086 Triangular Sums (ZOJ 2773)

    http://poj.org/problem?id=3086 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1773 让你计算两 ...

  2. POJ 2823 Sliding Window 线段树

    http://poj.org/problem?id=2823 出太阳啦~^ ^被子拿去晒了~晚上还要数学建模,刚才躺在床上休息一下就睡着了,哼,还好我强大,没有感冒. 话说今年校运会怎么没下雨!!!说 ...

  3. HDoj-1163- Digital Roots

    Problem Description The digital root of a positive integer is found by summing the digits of the int ...

  4. python高级学习目录

    1. Linux介绍.命令1.1. 操作系统(科普章节) 1.2. 操作系统的发展史(科普章节) 1.3. 文件和目录 1.4. Ubuntu 图形界面入门 1.5. Linux 命令的基本使用 1. ...

  5. 【u245】机房病毒

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 我们机房中了病毒,因此几乎什么都无法正常进入.为了解决这个病毒,我们花了好几天.终于在大家的共同努力下 ...

  6. ArcEngine 数据导入经验(转载)

    转自原文ArcEngine 数据导入经验(转载) (一) GIS系统数据是基础,想必大家在做ArcEngine二次开发的过程中都会遇到向MDB和SDE写入数据的工作,我们将会通过几个篇幅,从大数据量导 ...

  7. listener监听器笔记

    listener:三个域对象的监听器,,还有属性的变化. 监听三个域对象的创建和销毁:servletContextListenerservletRequestListenerservletsessio ...

  8. Powerful Bash-style command line editing for cmd.exe

    https://mridgers.github.io/clink/ Clink Powerful Bash-style command line editing for cmd.exe Downloa ...

  9. adobe Changing PDF Link Color for Regulatory Submissions

    Changing PDF Link Color for Regulatory Submissions http://blogs.adobe.com/acrobatforlifesciences/200 ...

  10. [Typescript] Sorting arrays in TypeScript

    In this lesson we cover all the details of how to sort a list of items using TypeScript. We also pre ...