1. Datagrid上的鍵盤響應
當Datagrid與數據源綁定后,會呈現出如圖1所示的形式。當Datagrid被聚焦后,焦點會首先落在第一行第一列的單元格上(注意:不是單元格內),如圖1-(3)所示。在該單元格上單擊一下鼠標,會出現如圖1-(4)所示的情況,焦點落入了單元格中。 圖1 Datagrid聚焦圖 我們在本節中討論的是圖1-(1)及1-(2)所示的情況,即焦點是落在Datagrid的框格上。一般的鍵盤事件響應是用KeyPress、KeyDown或KeyUp事件處理程序中的(鍵盤響應的順序是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 現在運行一下程序,當您點擊鍵盤上的“0-1”“A-Z”、“Enter鍵”、“Backspace鍵”等時,會彈出“你輸入的是…”對話框,但是當你點擊“Ctrl鍵”“Alt鍵”“Shift鍵”時會毫無反應,點擊方向鍵、Tab鍵時,焦點會相應發生變動,而對話框卻不會相應彈出。也就是說,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控件把它們藏起來了,怎么處理?后面再來說吧。
現在請關注這樣一個需求,我們不是已經可以截得“Enter鍵”了嗎?我想在用戶鍵入Enter時,響應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}") ‘通知系統調用Tab鍵的事件處理程序
End If
End Sub 運行一下程序,我們將焦點落在圖1-(1)的位置,敲下Enter鍵,怎么樣?果然程序把Enter鍵當成了Tab鍵來執行了,焦點落入到第一行的第二列那個單元格上了!
那我再敲Enter鍵,咦,焦點怎么不跳動了?呵呵,當然不會動了,因為現在焦點已經被單元格獲取了。
2. Datagrid單元格上的鍵盤響應
單元格上的鍵盤響應主要是針對能顯示的字符輸入(這也是單元格的主要作用嘛!),當然還有Backspace/Delete/Home/End這樣的功能鍵。那么怎樣來截得鍵盤信息呢?事件的對象現在是單元格了,可是我們在VS.NET的代碼編輯器的“類名”下拉框中卻看不到可以用的類,是什么東東的KeyDown/KeyPress/KeyUp事件呢?
如果您看過我寫的Datagrid結構剖析系列文章,您應該會很清楚,單元格的直接領導就是“列”了。所以我們應該在列上動動腦筋。讓列來承接這項任務。我們來完成的需求是:實現單元格的數值框功能,就是只能在單元格中輸入數字0-9,以及小數點“.”與回退鍵(Backspace鍵),Form_load中的代碼的參數聲明見Datagrid結構剖析(一): 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) '讓列中的單元格來響應KeyPress事件
aColumnTextColumn.HeaderText = dt.Columns(i).ColumnName
aColumnTextColumn.MappingName = dt.Columns(i).ColumnName
ts.GridColumnStyles.Add(aColumnTextColumn) '增加一種自定義的column風格
i = (i + 1)
Loop
DataGrid1.TableStyles.Add(ts) '增加一種自定義的表風格
……
‘事件處理程序,同樣適用于其它Textbox用于數值框處理的情況。
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”這樣的字符嗎?
當然還可以利用賦值方法來實現:
在類中先聲明(原因請參見拙作《Windows 窗體引介(二) 》): Friend WithEvents Column1 As TextBox
Friend WithEvents Column2 As TextBox 然后在Form_load中編寫代碼如下(同樣見Datagrid結構剖析(一)的參數聲明): 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 運行一下程序,你會發現第一列已經實現了數值框功能,第二列會在接受鍵盤請求后報告用戶按下的是什么鍵。這么一處理,我們可以輕松地針對各列的單元格進行我們想要的處理了(不管是KeyPress,KeyDown,還是其它Textbox能響應的事件,我們都可以來處理了!怎一個爽字了得!)
繼續第一節提出的問題,我們在單元格獲得響應時來按下“Enter鍵”發現會有兩種情況:(1)當單元格的內容沒有任何變化時,按下此鍵沒有任何響應;(2)當單元格的內容發生變動后,按下此鍵,焦點會落入下一行同一列的那個單元格里去了。
我們在上述的事件處理程序中來截取“Enter鍵”,完了,卻截不到了,不論是KeyPress還是KeyDown!那些第一節中就束手無策的虛鍵:方向鍵、Tab鍵、Pgup/PgDn,當然仍然截不到。怎么辦?它們藏到哪去了?下次再討論
|