前言
在C# 中,WndProc 是一個用於處理 Windows 消息的函數,通常在創建自定義控件或重寫窗口行為時使用。
它是 Windows 消息循環的核心部分之一。
- WndProc 是 Window Procedure(視窗處理函數)的縮寫。
- 它是 Windows 系統用來 傳遞和處理視窗訊息(Messages)的主要機制。
- 每個視窗(或控制項)都可以有一個視窗過程,用來接收並處理如滑鼠點擊、鍵盤按鍵、繪圖等事件
下面會有幾個繼承自 Form 或 Control 的Class中重寫 WndProc 的方法
1. 攔截關閉訊息 (WM_CLOSE)
| protected override void WndProc(ref Message m) |
| { |
| const int WM_CLOSE = 0x0010; |
| |
| if (m.Msg == WM_CLOSE) |
| { |
| DialogResult result = MessageBox.Show("確定要關閉應用程式嗎?", "提示", MessageBoxButtons.YesNo); |
| if (result == DialogResult.No) |
| return; |
| } |
| |
| base.WndProc(ref m); |
| } |
2. 禁用最大化按鈕 (WM_SYSCOMMAND)
| protected override void WndProc(ref Message m) |
| { |
| const int WM_SYSCOMMAND = 0x0112; |
| const int SC_MAXIMIZE = 0xF030; |
| |
| if (m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MAXIMIZE) |
| { |
| |
| return; |
| } |
| |
| base.WndProc(ref m); |
| } |
3. 處理熱鍵 (WM_HOTKEY)
| [DllImport("user32.dll")] |
| private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk); |
| |
| protected override void OnHandleCreated(EventArgs e) |
| { |
| base.OnHandleCreated(e); |
| RegisterHotKey(this.Handle, 1, 0x0002, (int)Keys.F12); |
| } |
| |
| protected override void WndProc(ref Message m) |
| { |
| const int WM_HOTKEY = 0x0312; |
| |
| if (m.Msg == WM_HOTKEY) |
| { |
| int id = m.WParam.ToInt32(); |
| if (id == 1) |
| { |
| MessageBox.Show("熱鍵 Ctrl+F12 被觸發!"); |
| } |
| } |
| |
| base.WndProc(ref m); |
| } |
4. 攔截鼠標右鍵 (WM_RBUTTONDOWN)
| protected override void WndProc(ref Message m) |
| { |
| const int WM_RBUTTONDOWN = 0x0204; |
| |
| if (m.Msg == WM_RBUTTONDOWN) |
| { |
| MessageBox.Show("右鍵點擊被攔截!"); |
| return; |
| } |
| |
| base.WndProc(ref m); |
| } |
5. 攔截鍵盤輸入 (WM_KEYDOWN)
| protected override void WndProc(ref Message m) |
| { |
| const int WM_KEYDOWN = 0x0100; |
| |
| if (m.Msg == WM_KEYDOWN) |
| { |
| Keys key = (Keys)m.WParam.ToInt32(); |
| if (key == Keys.Escape) |
| { |
| MessageBox.Show("你按下了 ESC 鍵!"); |
| return; |
| } |
| } |
| |
| base.WndProc(ref m); |
| } |
6. 顯示滑鼠移動位置 (WM_MOUSEMOVE)
| using System; |
| using System.Windows.Forms; |
| using System.Runtime.InteropServices; |
| |
| public class MouseMoveForm : Form |
| { |
| private const int WM_MOUSEMOVE = 0x0200; |
| |
| protected override void WndProc(ref Message m) |
| { |
| if (m.Msg == WM_MOUSEMOVE) |
| { |
| |
| int x = m.LParam.ToInt32() & 0xFFFF; |
| int y = (m.LParam.ToInt32() >> 16) & 0xFFFF; |
| |
| this.Text = $"Mouse Position: ({x}, {y})"; |
| } |
| |
| base.WndProc(ref m); |
| } |
| } |
- WM_MOUSEMOVE:當滑鼠在視窗上移動時會觸發。
- LParam:包含滑鼠座標,低 16 位是 X,高 16 位是 Y。
- this.Text:即視窗的標題,我們用它即時顯示滑鼠座標。
- 建議總是呼叫 base.WndProc(ref m); 以保證其他消息能正常處理。
- 大部分WM_* 常量可以在 WinUser.h 裡查到
WinUser.h(Windows SDK)
這個檔案是 Windows SDK 中的一部分,通常會隨著 Visual Studio 安裝或 Windows 開發環境提供。
- 檔案位置
C:\Program Files (x86)\Windows Kits\10\Include\<SDK 版本號>\um\WinUser.h
| #define WM_PAINT 0x000F |
| #define WM_KEYDOWN 0x0100 |
| #define WM_MOUSEMOVE 0x0200 |
在 C# 裡你不能直接使用這些 C 巨集(宏),但可以自己定義這些常數:
| private const int WM_PAINT = 0x000F; |
| private const int WM_KEYDOWN = 0x0100; |
| private const int WM_MOUSEMOVE = 0x0200; |
留言
張貼留言