Results 1 to 12 of 12

Thread: Non-restricted movement between buttons

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Non-restricted movement between buttons

    Hi there

    I am creating a Windows Forms App .NET with VB in VS, and I have 4 buttons arranged in a square (2 rows and 2 columns).
    I would like to have free movement between the buttons using the arrow keys, so that when the upper left button has focus
    I can move focus to the lower left button with the down arrow, or to the upper right button using the right arrow.

    I already sat the focus to be on the upper left button when the form is shown, and I have tinkered a little bit with the
    TabIndex and the TabStop, but can't seem to get 100% free movement.

    Also, I have tried using a KeyDown event on the button, like this:

    If e.KeyCode = Keys.Down Then
    Button4.Focus()
    End if

    But it does not work...

    Any ideas?
    Thanks!

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    Try this...

    Code:
    Public Class Form20
    
        Dim buttons(1)() As Button
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            buttons(0) = New Button() {Button1, Button2}
            buttons(1) = New Button() {Button3, Button4}        
        End Sub
    
        Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
            Dim sy As Integer
            Dim sx As Integer
            sx = Array.IndexOf(buttons(0), Control.FromHandle(msg.HWnd))
            If sx > -1 Then
                sy = 0
            Else
                sy = 1
                sx = Array.IndexOf(buttons(1), Control.FromHandle(msg.HWnd))
            End If
    
            Select Case keyData
                Case Keys.Up
                    If sx = -1 then Return False
                    If sy = 1 Then
                        buttons(0)(sx).Select()
                    End If
                    Return True
                Case Keys.Down
                    If sy = 0 Then
                        buttons(1)(sx).Select()
                    End If
                    Return True
                Case Keys.Left
                    If sx = 1 Then
                        buttons(sy)(0).Select()
                    End If
                    Return True
                Case Keys.Right
                    If sx = 0 Then
                        buttons(sy)(1).Select()
                    End If
                    Return True
            End Select
    
            Return False
    
    End Class
    Last edited by .paul.; Feb 3rd, 2022 at 01:52 PM.

  3. #3

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Re: Non-restricted movement between buttons

    Thank you for your reply, I will try it in a moment

    And if I had 9 buttons also in a square (3x3) it would just be this?:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    buttons(0) = New Button() {Button1, Button2, Button3}
    buttons(1) = New Button() {Button4, Button5, Button6}
    buttons(2) = New Button() {Button7, Button8, Button9}
    End Sub

    And then change the rest accordingly?

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    Quote Originally Posted by Anderskd1 View Post
    Thank you for your reply, I will try it in a moment

    And if I had 9 buttons also in a square (3x3) it would just be this?:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    buttons(0) = New Button() {Button1, Button2, Button3}
    buttons(1) = New Button() {Button4, Button5, Button6}
    buttons(2) = New Button() {Button7, Button8, Button9}
    End Sub

    And then change the rest accordingly?
    There would be more to do than just changing the array

  5. #5

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Re: Non-restricted movement between buttons

    Would you be so kind to explain the rest of the changes if ther were 3x3 buttons, please?
    I'm just not sure that I understand the "sx" and "sy" part.

  6. #6
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    Imagine a square grid with 3 rows and 3 columns
    sx is the horizontal index of a cell
    sy is the vertical index of a cell

    Now you can see that the array is a square grid of 3 rows of 3 buttons

  7. #7

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Re: Non-restricted movement between buttons

    Ah, okay, that makes a lot of sense, but what is up with the "-1"?

  8. #8
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    Here's a 3 by 3 grid of buttons...

    Code:
    Public Class Form1
    
        Dim buttons(2)() As Button
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            buttons(0) = New Button() {Button1, Button2, Button3}
            buttons(1) = New Button() {Button4, Button5, Button6}
            buttons(2) = New Button() {Button7, Button8, Button9}
        End Sub
    
        Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
            Dim sy As Integer = -1
            Dim sx As Integer = -1
            sx = Array.IndexOf(buttons(0), Control.FromHandle(msg.HWnd))
            If sx > -1 Then
                sy = 0
            Else
                sx = Array.IndexOf(buttons(1), Control.FromHandle(msg.HWnd))
                If sx > -1 Then
                    sy = 1
                Else
                    sx = Array.IndexOf(buttons(2), Control.FromHandle(msg.HWnd))
                    If sx > -1 Then
                        sy = 2
                    Else
                        sy = -1
                    End If
                End If
            End If
    
            Select Case keyData
                Case Keys.Up
                    If sy = 1 Then
                        buttons(0)(sx).Select()
                    End If
                    If sy = 2 Then
                        buttons(1)(sx).Select()
                    End If
                    Return True
                Case Keys.Down
                    If sy = 0 Then
                        buttons(1)(sx).Select()
                    End If
                    If sy = 1 Then
                        buttons(2)(sx).Select()
                    End If
                    Return True
                Case Keys.Left
                    If sx = 1 Then
                        buttons(sy)(0).Select()
                    End If
                    If sx = 2 Then
                        buttons(sy)(1).Select()
                    End If
                    Return True
                Case Keys.Right
                    If sx = 0 Then
                        buttons(sy)(1).Select()
                    End If
                    If sx = 1 Then
                        buttons(sy)(2).Select()
                    End If
                    Return True
            End Select
    
            Return False
    
        End Function
    End Class
    The Array.IndexOf function, either finds the index of what you specify, or -1 if it can't find it...

  9. #9
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    Control.FromHandle(msg.HWnd) is the Button (or any control on your form) that has the focus when the CMD key is pressed
    Last edited by .paul.; Feb 3rd, 2022 at 03:05 PM.

  10. #10
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,689

    Re: Non-restricted movement between buttons

    To avoid blocking arrow key navigation on other controls on your form, such as ListBoxes, or DataGridViews...

    Code:
    Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Dim sy As Integer = -1
        Dim sx As Integer = -1
        sx = Array.IndexOf(buttons(0), Control.FromHandle(msg.HWnd))
        If sx > -1 Then
            sy = 0
        Else
            sx = Array.IndexOf(buttons(1), Control.FromHandle(msg.HWnd))
            If sx > -1 Then
                sy = 1
            Else
                sx = Array.IndexOf(buttons(2), Control.FromHandle(msg.HWnd))
                If sx > -1 Then
                    sy = 2
                Else
                    sy = -1
                End If
            End If
        End If
    
        Select Case keyData
            Case Keys.Up
                If sy = -1 Then Return False
                If sy = 1 Then
                    buttons(0)(sx).Select()
                End If
                If sy = 2 Then
                    buttons(1)(sx).Select()
                End If
                Return True
            Case Keys.Down
                If sy = -1 Then Return False
                If sy = 0 Then
                    buttons(1)(sx).Select()
                End If
                If sy = 1 Then
                    buttons(2)(sx).Select()
                End If
                Return True
            Case Keys.Left
                If sx = -1 Then Return False
                If sx = 1 Then
                    buttons(sy)(0).Select()
                End If
                If sx = 2 Then
                    buttons(sy)(1).Select()
                End If
                Return True
            Case Keys.Right
                If sx = -1 Then Return False
                If sx = 0 Then
                    buttons(sy)(1).Select()
                End If
                If sx = 1 Then
                    buttons(sy)(2).Select()
                End If
                Return True
        End Select
    
        Return False
    
    End Function

  11. #11

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Re: Non-restricted movement between buttons

    Wow thank you very much for your help! I really appreciate it.
    I will try it out tomorrow

  12. #12

    Thread Starter
    New Member
    Join Date
    Jan 2022
    Posts
    15

    Re: Non-restricted movement between buttons

    It worked! Thank you very much, Paul!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width