1. 程式人生 > >WM_NEXTDLGCTL message and OnKeyPress

WM_NEXTDLGCTL message and OnKeyPress

原文地址:http://blog.sina.com.cn/s/blog_47df3bea0101bddf.html
說明:原文是Delphi語言寫的,我這裡改成C++語言,意思不改變。

在MSDN:https://msdn.microsoft.com/en-us/library/ms645432(VS.85).aspx
Parameters
wParam
If lParam is TRUE, this parameter identifies the control that receives the focus. If lParam is FALSE, this parameter indicates whether the next or previous control with the WS_TABSTOP style receives the focus. If wParam is zero, the next control receives the focus; otherwise, the previous control with the WS_TABSTOP style receives the focus.
wParam
如果lParam為TRUE,則此引數表明獲得焦點的控制元件。 如果lParam為FALSE,則此引數指示具有WS_TABSTOP樣式的下一個或上一個控制元件是否獲得焦點。 如果wParam為零,則下一個控制元件獲得焦點; 其他情況,上一個擁有WS_TABSTOP風格的控制元件會收到焦點。

lParam
The low-order word indicates how the system uses wParam. If the low-order word is TRUE, wParam is a handle associated with the control that receives the focus; otherwise, wParam is a flag that indicates whether the next or previous control with the WS_TABSTOP style receives the focus.
lParam
低位字表示系統如何使用wParam。 如果低位字是TRUE,則wParam是一個與接收焦點的控制元件相關的控制代碼; 否則,wParam是一個標誌,它表示下一個或上一個WS_TABSTOP風格的控制元件是否接收到焦點。

Do not use the SendMessage function to send a WM_NEXTDLGCTL message if your application will concurrently process other messages that set the focus. Use the PostMessage function instead.
如果應用程式將同時處理其他設定焦點的訊息,則不要使用SendMessage函式傳送WM_NEXTDLGCTL訊息。 使用PostMessage函式。

好了,讓我們一起看一段程式碼:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
if(Key == 13){
Perform(WM_NEXTDLGCTL, 0, 0);
}
}
看程式碼時,看見最普通的一段程式碼,相信大家都看見過,但是大家對這段程式碼真正瞭解多少呢,現在詳細分析下。
1、TEdit的OnKeyPress事件:當按下鍵盤上一個ASCII碼鍵時將觸發該事件。注意:非ASCII碼鍵不能觸發該事件。

(哪些是非ASCII碼鍵,自己不是很瞭解,從網上找到一些內容。
http://ascii.911cha.com/
TEdit的OnKeyPress事件:當按下鍵盤上一個任何鍵時將觸發該事件。

2、通過一的內容知道,Enter鍵的ASCII碼為13。

3、Perform(WM_NEXTDLGCTL,0,0) 就是將焦點切換到下一個控制元件

上面的程式碼的意思就是你觸發Enter鍵或者Tab鍵時,焦點切換到下一個控制元件。
加入窗體上有很多控制元件,難道每個控制元件的OnKeyPress事件中都寫入此程式碼,那樣實在是太麻煩,現在又簡單的方法。(來源:http://blog.sina.com.cn/s/blog_4c0fc2c0010008y2.html
先將窗體的KeyPreview屬性設為True。然後在FormKeyPress事件中加入以下程式碼:

void __fastcall TForm1::FormKeyPress(TObject *Sender, System::WideChar &Key)
{
if(Key == 13)
{
Key = 0; //吃掉回車鍵
//方法1
PostMessageA(this->Handle,WM_NEXTDLGCTL,0,0);
//方法2
//Perform(WM_NEXTDLGCTL, 0, 0);
}
}
這個方法對於大多數控制元件都適用,但不適用於TButton控制元件,因為對於按鈕,回車鍵等於按下了按鈕,不觸發FormKeyPress事件。
方法確實已經非常簡單,但如果要在每一個視窗都重複寫以上內容,還是有些繁。怎樣將其改寫成一個自定義過程,然後在每一個視窗中呼叫此過程?
答:要改寫成一個自定義過程,可以這樣:
void __fastcall TForm1::MyKeyPress(TObject *Sender, System::WideChar &Key)
{
if(Key == 13)
{
Key = 0;
//方法1
PostMessageA(this->Handle,WM_NEXTDLGCTL,0,0);
//方法2
//Perform(WM_NEXTDLGCTL, 0, 0);
}
}
void __fastcall TForm1::FormKeyPress(TObject *Sender, System::WideChar &Key)
{
MyKeyPress(Sender,Key);
}
但是這樣還有有些控制元件不適用,具體訪問上面的網址,就不在此列出。

把焦點設給下一個控制元件,那如何把焦點設到上一個控制元件呢。
同樣也是先將窗體的KeyPreview屬性設為True。然後在FormKeyDown事件中加入以下程式碼:
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
if(Key == VK_UP)
{
Perform(WM_NEXTDLGCTL, 1, 0);
}
else if(Key == VK_DOWN)
{
Perform(WM_NEXTDLGCTL, 0, 0);
}
}