LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C# 窗口过程消息处理 WndProc

freeflydom
2025年4月7日 16:50 本文热度 82

在 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);

           }

       }

   }

}

该文章在 2025/4/7 16:51:04 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved