C#窗口过程消息处理WndProc

C# 窗口过程消息处理 WndProc

WinForm WndProc

在 WinForm 中一般采用重写 WndProc 的方法对窗口或控件接受到的指定消息进行处理

示例:禁止通过关闭按钮或其他发送 WM_CLOSE 消息的途径关闭窗口

protected override void WndProc(ref Message m)
{const int WM_CLOSE = 0x0010;if(m.Msg == WM_CLOSE){// MessageBox.Show("禁止关闭此窗口");return;}base.WndProc(ref m);
}

Control 类中还有个 DefWndProc 为默认的窗口过程

WPF HwndSource

WPF 仅本机窗口或 HwndHost 嵌入控件拥有句柄,可通过 HwndSource 添加消息处理

示例:禁止通过关闭按钮或其他发送 WM_CLOSE 消息的途径关闭窗口

HwndSource source = null;protected override void OnSourceInitialized(EventArgs e)
{base.OnSourceInitialized(e);IntPtr handle = new WindowInteropHelper(this).Handle;source = HwndSource.FromHandle(handle);source.AddHook(WndProc);
}protected override void OnClosed(EventArgs e)
{source?.RemoveHook(WndProc);base.OnClosed(e);
}private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{const int WM_CLOSE = 0x0010;if(msg == WM_CLOSE){// MessageBox.Show("禁止关闭此窗口");handled = true; // 标记为已处理}return IntPtr.Zero;
}

WinForm IMessageFilter

⚠ 注意:1.消息过滤器对于特定线程是唯一的;2.使用消息过滤器可能会降低程序性能

IMessageFilter 接口允许程序在将消息调度到控件或窗口之前捕获消息进行预处理

IMessageFilter 的 PreFilterMessage 与 Control 的 WndProc 接收到的消息是一个交集关系,应用程序接收到的消息来自系统消息队列,相对来说更全,但会有部分消息会直接发送到窗口或控件而不进入系统消息队列

实现 IMessageFilter 接口实例可对整个线程消息循环进行预处理,并根据 m.HWnd 获取消息传入的窗口或控件句柄

示例:截获程序鼠标悬浮消息,窗口标题显示当前悬浮控件名

static class Program
{[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);var filter = new SampleMsgFilter();Application.AddMessageFilter(filter); // 添加到消息泵Application.Run(new MainForm());Application.RemoveMessageFilter(filter); // 从消息泵移除}
}sealed class SampleMsgFilter : IMessageFilter
{public bool PreFilterMessage(ref Message m){const int WM_MOUSEHOVER = 0x02A1;if(m.Msg == WM_MOUSEHOVER && Control.FromHandle(m.HWnd) is Control ctr){ctr.FindForm().Text = ctr.Name;return true; // 过滤消息不继续派发}return false; // 允许消息派发到下一个过滤器或控件}
}

WinForm NativeWindow

NativeWindow 是 IWin32Window 的低级封装,并且和 WinForm Control 一样拥有 WndProc 和 DefWndProc 方法,故同样可通过重写 WndProc 方法处理消息

可以通过 CreateHandle(new CreateParams()) 创建没有 UI 的仅消息循环的窗口。比如托盘图标类 NotifyIcon 内部会创建一个 NativeWindow 用来接收任务栏创建消息 WM_TASKBARCREATED ("TaskbarCreated"),在资源管理器崩溃重启后重新创建图标。

附加到其他窗口

由于 WinForm Control WndProc 是密封的,处理消息时必须继承类型并重写,需要单独进行消息处理的窗口或控件较多时,对原代码具有很大的侵入性;而 IMessageFilter 是针对整个应用程序的消息循环,官方文档说使用消息过滤器很可能会降低程序性能;相对来说,由于 HwndSource AddHook 和 RemoveHook 不是密封的,WPF 程序可以在不侵入原代码的条件下处理窗口消息,在可复用性上面反而还具有优势。但如果仔细看看 NativeWindow 源代码,会发现它内部调用了 SetWindowLong GWL_WNDPROC (窗口子类化),可以通过 AssignHandle 附加到任意窗口或控件进行消息处理,这个窗口不限制类型,甚至可以附加到其他程序窗口。

这里提供一个静态辅助类,借助 NativeWindow 简化附加窗口消息过程处理操作:

using System;
using System.Collections.Generic;
using System.Windows.Forms;namespace Wondershare.WinTool.Helpers
{public delegate bool HookProc(ref Message m);public static class MessageHooker{sealed class HookWindow : NativeWindow{List<KeyValuePair<HookProc, Action>> hooks;public HookWindow(IntPtr hWnd){AssignHandle(hWnd);}public void AddHookProc(HookProc hook, Action removedHandler){if (hooks == null){hooks = new List<KeyValuePair<HookProc, Action>>();}hooks.Insert(0, new KeyValuePair<HookProc, Action>(hook, removedHandler));}public void RemoveHookProc(HookProc hook){if (hooks != null){for (int i = hooks.Count - 1; i >= 0; i--){if (hooks[i].Key == hook){hooks[i].Value?.Invoke();hooks.RemoveAt(i);}}}}protected override void WndProc(ref Message m){if (hooks != null){foreach (var hook in hooks){if (hook.Key(ref m)) return;}const int WM_NCDESTORY = 0x0082;if (m.Msg == WM_NCDESTROY) // 窗口销毁时移除所有 hook{for (int i = hooks.Count - 1; i >= 0; i--){hooks[i].Value?.Invoke();}hooks = null;}base.WndProc(ref m);}}}/// <summary>附加消息处理过程到窗口</summary>/// <param name="handle">需要附加消息处理过程的窗口句柄</param>/// <param name="hook">消息处理过程</param>/// <param name="removedHandler">消息处理过程移除回调</param>public static void AddHook(IntPtr handle, HookProc hook, Action removedHandler = null){if (!(NativeWindow.FromHandle(handle) is HookWindow window)){window = new HookWindow(handle);}window.AddHookProc(hook, removedHandler);}/// <summary>从窗口移除附加的消息处理过程</summary>/// <param name="handle">需要移除消息处理过程的窗口句柄</param>/// <param name="hook">消息处理过程</param>public static void RemoveHook(IntPtr handle, HookProc hook){if (NativeWindow.FromHandle(handle) is HookWindow window){window.RemoveHookProc(hook);}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/909366.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

必看!Spring Boot 项目新老版本 Controller 低侵入式切换实战秘籍

在当今快速迭代的软件开发环境中,项目的迁移重构是许多开发团队都绕不开的工作。最近,业务方的一个项目就面临着这样的挑战,而在迁移重构的过程中,如何确保下游系统对接无感知成为了重中之重。具体来说,他们需要实现这样一个需求:读请求访问老版本 Controller 时,能够无…

第6章 异步原理

第6章 异步原理 6.1 生成代码的结构 异步模式的实现原理是基于 状态机 的,它负责追踪 async 方法当前的执行进度。从逻辑上讲,可以分为以下 4 种状态:未启动 正在执行 暂停 完成(成功或 faulted)Eureka 这里的“暂停”,指程序运行至 await 处,任务未完成时,当前方法在此…

用Arduino开发STM32

参考文档: https://blog.csdn.net/weixin_42880082/article/details/121619101 qq:505645074

【重点】文件摆渡系统如何简化跨平台跨网络的文件传输?

在当今数字化时代,企业数据的流动性和安全性变得愈发重要。随着业务规模的扩大和全球化协作的深入,跨平台、跨网络的文件传输需求日益增长。然而,传统的文件传输方式往往面临效率低下、安全性不足、兼容性差等问题。文件摆渡系统作为一种专门设计用于简化跨平台、跨网络文件…

想让你多爱自己一些的开源计时器

我用过 Pomotroid、Reminders MenuBar、Timer 等众多优秀、开源的番茄时钟和计时工具,它们帮我更高效地管理时间,让我更专注地投入工作。 但有一个问题始终困扰着我:每当计时结束时,我总是习惯性地忽略休息提醒,继续沉浸在手头的事情中,直到第二天身体不适才追悔莫及。 最…

VMware ESXi 8.0U3d macOS Unlocker OEM BIOS 标准版和厂商定制版,已适配主流品牌服务器

VMware ESXi 8.0U3d macOS Unlocker & OEM BIOS 标准版和厂商定制版,已适配主流品牌服务器VMware ESXi 8.0U3d macOS Unlocker & OEM BIOS 标准版和厂商定制版 ESXi 8.0U3d 标准版,Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科)、Hitachi (日…

AMS1117-LDO(线性稳压器)稳压电路

AMS1117-LDO(线性稳压器)稳压电路 原理图引脚说明编号 名称 功能描述1 GND GND2 VOUT 输出3 VIN 输入4 VOUT 输出拓展C8和C7为输出滤波电容,用于抑制自激振荡。如果这两个电容不接,线性稳压器的输出通常会是一个振荡波形。 电容C5和C6是输入电容。对于交流电压整流输入,它…

Avalonia 界面效果 滚动的渐变矩形边框

本文将和大家介绍一个 Avalonia 界面效果,制作一个滚动的渐变矩形边框本文代码基于 Avalonia 11.2.x 版本实现,预期在其他 Avalonia 版本也能正常使用 本文效果由 晓嗔戈 提供,我只是记录此实现方法的工具人 界面效果如下图所示,录制的gif中颜色存在一些偏差,动画有些卡顿…

Avalonia 界面效果 三个圆实现模糊界面动效背景

本文将和大家介绍一个 Avalonia 动效界面效果,由三个圆带模糊效果实现的模糊界面动效背景,适合用在各种 AIGC 主题的应用里面本文代码基于 Avalonia 11.2.x 版本实现,预期在其他 Avalonia 版本也能正常使用 本文效果由 晓嗔戈 提供,我只是记录此实现方法的工具人 界面效果如…

儿子的画

昨天儿子在幼儿园学习了自制小册子,并在上面画画。 晚上睡觉前,心血来潮想要再展示一下他在学校是怎么弄的,于是又一顿操作起来,动作还算麻利,只是完成之后都已过十点了,非要我们帮他配上文字,我一开始不明就理,以为写个标题就好了..., 但最后终于搞懂他是要我帮忙下一…

团队协作管理:贝尔宾团队角色模型学习

“没有完美的个人,只有完美的团队。” 任何企业的领导者要想使自己的企业能够快速地发展和成长,就必须对团队建设的重要性有正确的认识。团队角色理论 团队角色理论是管理学中用于分析和优化团队协作的重要理论,可以帮助管理者认识人才、选拔人才,组建高效率合作团队。也可…

钉钉 + AI 网关给 DeepSeek 办入职

通过 Open-WebUI 在企业内部部署一套 DeepSeek 只是第一步,给 DeepSeek 办理入职,在钉钉等企业通讯工具上和 DeepSeek 对话才是真时尚。通过 Open-WebUI 在企业内部部署一套 DeepSeek 只是第一步,给 DeepSeek 办理入职,在钉钉等企业通讯工具上和 DeepSeek 对话才是真时尚。…