WPF无边框捕获消息改变窗口大小
文章大部分转载自http://blog.csdn.net/fwj380891124,如有问题,请联系删除
最近一直在学习 WPF,看着别人做的WPF程序那么漂亮,眼红啊~ 很多漂亮的程序都是无边框的。于是无边框窗口操作就是最重要的了。无边框窗口的操作一直以来相关的资料就很少。WPF 下的就更少了,有的大多是无边框窗体的移动。在得到群里高人的指点,再查了一些资料之后,终于把问题解决了。
废话不多说,直接来看看如何实现吧!其实现原理很简单:拦截并处理 Windows 消息:WM_NCHITTEST。
WPF 处理 Windows 消息的模式和 WinForm 不一样了。Window 类里没有 WndProc 函数了,想要截取 Windows 消息必须借助 HwndSource 添加 Hook。
- protected override void OnSourceInitialized(EventArgs e)
- {
- base.OnSourceInitialized(e);
- HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
- if (hwndSource != null)
- {
- hwndSource.AddHook(new HwndSourceHook(this.WndProc));
- }
- }
- protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- {
- return IntPtr.Zero;
- }
OK,WndProc 注册完成之后就可以通过 WndProc 函数完成对Windows消息的处理了。可以发现,这里的 WndProc 和标准的 Win32 消息循环很像,只是多了一个 ref bool handled 参数,对于该参数MSDN是这样说明的:指示该消息是否已处理的值。如果该消息已处理,请将值设置为 true;否则请将其设置为 false。 在下面我们将会使用到这个参数数。
- private const int WM_NCHITTEST = 0x0084;
- private readonly int agWidth = 12; //拐角宽度
- private readonly int bThickness = 4; // 边框宽度
- private Point mousePoint = new Point(); //鼠标坐标
- protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- {
- switch (msg)
- {
- case WM_NCHITTEST:
- this.mousePoint.X = (lParam.ToInt32() &0xFFFF);
- this.mousePoint.Y = (lParam.ToInt32() >> 16);
- 测试鼠标位置#region 测试鼠标位置
- // 窗口左上角
- if (this.mousePoint.Y - this.Top <= this.agWidth
- && this.mousePoint.X - this.Left <= this.agWidth)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTTOPLEFT);
- }
- // 窗口左下角
- else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth
- && this.mousePoint.X - this.Left <= this.agWidth)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTBOTTOMLEFT);
- }
- // 窗口右上角
- else if (this.mousePoint.Y - this.Top <= this.agWidth
- && this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTTOPRIGHT);
- }
- // 窗口右下角
- else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth
- && this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTBOTTOMRIGHT);
- }
- // 窗口左侧
- else if (this.mousePoint.X - this.Left <= this.bThickness)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTLEFT);
- }
- // 窗口右侧
- else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.bThickness)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTRIGHT);
- }
- // 窗口上方
- else if (this.mousePoint.Y - this.Top <= this.bThickness)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTTOP);
- }
- // 窗口下方
- else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.bThickness)
- {
- handled = true;
- return new IntPtr((int)HitTest.HTBOTTOM);
- }
- else // 窗口移动
- {
- handled = true;
- return new IntPtr((int)HitTest.HTCAPTION);
- }
- #endregion
- }
- return IntPtr.Zero;
- }
从上面的代码可以看出,工作原理很简单:截取 WM_NCHITTEST 消息,获得鼠标坐标,再在你希望的地方返回不同的消息以模拟鼠标的状态即可。需要注意的是,返回消息之前必须将handled 设为 true。告诉系统你已经处理过该消息,不然无效果。
关于 HitTest 是自定义的枚举类,里面包含了鼠标的各种消息。
- 1public enum HitTest:int
- {
- HTERROR = -2,
- HTTRANSPARENT = -1,
- HTNOWHERE = 0,
- HTCLIENT = 1,
- HTCAPTION = 2,
- HTSYSMENU = 3,
- HTGROWBOX = 4,
- HTSIZE = HTGROWBOX,
- HTMENU = 5,
- HTHSCROLL = 6,
- HTVSCROLL = 7,
- HTMINBUTTON = 8,
- HTMAXBUTTON = 9,
- HTLEFT = 10,
- HTRIGHT = 11,
- HTTOP = 12,
- HTTOPLEFT = 13,
- HTTOPRIGHT = 14,
- HTBOTTOM = 15,
- HTBOTTOMLEFT = 16,
- HTBOTTOMRIGHT = 17,
- HTBORDER = 18,
- HTREDUCE = HTMINBUTTON,
- HTZOOM = HTMAXBUTTON,
- HTSIZEFIRST = HTLEFT,
- HTSIZELAST = HTBOTTOMRIGHT,
- HTOBJECT = 19,
- HTCLOSE = 20,
- HTHELP = 21,
- }
- 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无边框捕获消息改变窗口大小的更多相关文章
- wpf无边框窗体移动和大小调整
原文:wpf无边框窗体移动和大小调整 using System; using System.Windows; using System.Windows.Interop; namespace Wpf ...
- C# .net WPF无边框移动窗体
转自 http://download.csdn.net/detail/xiang348352/3095084 WPF无边框移动窗体,先在<Window>里添加 MouseLeftButto ...
- WPF无边框拖动、全屏、缩放
原文:WPF无边框拖动.全屏.缩放 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/lwwl12/article/details/78059361 先看效果 ...
- WPF无边框移动窗体
WPF无边框移动窗体,先在<Window>里添加 MouseLeftButtonDown=”Window_MouseLeftButtonDown” 然后导航到事件,在事件里添加 if (e ...
- WPFの无边框窗体以及控件的移动
对于WPF,一旦隐藏了标题栏,就无法移动,这时候需要重写移动方法,下面列举常见的三种方式方式. 方式一:重写OnMouseLeftButtonDown protected override void ...
- 【转载】 wpf无边框的方法以及拖拽的问题
今天在做wpf程序的时候遇到了一个制作无边框的窗体并且有透明圆角的问题,我把解决的过程写下来,和大家学习 正常窗体必须把WindowStyle="None"这个属性加上去,但是加上 ...
- WPF 无边框透明按钮
在实际开发过程中,有时候要设置一个无边框的按钮,或者无边框的透明按钮. 按钮效果如下: 1.当你应用telerik组件中的Button时,这个直接就可以设置 telerik:StyleManager. ...
- WPF 无边框拖动
无边框之后的拖动方法有三种. 我个人是喜欢第一和第三的方法,看个人去需求. 第三种代码比较仓促,有需要者可以立马用,或者稍作整理修改. 对于WIN10 .NET 4.5以上的框架可以使用 WIndow ...
- C# WPF 无窗体传递消息
WPF如果存在窗体(或至少,在任务栏有图标显示),互相传递消息是很容易的. 寻找目标窗体句柄->WindowsAPI SendMessage/PostMessage->目标窗体AddHoo ...
随机推荐
- Java文档上传问题设计
近期公司让做一个文档上传的功能,功能描写叙述大概是这样子滴 书籍名称.书籍定价.书籍封面图片(须要上传).文档内容 (须要上传) .还有其它相关的描写叙述信息. 我的设计 表 A 包括以上字段 , ...
- php面试题四
php面试题四 一.总结 二.php面试题四 01. 输出为 Mozilla/4.0(compatible;MSIE5.01;Window NT 5.0)时,可能的输出语句是: A.$_S ...
- 【t035】收入计划
Time Limit: 1 second Memory Limit: 32 MB [问题描述] 高考结束后,同学们大都找到了一份临时工作,渴望挣得一些零用钱.从今天起,Matrix67将连续工作N天( ...
- 二:新浪微博:第三方框架管理工具CocoaPods的安装和使用
一:CocoaPods的安装 我们可以用淘宝的Ruby镜像来访问cocoapods.按照下面的顺序在终端中敲入依次敲入 $ gem sources --remove https://rubygems. ...
- js获取浏览器尺寸
Javascript: alert(document.body.clientWidth); //网页可见区域宽(body) alert(document.body.clientHeigh ...
- Linux命令具体解释(2) – mv
文件位置: mv: /bin/mv /usr/share/man/man1/mv.1.gz 名称: mv - move (rename) files 使用方法: mv [ ...
- 《高性能MySQL》--复制笔记
复制解决的问题 1,数据分布 MySQL复制通常不会对带宽造成很大的压力,但在5.1版本引入的基于行的复制会比传统的基于语句的复制模式的带宽压力更大.你可以随意地停止或开始复制,并在不同的地理位置来分 ...
- Git恢复删除或修改的文件 ls-files
一.git ls-files -d 查看删除了的文件 1.查看当前状态可以看到删除了一个index.js: git status image.png 2.查看当前项目中删除了的文件 git ls-fi ...
- CSU1323: ZZY and his little friends
Description zzy养了一只小怪兽和N只凹凸曼,单挑的话每只凹凸曼都不是小怪兽的对手,所以必须由两只凹凸曼合作来和小怪兽战斗.凹凸曼A和凹凸曼B合作的战斗力为他们战斗力的异或值.现在由zzy ...
- 再续FPGA初心,京微齐力脱胎京微雅格重新起航(700万元天使轮,泰有基金领投,水木基金、臻云创投、泰科源跟投。数千万元Pre-A轮融资,领投方为海康基金)
集微网消息,新的一年开启新的希望,新的空白承载新的梦想.这是年初一集微网给读者们拜年时写的寄语.在中国农历新年开年之际,半导体产业里也迎来了许多新的起点.例如长江存储在与苹果就采购前者的Nand闪存芯 ...