最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#?窗口過(guò)程消息處理?WndProc的方法詳解

 更新時(shí)間:2025年04月02日 08:53:22   作者:藍(lán)點(diǎn)lilac  
在WinForm中一般采用重寫WndProc的方法對(duì)窗口或控件接受到的指定消息進(jìn)行處理,本文給大家介紹C#窗口過(guò)程消息處理WndProc的方法詳解,感興趣的朋友一起看看吧

WinForm WndProc

在 WinForm 中一般采用重寫 WndProc 的方法對(duì)窗口或控件接受到的指定消息進(jìn)行處理

示例:禁止通過(guò)關(guān)閉按鈕或其他發(fā)送 WM_CLOSE 消息的途徑關(guān)閉窗口

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

Control 類中還有個(gè) DefWndProc 為默認(rèn)的窗口過(guò)程

WPF HwndSource

WPF 僅本機(jī)窗口或 HwndHost 嵌入控件擁有句柄,可通過(guò) HwndSource 添加消息處理

示例:禁止通過(guò)關(guān)閉按鈕或其他發(fā)送 WM_CLOSE 消息的途徑關(guān)閉窗口

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("禁止關(guān)閉此窗口");
        handled = true; // 標(biāo)記為已處理
    }
    return IntPtr.Zero;
}

WinForm IMessageFilter

? 注意:1.消息過(guò)濾器對(duì)于特定線程是唯一的;2.使用消息過(guò)濾器可能會(huì)降低程序性能

IMessageFilter 接口允許程序在將消息調(diào)度到控件或窗口之前捕獲消息進(jìn)行預(yù)處理

IMessageFilter 的 PreFilterMessage 與 Control 的 WndProc 接收到的消息是一個(gè)交集關(guān)系,應(yīng)用程序接收到的消息來(lái)自系統(tǒng)消息隊(duì)列,相對(duì)來(lái)說(shuō)更全,但會(huì)有部分消息會(huì)直接發(fā)送到窗口或控件而不進(jìn)入系統(tǒng)消息隊(duì)列

實(shí)現(xiàn) IMessageFilter 接口實(shí)例可對(duì)整個(gè)線程消息循環(huán)進(jìn)行預(yù)處理,并根據(jù) m.HWnd 獲取消息傳入的窗口或控件句柄

示例:截獲程序鼠標(biāo)懸浮消息,窗口標(biāo)題顯示當(dāng)前懸浮控件名

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; // 過(guò)濾消息不繼續(xù)派發(fā)
        }
        return false; // 允許消息派發(fā)到下一個(gè)過(guò)濾器或控件
    }
}

WinForm NativeWindow

NativeWindow 是 IWin32Window 的低級(jí)封裝,并且和 WinForm Control 一樣擁有 WndProc 和 DefWndProc 方法,故同樣可通過(guò)重寫 WndProc 方法處理消息

可以通過(guò) CreateHandle(new CreateParams()) 創(chuàng)建沒(méi)有 UI 的僅消息循環(huán)的窗口。比如托盤圖標(biāo)類 NotifyIcon 內(nèi)部會(huì)創(chuàng)建一個(gè) NativeWindow 用來(lái)接收任務(wù)欄創(chuàng)建消息 WM_TASKBARCREATED ("TaskbarCreated"),在資源管理器崩潰重啟后重新創(chuàng)建圖標(biāo)。

附加到其他窗口

由于 WinForm Control WndProc 是密封的,處理消息時(shí)必須繼承類型并重寫,需要單獨(dú)進(jìn)行消息處理的窗口或控件較多時(shí),對(duì)原代碼具有很大的侵入性;而 IMessageFilter 是針對(duì)整個(gè)應(yīng)用程序的消息循環(huán),官方文檔說(shuō)使用消息過(guò)濾器很可能會(huì)降低程序性能;相對(duì)來(lái)說(shuō),由于 HwndSource AddHook 和 RemoveHook 不是密封的,WPF 程序可以在不侵入原代碼的條件下處理窗口消息,在可復(fù)用性上面反而還具有優(yōu)勢(shì)。但如果仔細(xì)看看 NativeWindow 源代碼,會(huì)發(fā)現(xiàn)它內(nèi)部調(diào)用了 SetWindowLong GWL_WNDPROC (窗口子類化),可以通過(guò) AssignHandle 附加到任意窗口或控件進(jìn)行消息處理,這個(gè)窗口不限制類型,甚至可以附加到其他程序窗口。

這里提供一個(gè)靜態(tài)輔助類,借助 NativeWindow 簡(jiǎn)化附加窗口消息過(guò)程處理操作:

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) // 窗口銷毀時(shí)移除所有 hook
                    {
                        for (int i = hooks.Count - 1; i >= 0; i--)
                        {
                            hooks[i].Value?.Invoke();
                        }
                        hooks = null;
                    }
                    base.WndProc(ref m);
                }
            }
        }
        /// <summary>附加消息處理過(guò)程到窗口</summary>
        /// <param name="handle">需要附加消息處理過(guò)程的窗口句柄</param>
        /// <param name="hook">消息處理過(guò)程</param>
        /// <param name="removedHandler">消息處理過(guò)程移除回調(diào)</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>從窗口移除附加的消息處理過(guò)程</summary>
        /// <param name="handle">需要移除消息處理過(guò)程的窗口句柄</param>
        /// <param name="hook">消息處理過(guò)程</param>
        public static void RemoveHook(IntPtr handle, HookProc hook)
        {
            if (NativeWindow.FromHandle(handle) is HookWindow window)
            {
                window.RemoveHookProc(hook);
            }
        }
    }
}

到此這篇關(guān)于C# 窗口過(guò)程消息處理 WndProc的方法詳解的文章就介紹到這了,更多相關(guān)C# 消息處理 WndProc內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

九江市| 汤原县| 柏乡县| 白水县| 石泉县| 乳源| 报价| 双柏县| 宿迁市| 盘锦市| 永定县| 吕梁市| 且末县| 长寿区| 昂仁县| 临潭县| 眉山市| 宿迁市| 剑河县| 安泽县| 达州市| 体育| 卢氏县| 翁牛特旗| 大兴区| 遂昌县| 榆林市| 仙游县| 花莲县| 乐业县| 延川县| 南投县| 巴青县| 扎鲁特旗| 方城县| 志丹县| 高唐县| 曲麻莱县| 治县。| 垦利县| 社旗县|