程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WinForm控件開發總結(十二) 讓控件處理導航鍵

WinForm控件開發總結(十二) 讓控件處理導航鍵

編輯:關於.NET

最近真的真的太忙了,以至於一個多月都沒喲更新我的blog。昨天晚上,一個網上的朋友看了我的 ToolBox的文章,問我一個問題,他說如何讓ToolBox控件也能響應鍵盤操作,也就是用Up,down按鍵來選 擇工具箱控件裡的Item,他添加了鍵盤事件,但是不起作用。一開始做這個控件的時候也只是演示一下控 件的制作過程,只用了很短的時間做了一個,只考慮了用鼠標選取,沒有考慮鍵盤操作,我想要添加鍵盤 操作無非重載KeyDown事件,針對Up,Down做一些響應就可以了。可是添加了重載了OnKeyDown事件後,結 果和那位朋友所說的一樣,沒有任何作用,我設了斷點,調試了一下,發現KeyDown根本捕獲不到Up, Down按鍵的點擊,是什麼原因呢,是不是忘記設控件的風格以便讓它能夠獲得焦點?於是,我使用了語句 :

SetStyle(ControlStyles.Selectable, true);依然沒有效果,當我們在控件上按下Down鍵的時候,另 一個控件獲得了焦點。這時Up,Down按鈕只是起到了導航的作用就像Tab鍵一樣。

接下來,我在測試工程的窗體上放置了一個ListBox控件做一個對比,其實ToolBox和ListBox在界面表 現上有相似之處,就是都有子Item,並且在ListBox上點擊Down是起作用的,ListBox並沒有失去焦點,這 說明這時Up,Down按鍵沒有成為導航鍵。我想Windows一定是對默認的導航鍵Up,Down,Left,Right有默認 的處理,除非你希望你的控件希望自己處理這些鍵。用反匯編工具看了一下ListBoxControl控件的源代碼 ,發現一個有趣的函數:

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控件的基類Control的這個函數是如何處理的:

[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消息呢,打開WinUser.h文件,發現是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.

也就是說windows用這個消息來判斷哪些類型的輸入交給控件本身來處理。然後,我注意到,對於方向 導航鍵,函數都給於一個值5與this.SendMessage(0x87, 0, 0))的返回值進行與操作,那麼 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最貼切的表達就是DLGC_WANTMESSAGE |

DLGC_WANTARROWS,也就是將方向鍵發送給控件處理,對於6呢,也就是DLGC_WANTMESSAGE| DLGC_WANTTAB,將Tab鍵發送給控件處理。

從這段代碼裡和控件實際的行為我們可以得出一個結論,那就是,控件本身是不處理方向鍵和Tab鍵的 ,因為他們有默認的行為,也就是支持焦點在窗體的控件之間轉換。如果你想要處理這些導航鍵,那麼結 論很簡單,就是重載IsInputKey方法,它是一個保護類型的虛方法。

在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);

        }

當用戶點擊的鍵是Up,Down的時候,返回true,這時我們的OnKeyDown方法裡就可以捕獲到Up,Down的 點擊事件了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved