轉(zhuǎn)帖|其它|編輯:郝浩|2010-12-01 16:05:21.000|閱讀 665 次
概述:本問(wèn)主要介紹如何讓ToolBox控件響應(yīng)鍵盤(pán)操作,希望對(duì)大家有幫助。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門(mén)軟控件火熱銷(xiāo)售中 >>
最近,一朋友問(wèn)我如何讓ToolBox控件也能響應(yīng)鍵盤(pán)操作,也就是用Up,down按鍵來(lái)選擇工具箱控件里的Item,他添加了鍵盤(pán)事件,但是不起作用。一開(kāi)始做這個(gè)控件的時(shí)候也只是演示一下控件的制作過(guò)程,只用了很短的時(shí)間做了一個(gè),只考慮了用鼠標(biāo)選取,沒(méi)有考慮鍵盤(pán)操作,我想要添加鍵盤(pán)操作無(wú)非重載KeyDown事件,針對(duì)Up,Down做一些響應(yīng)就可以了。可是添加了重載了OnKeyDown事件后,結(jié)果和那位朋友所說(shuō)的一樣,沒(méi)有任何作用,我設(shè)了斷點(diǎn),調(diào)試了一下,發(fā)現(xiàn)KeyDown根本捕獲不到Up,Down按鍵的點(diǎn)擊,是什么原因呢,是不是忘記設(shè)控件的風(fēng)格以便讓它能夠獲得焦點(diǎn)?于是,我使用了語(yǔ)句:
SetStyle(ControlStyles.Selectable, true);
依然沒(méi)有效果,當(dāng)我們?cè)诳丶习聪翫own鍵的時(shí)候,另一個(gè)控件獲得了焦點(diǎn)。這時(shí)Up,Down按鈕只是起到了導(dǎo)航的作用就像Tab鍵一樣。
接下來(lái),我在測(cè)試工程的窗體上放置了一個(gè)ListBox控件做一個(gè)對(duì)比,其實(shí)ToolBox和ListBox在界面表現(xiàn)上有相似之處,就是都有子Item,并且在ListBox上點(diǎn)擊Down是起作用的,ListBox并沒(méi)有失去焦點(diǎn),這說(shuō)明這時(shí)Up,Down按鍵沒(méi)有成為導(dǎo)航鍵。我想Windows一定是對(duì)默認(rèn)的導(dǎo)航鍵Up,Down,Left,Right有默認(rèn)的處理,除非你希望你的控件希望自己處理這些鍵。用反匯編工具看了一下ListBoxControl控件的源代碼,發(fā)現(xiàn)一個(gè)有趣的函數(shù):
protected override bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) == Keys.Alt)
{
return false;
}
switch ((keyData & Keys.KeyCode))
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
return true;
}
return base.IsInputKey(keyData);
}
在這里面,ListBoxControl允許Prior,Next,End,Home成為有效的輸入鍵,接著一路跟下去,看看winform控件的基類(lèi)Control的這個(gè)函數(shù)是如何處理的:
[UIPermission(SecurityAction.InheritanceDemand, Window=UIPermissionWindow.AllWindows)]
protected virtual bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) != Keys.Alt)
{
int num = 4;
switch ((keyData & Keys.KeyCode))
{
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
num = 5;
break;
case Keys.Tab:
num = 6;
break;
}
if (this.IsHandleCreated)
{
return ((((int) this.SendMessage(0x87, 0, 0)) & num) != 0);
}
}
return false;
}
注意這一行return ((((int) this.SendMessage(0x87, 0, 0)) & num) != 0);0x87是什么windows消息呢,打開(kāi)WinUser.h文件,發(fā)現(xiàn)是WM_GETDLGCODE,在MSDN中的描述是這樣的:
The WM_GETDLGCODE message is sent to the window procedure associated with a control. By default, the system handles all keyboard input to the control; the system interprets certain types of keyboard input as dialog box navigation keys. To override this default behavior, the control can respond to the WM_GETDLGCODE message to indicate the types of input it wants to process itself.
也就是說(shuō)windows用這個(gè)消息來(lái)判斷哪些類(lèi)型的輸入交給控件本身來(lái)處理。然后,我注意到,對(duì)于方向?qū)Ш芥I,函數(shù)都給于一個(gè)值5與this.SendMessage(0x87, 0, 0))的返回值進(jìn)行與操作,那么this.SendMessage(0x87, 0, 0))的返回值都可能是什么值呢,WinUser.h中是這樣聲明的:
/*
* Dialog Codes
*/
#define DLGC_WANTARROWS 0x0001 /* Control wants arrow keys */
#define DLGC_WANTTAB 0x0002 /* Control wants tab keys */
#define DLGC_WANTALLKEYS 0x0004 /* Control wants all keys */
#define DLGC_WANTMESSAGE 0x0004 /* Pass message to control */
#define DLGC_HASSETSEL 0x0008 /* Understands EM_SETSEL message */
#define DLGC_DEFPUSHBUTTON 0x0010 /* Default pushbutton */
#define DLGC_UNDEFPUSHBUTTON 0x0020 /* Non-default pushbutton */
#define DLGC_RADIOBUTTON 0x0040 /* Radio button */
#define DLGC_WANTCHARS 0x0080 /* Want WM_CHAR messages */
#define DLGC_STATIC 0x0100 /* Static item: don't include */
#define DLGC_BUTTON 0x2000 /* Button item: can be checked */
5最貼切的表達(dá)就是DLGC_WANTMESSAGE | DLGC_WANTARROWS,也就是將方向鍵發(fā)送給控件處理,對(duì)于6呢,也就是DLGC_WANTMESSAGE| DLGC_WANTTAB,將Tab鍵發(fā)送給控件處理。
從這段代碼里和控件實(shí)際的行為我們可以得出一個(gè)結(jié)論,那就是,控件本身是不處理方向鍵和Tab鍵的,因?yàn)樗麄冇心J(rèn)的行為,也就是支持焦點(diǎn)在窗體的控件之間轉(zhuǎn)換。如果你想要處理這些導(dǎo)航鍵,那么結(jié)論很簡(jiǎn)單,就是重載IsInputKey方法,它是一個(gè)保護(hù)類(lèi)型的虛方法。
在ToolBox控件的代碼里重載IsinputKey方法:
protected override bool IsInputKey(Keys keyData)
{
if ((keyData & Keys.Alt) == Keys.Alt)
{
return false;
}
switch ((keyData & Keys.KeyCode))
{
case Keys.Up:
case Keys.Down:
return true;
}
return base.IsInputKey(keyData);
}
當(dāng)用戶點(diǎn)擊的鍵是Up,Down的時(shí)候,返回true,這時(shí)我們的OnKeyDown方法里就可以捕獲到Up,Down的點(diǎn)擊事件了。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:博客轉(zhuǎn)載