Henry手記 - Datagrid鍵盤事件響應(二)
2024-07-21 02:16:33
供稿:網友
 
對于datagrid的鍵盤事件響應,我們一定要分辨清楚是datagrid自身的,還是cell單元格的鍵盤事件響應,處理方法是有很大區別的。大家可以參考第一篇的方法,對cell中的鍵盤事件進行處理。
 但有個問題上一節沒有交待,就是如何對enter鍵、方向鍵、tab鍵、pgup/pgdn這些虛鍵進行攔截與處理?一般網友遇到這個問題,十有八九是出于這個目的:就是希望按enter鍵時使光標在一行中向右一個格一個格跳(從“name”到“123”),而不是立即跳向同一列的下一行(到“xxx”)。(如圖1所示)
圖1 跳格演示
          但是,我們在上一篇中用盡方法也截不下enter鍵呀,看來這一鍵盤響應已經被控件封裝為protected型了。控件編寫人員把多個預定義的鍵盤綁定方案封裝起來,稱為快捷鍵。我們在keydown/keypress中沒辦法攔截到enter鍵和其它一些鍵盤按鍵正是這個原因。
 快捷鍵與菜單快捷方式被稱為命令鍵,應用程序會在對常規輸入進行處理前的消息預處理過程中對它們進行處理。命令鍵也就始終比常規輸入鍵具有優先權。
 processcmdkey 方法首先確定控件是否有上下文菜單,如果有,則允許 contextmenu 處理命令鍵。如果命令鍵不是菜單快捷方式,且控件有父級,那么該鍵傳遞到父級的 processcmdkey 方法。凈效果是命令鍵在控件層次結構中向上“冒”。除了用戶按下的鍵外,鍵數據還指示哪些(如果有的話)修改鍵與該鍵同時按下。修改鍵包括 shift、ctrl 和 alt 鍵(成為組合鍵)。
 這里要注意:該方法必須返回 true,以指示它已經處理完命令鍵,或者 false,以指示該鍵不是命令鍵。在派生類中重寫 processcmdkey 方法時,控件應返回 true 以指示它已處理該鍵。對于未由該控件處理的鍵,應返回調用基類的 processcmdkey 方法的結果。
 如果不加返回值,會默認為false。這樣你明明已經修改了處理方法,卻會在執行完你的命令之后,繼續執行父類中定義的該鍵盤按鍵的處理方法。
 那么我們怎么處理文頭的命題?解決之道就是自己寫一個控件,繼承自現有的datagrid控件,再重寫處理命令鍵響應程序processcmdkey,來實現我們的需求。
 步驟一:在vs.net編輯器中,“文件”->“新建”->“項目”,然后選擇新建一個“windows控件庫”的項目:henrydatagrid。這樣運行的結果會生成一個dll文件,而不是exe執行文件;
 步驟二:在henrydatagrid.vb文件代碼編輯窗口中加入有陰影的這句話:
public class henrydatagrid
inherits system.windows.forms.datagrid   ‘這表示新建的控件是datagrid的派生控件
 步驟三:在“類名”窗口中選擇overrides,然后在“方法名稱”窗口選擇“processcmdkey”(如圖2所示)
圖2 選擇要重寫的方法
 然后就會出現一段空的processcmdkey代碼段,我們可以寫入自己的代碼:
protected overrides function processcmdkey
(byref msg as system.windows.forms.message, byval keydata as system.windows.forms.keys) as boolean
 dim wm_keydown as integer = 256 ‘消息響應的問題可以參考其他win32編程的文章
 dim wm_syskeydown as integer = 260 
 if ((msg.msg = wm_keydown) or (msg.msg = wm_syskeydown)) then
 select case keydata
 case keys.down 
 msgbox("截到下箭頭鍵")
 return true
 case keys.up
 msgbox("截到上箭頭鍵")
 return true
 case keys.enter
 sendkeys.send("{tab}")
 return true
 case keys.control + keys.m
 msgbox("<ctrl> + m 組合鍵被截獲")
 return true
 case keys.alt + keys.z
 msgbox("<alt> + z 組合鍵被截獲")
 return true
 end select
 end if
 end function
  然后運行一下,生成henrydatagrid.dll文件
 步驟四:再建立一個項目,然后在新項目的設計窗口的工具箱上單擊鼠標右鍵,在彈出菜單中選擇“添加引用”,然后在.net選項卡中占擊“瀏覽”,選擇到henrydatagrid.dll,加入進來,然后您的工具箱上會多出一個henrydatagrid的圖標,在新項目中使用henrydatagrid來代替datagrid控件。看一下,您所需要的“enter跳格”事件就這樣完成了。
 建議:您在keys.enter代碼中的return true去掉,看一下會有什么情況發生。
 這里說句題外話,我們在重寫類方法時,必須也只能使用overridable關鍵字修飾的protected 
 方法。這是因為在vb中是用overridable 關鍵字指定屬性或方法可以在派生類中重寫。沒有這個東東的我們也沒有資格重寫了。注冊會員,創建你的web開發資料庫,