Henry手記 - Datagrid鍵盤事件響應(yīng)(一)
2024-07-21 02:16:34
供稿:網(wǎng)友
 
1. datagrid上的鍵盤響應(yīng)
 當(dāng)datagrid與數(shù)據(jù)源綁定后,會呈現(xiàn)出如圖1所示的形式。當(dāng)datagrid被聚焦后,焦點會首先落在第一行第一列的單元格上(注意:不是單元格內(nèi)),如圖1-(3)所示。在該單元格上單擊一下鼠標(biāo),會出現(xiàn)如圖1-(4)所示的情況,焦點落入了單元格中。
圖1 datagrid聚焦圖
 我們在本節(jié)中討論的是圖1-(1)及1-(2)所示的情況,即焦點是落在datagrid的框格上。一般的鍵盤事件響應(yīng)是用keypress、keydown或keyup事件處理程序中的(鍵盤響應(yīng)的順序是keydown->keypress->keyup),我們也來如法炮制一下:
private sub datagrid1_keypress(byval sender as object, byval e as _
system.windows.forms.keypresseventargs) handles datagrid1.keypress
  msgbox("你輸入的是:" + e.keychar.tostring)
end sub
 現(xiàn)在運行一下程序,當(dāng)您點擊鍵盤上的“0-1”“a-z”、“enter鍵”、“backspace鍵”等時,會彈出“你輸入的是…”對話框,但是當(dāng)你點擊“ctrl鍵”“alt鍵”“shift鍵”時會毫無反應(yīng),點擊方向鍵、tab鍵時,焦點會相應(yīng)發(fā)生變動,而對話框卻不會相應(yīng)彈出。也就是說,keypress不能截得虛鍵,這是因為keychar表示的是ascii碼表中有的鍵碼。要截得虛鍵,我們用keydown來試試:
private sub datagrid1_keydown(byval sender as object, byval e as _
system.windows.forms.keyeventargs) handles datagrid1.keydown
 msgbox("你輸入的是:" + e.keycode.tostring)
end sub
 搞定了,我們可以截得“ctrl鍵”“alt鍵”“shift鍵”了(組合鍵問題也就迎刃而解了,對吧?),等等,方向鍵、tab鍵、pgup、pgdown為什么還不理我們?看來是datagrid控件把它們藏起來了,怎么處理?后面再來說吧。
 現(xiàn)在請關(guān)注這樣一個需求,我們不是已經(jīng)可以截得“enter鍵”了嗎?我想在用戶鍵入enter時,響應(yīng)tab鍵的事件處理程序。來吧,用keydown試試(keypress也行):
private sub datagrid1_keydown(byval sender as object, byval e as _
system.windows.forms.keyeventargs) handles datagrid1.keydown
 if e.keycode = keys.enter then
 sendkeys.send("{tab}") ‘通知系統(tǒng)調(diào)用tab鍵的事件處理程序
 end if
end sub
 運行一下程序,我們將焦點落在圖1-(1)的位置,敲下enter鍵,怎么樣?果然程序把enter鍵當(dāng)成了tab鍵來執(zhí)行了,焦點落入到第一行的第二列那個單元格上了!
 那我再敲enter鍵,咦,焦點怎么不跳動了?呵呵,當(dāng)然不會動了,因為現(xiàn)在焦點已經(jīng)被單元格獲取了。
 2. datagrid單元格上的鍵盤響應(yīng)
 單元格上的鍵盤響應(yīng)主要是針對能顯示的字符輸入(這也是單元格的主要作用嘛!),當(dāng)然還有backspace/delete/home/end這樣的功能鍵。那么怎樣來截得鍵盤信息呢?事件的對象現(xiàn)在是單元格了,可是我們在vs.net的代碼編輯器的“類名”下拉框中卻看不到可以用的類,是什么東東的keydown/keypress/keyup事件呢?
 如果您看過我寫的datagrid結(jié)構(gòu)剖析系列文章,您應(yīng)該會很清楚,單元格的直接領(lǐng)導(dǎo)就是“列”了。所以我們應(yīng)該在列上動動腦筋。讓列來承接這項任務(wù)。我們來完成的需求是:實現(xiàn)單元格的數(shù)值框功能,就是只能在單元格中輸入數(shù)字0-9,以及小數(shù)點“.”與回退鍵(backspace鍵),form_load中的代碼的參數(shù)聲明見datagrid結(jié)構(gòu)剖析(一):
 dim ts as new datagridtablestyle() 
 dim acolumntextcolumn as datagridtextboxcolumn 
 datagrid1.datasource = dt
 ts.mappingname = dt.tablename
 
 dim numcols as integer
 numcols = dt.columns.count
 
 dim i as integer = 0
 do while (i < numcols) '重繪所有的列
 acolumntextcolumn = new datagridtextboxcolumn()
addhandler acolumntextcolumn.textbox.keypress, new keypresseventhandler(addressof column_keypress) 
'讓列中的單元格來響應(yīng)keypress事件
 acolumntextcolumn.headertext = dt.columns(i).columnname
 acolumntextcolumn.mappingname = dt.columns(i).columnname
 ts.gridcolumnstyles.add(acolumntextcolumn) '增加一種自定義的column風(fēng)格
 i = (i + 1)
 loop
 datagrid1.tablestyles.add(ts) '增加一種自定義的表風(fēng)格 
……
‘事件處理程序,同樣適用于其它textbox用于數(shù)值框處理的情況。
 private sub column_keypress(byval sender as object, _
  byval e as system.windows.forms.keypresseventargs)
 
 msgbox("you have pressed the " & e.keychar)
 if not (isnumeric(e.keychar) or e.keychar = chrw(8) or e.keychar = chrw(46)) then
 e.handled = true
 end if
 運行一下程序,您還能在單元格中輸入“a-z”這樣的字符嗎?
 當(dāng)然還可以利用賦值方法來實現(xiàn):
 在類中先聲明(原因請參見拙作《windows 窗體引介(二) 》):
 friend withevents column1 as textbox
 friend withevents column2 as textbox
 然后在form_load中編寫代碼如下(同樣見datagrid結(jié)構(gòu)剖析(一)的參數(shù)聲明):
dim mygridtablestyle as datagridtablestyle = new datagridtablestyle()
 mygridtablestyle.mappingname = dt.tablename
 datagrid1.tablestyles.add(mygridtablestyle)
 dim tempcolumn as datagridtextboxcolumn
 tempcolumn = datagrid1.tablestyles(0).gridcolumnstyles(0)
 column1 = tempcolumn.textbox
 tempcolumn = datagrid1.tablestyles(0).gridcolumnstyles(1)
 事件處理程序:
private sub column1_keypress(byval sender as object, _
 byval e as system.windows.forms.keypresseventargs) _
 handles column1.keypress
 if not (isnumeric(e.keychar) or e.keychar = chrw(8) or e.keychar = chrw(46)) then
 e.handled = true
end if
end sub
private sub column2_keydown(byval sender as object, _
 byval e as system.windows.forms.keyeventargs) _
 handles column2.keydown
 msgbox("you have pressed the " & e.keycode)
end sub
 運行一下程序,你會發(fā)現(xiàn)第一列已經(jīng)實現(xiàn)了數(shù)值框功能,第二列會在接受鍵盤請求后報告用戶按下的是什么鍵。這么一處理,我們可以輕松地針對各列的單元格進行我們想要的處理了(不管是keypress,keydown,還是其它textbox能響應(yīng)的事件,我們都可以來處理了!怎一個爽字了得!)
 繼續(xù)第一節(jié)提出的問題,我們在單元格獲得響應(yīng)時來按下“enter鍵”發(fā)現(xiàn)會有兩種情況:(1)當(dāng)單元格的內(nèi)容沒有任何變化時,按下此鍵沒有任何響應(yīng);(2)當(dāng)單元格的內(nèi)容發(fā)生變動后,按下此鍵,焦點會落入下一行同一列的那個單元格里去了。
 我們在上述的事件處理程序中來截取“enter鍵”,完了,卻截不到了,不論是keypress還是keydown!那些第一節(jié)中就束手無策的虛鍵:方向鍵、tab鍵、pgup/pgdn,當(dāng)然仍然截不到。怎么辦?它們藏到哪去了?下次再討論吧,敬請繼續(xù)關(guān)注!