Net平台在消息處理上的編程和Windows C++有很大的不同,Net對消息處理更加面向對象,但對於截獲某些Window消息的處理並不讓人很適應, 這裡根據我們遇到的一些需求寫了點東西供大家參考.
有這樣一個需求, 一個文本框, 用戶要求只能輸入數字, 不可以輸入字符, 但又不願意在保存的時候提醒, 而是直接讓字符輸不進來.
這時我們就要截獲字符輸入消息, 避免讓它顯示在文本框裡, 看下面的代碼:
public class MyTextBox:TextBox
{
private const int WM_CHAR=0x0102; //定義在WinUser.h中, 位於這個目錄:...\Vc7\PlatformSDK\Include
public override bool PreProcessMessage(ref Message msg)
{
if(msg.Msg==WM_CHAR)
{
Keys keyCode=(Keys)(int)msg.WParam & Keys.KeyCode;
if(keyCode<Keys.D0 || keyCode>Keys.D9)
if(keyCode!=Keys.Back && keyCode!=Keys.Delete)
return true; // 這行代碼可以截住輸入, 從而避免顯示
}
return base.PreProcessMessage (ref msg);
}
}
這裡講兩個方法:PreProcessMessage 和 WndProc. 它們都是Control的虛方法, 可以被覆蓋從而為我所用. 這兩個方法只對於本控件有效, 與別的控件, 無論是子控件還是父控件.統統無關. Net裡的消息如果當前控件不處理它, 它就被丟棄, 不會傳給父控件. 它不再沿用VC的消息機制, 這點要記住.
PreProcessMessage: Preprocesses input messages within the message loop before they are dispatched.
WndProc: Processes Windows messages.
我們可以看到, 這兩個方法的分工不同, 前一個是處理那些輸入消息,比如鍵盤上的輸入鍵. 後一個是處理單純的消息, 比如鼠標點擊,激活等.
這裡一個例子是截獲雙擊事件:
private const int WM_LBUTTONDBLCLK=0x0203;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_LBUTTONDBLCLK)
{
System.Diagnostics.Debug.WriteLine("wndproc");
return;
}
base.WndProc(ref m);
}
在這裡, 處理完事件後, 用return來截獲, 如果不加return這句代碼, 消息將會繼續得到處理, 如果你又定義了一個雙擊的事件處理方法後, 這個方法將被觸發:
private void textBox1_DoubleClick(object sender, System.EventArgs e)
{
System.Diagnostics.Debug.WriteLine("double click");
}
Net 裡的每個控件都定義了十分豐富的消息事件, 一般情況下都可以滿足你的需求, 所以WndProc重寫並不普遍.這一切由你來權衡, 有的人想把所有的消息處理放到一起, 用這種方式也未嘗不可.