Impedire la selezione di un controllo

Nelle applicazioni .NET WinForms (Windows Forms) vi sono casi in cui è preferibile che determinati controlli in una Form non possano essere selezionabili ovvero non sia possibile impostare il Focus su di loro.

Si pensi ad esempi ad un pulsante in una form che esegue un certa azione, per default un pulsante è selezionabile ovvero può ricevere il Focus e se questo non viene spostato su di un altro controllo lo mantiene.

Un controllo può ricevere il Focus se sono vere le seguenti condizioni:

  • il valore del flag Selectable di ControlStyles è true
  • il controllo è contenuto in un altro controllo e tutti i relativi controlli principali sono visibili e abilitati.

Un controllo può essere selezionato quando ha il Focus.

La differenza tra Focus e controllo selezionabile è importate perché, come riportato in Control.Focus Method, il Focus è un metodo di basso livello destinato principalmente allo sviluppo di controlli personalizzati, mentre per lo sviluppo di applicazioni si dovrebbe utilizzare il metodo Select o la proprietà ActiveControl per i controlli figlio o il metodo Activate della Form.

Quando un controllo ha il Focus riceve gli eventi della tastiera e del mouse, scendo in un caso pratico se un pulsante ha il Focus su di esso e l’utente preme il tasto Invio (Enter) sulla tastiera il pulsante si comporterà come se fosse stato eseguito un click su di esso, questo potrebbe essere un comportamento non desiderato se l’utente tiene l’applicazione aperta insieme ad altre e la pressione del tasto Invio potrebbe scatenare involontariamente l’esecuzione dell’azione del pulsante.

Per evitare che un controllo possa ricevere il Focus l’approccio migliore è quello di impostare a False il flag Selectable di ControlStyles, per fare ciò è possibile creare un Extension Method che imposta il flag, di seguito un esempio di un modulo che implementa l’estensione:

Public Module UtilControlExtensions

 

<System.Runtime.CompilerServices.Extension()>
Public Sub UtilSetStyle(ByVal control As System.Windows.Forms.Control, ByVal style As System.Windows.Forms.ControlStyles, ByVal value As Boolean)

Dim setStyleMethodInfo = control.GetType().GetMethod(“SetStyle”, Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
setStyleMethodInfo.Invoke(control, New System.Object() {style, value})
setStyleMethodInfo = Nothing

End Sub

 

<System.Runtime.CompilerServices.Extension()>
Public Sub UtilSetSelectable(ByVal control As System.Windows.Forms.Control, ByVal value As Boolean)

control.UtilSetStyle(System.Windows.Forms.ControlStyles.Selectable, value)

End Sub

 

End Module

Per impedire la selezione del pulsante e quindi la possibilità che possa ricevere il Focus sarà sufficiente impostare a False il flag Selectable di ControlStyles del punsante nella load della Form:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Me.Button1.UtilSetSelectable(False)

End Sub