Descrizione :
Una tecnica per intercettare e gestire a livello di Control i comandi da tastiera.
+ Articolo :
Nell'esempio seguente definisco una Classe MioPanel che eredita da Panel, e che permette la gestione di comandi da tastiera, senza alcun uso del mouse, e soprattutto senza alcun bisogno di aggiungere e gestire eventi dall'esterno, ossia dalla FormMain Parent.
Per rendere l'articolo più significativo gestisco in particolare i 4 Tasti Arrows, che normalmente sono di selezione / spostamento tra controlli, e che quindi, senza un'opportuna implementazione degli Override di OnPreviewKeyDown e OnKeyDown, verrebbero ignorati a livello di Control.
Vanno gestiti entrambi, perchè OnPreviewKeyDown serve solo a definire quali tasti sono da considerare "di Input" per il controllo, anzichè di Selezione e lo si fa con e.IsInputKey.
Mentre sotto OnKeyDown va la logica per gestire ogni particolare tasto...
Le logiche di gestione tasti e spostamento sono incapsulate nella Classe "MioPanel", e non gestite dall'esterno ( dal codice Form... ).
Settare KeyPreview = True sulla Form che ospita i Panel non serve, perciò su FormMain, KeyPreview = False.
--> La Classe MioPanel :
Public Class MioPanel Inherits Panel Private m_selected As Boolean Private m_selectedcolor As Color = Color.Red Private m_defaultcolor As Color = Color.White Private m_movestep As Integer = 10 Public Property Selected As Boolean Get Return m_selected End Get Set(ByVal value As Boolean) m_selected = value If m_selected = True Then Me.BackColor = m_selectedcolor For Each C As Control In Me.Parent.Controls If TypeOf (C) Is MioPanel And Not C Is Me Then DirectCast(C, MioPanel).Selected = False Next Me.Select() Else Me.BackColor = m_defaultcolor End If End Set End Property Public Property SelectedColor As Color Get Return m_selectedcolor End Get Set(ByVal value As Color) m_selectedcolor = value End Set End Property Public Property DefaultColor As Color Get Return m_defaultcolor End Get Set(ByVal value As Color) m_defaultcolor = value End Set End Property Public Property MoveStep As Integer Get Return m_movestep End Get Set(ByVal value As Integer) m_movestep = value End Set End Property Public Sub New() Me.BackColor = m_defaultcolor End Sub Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = MouseButtons.Left Then Me.Selected = True End Sub Protected Overrides Sub OnPreviewKeyDown(ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Select Case e.KeyCode Case Keys.Up, Keys.Down, Keys.Right, Keys.Left 'Tasti Arrows = spostamento da tastiera e.IsInputKey = True Case Keys.Tab 'Tasto TAB = passaggio al prossimo controllo di tipo MioPanel e.IsInputKey = True Case Else e.IsInputKey = False End Select End Sub Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs) Select Case e.KeyCode Case Keys.Up Me.Top -= m_movestep Case Keys.Down Me.Top += m_movestep Case Keys.Right Me.Left += m_movestep Case Keys.Left Me.Left -= m_movestep Case Keys.Tab Dim j As Integer Dim c As Integer = Me.Parent.Controls.Count - 1 For i As Integer = 0 To c If Me.Parent.Controls(i) Is Me Then j = i + 1 Do If j > c Then j = 0 Try DirectCast(Me.Parent.Controls(j), MioPanel).Selected = True Exit For Catch ex As Exception j += 1 End Try Loop Until j = i End If Next Case Else '... End Select End Sub End Class
Il codice, apparentemente "complicato", per gestire il tasto TAB, è giustificato dal fatto che la selezione manuale ( Click sinistro del mouse oppure tastiera con TAB ), e la selezione da codice, vengono centralizzate in un solo Metodo di Propery-Set : la Property Selected.
Inoltre è possibile avere anche altri controlli su FormMain : in questo caso tutti i controlli che non sono Oggetti della Classe MioPanel verranno ignorati : la pressione di TAB su un "MioPanel" correntemente selezionato avrà come effetto la selezione del "MioPanel" successivo, con una logica ciclica.
Per queste ragioni non ce la si può fare con un semplice Me.Parent.SelectNextControl ...
--> FormMain :
Su FormMain ho un Button "cmd_aggiungi", che serve allo scopo di creare alcuni Oggetti "MioPanel" a runtime, e inoltre a verificare la logica di selezione ciclica ogni volta che si fa TAB su un "MioPanel" attivo.
Public Class FormMain Private Sub cmd_aggiungi_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_aggiungi.Click Dim mp1 As New MioPanel Me.Controls.Add(mp1) mp1.SelectedColor = Color.Red mp1.Location = New Point(0, 100) mp1.Size = New Size(50, 50) Dim mp2 As New MioPanel Me.Controls.Add(mp2) mp2.SelectedColor = Color.Gold mp2.Location = New Point(100, 100) mp2.Size = New Size(50, 50) Dim mp3 As New MioPanel Me.Controls.Add(mp3) mp3.SelectedColor = Color.Green mp3.Location = New Point(200, 100) mp3.Size = New Size(50, 50) mp3.Selected = True End Sub End Class
Perciò riassumendo il tutto :
--> Avvio il Progetto, e poi senza toccare il mouse, premo Invio, che comporta un Click sul Button cmd_aggiungi.
--> Vengono creati 3 Oggetti della Classe MioPanel, e viene selezionato il terzo.
--> Con i tasti Arrows sposto il "MioPanel" attivo.
--> Con il tasto TAB seleziono ciclicamente tutti i "MioPanel" presenti, ignorando eventuali altri controlli.
+ Fine Articolo.
0 commenti:
Posta un commento