שתף באמצעות


How to make arrow keys act like tab key

Question

Thursday, October 31, 2013 1:07 AM

I am trying to make the down arrow/right arrow act like tab.  I am trying to make up arrow/left arrow act like shift tab.

any advice?

newbie

All replies (34)

Thursday, October 31, 2013 1:19 AM

I am trying to make the down arrow/right arrow act like tab.  I am trying to make up arrow/left arrow act like shift tab.

any advice?

newbie

Capture the KeyPress event and then call the key you want.

   Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

        Select Case thekeycode
            Case 27  '&H1B   'esc
                MasterControl(True)
                'cancel any following keys like tabcontrol right arrow
                e.Handled = True
            Case 33 'page up      'zoom out
                ToolBarCommands(7)
                e.Handled = True
            Case 34   'page down  'zoom in
                ToolBarCommands(6)
                e.Handled = True
            Case Else

          End Select
    End Sub

Thursday, October 31, 2013 1:36 AM | 1 vote

First you have to tell the form to process the arrow keys otherwise it won't.  Then you have to be sure to have the form preview the keys otherwise it won't handle keystrokes when a child control is selected.  With those two things in place you can then use the SelectNextControl method to do what the tab key does:

Public Class Form1
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        KeyPreview = True
    End Sub

    Protected Overrides Function IsInputKey(keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
            Case Keys.Left, Keys.Right, Keys.Up, Keys.Down
                Return True
            Case Else
                Return MyBase.IsInputKey(keyData)
        End Select
    End Function

    Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
        Select Case e.KeyCode
            Case Keys.Left, Keys.Up
                SelectNextControl(ActiveControl, False, True, False, True)
            Case Keys.Right, Keys.Down
                SelectNextControl(ActiveControl, True, True, False, True)
        End Select
        MyBase.OnKeyDown(e)
    End Sub
End Class

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Thursday, October 31, 2013 1:59 PM

I tried this code, but nothing happens at all.


Thursday, October 31, 2013 2:13 PM | 1 vote

Which code? Reed Kimbles code or tommytwotrains code. BTW tommy I'm in Elephant Butte.

When you respond it's better if you reference you you're responding to so everybody can tell which code you had an issue with.

And you can display your code using the Insert Code Block function (the little square button that looks like a sheet of paper with a left and right facing arrow on it in a posts forms header while a post is being created) so we can see what you tried also.

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Thursday, October 31, 2013 2:20 PM

I'm still getting used to these forums.  Thank you for the pointers.

I was referring to Reed's code.  After I add his code to my project the arrow keys still behave exactly the same as before.

I also want to clarify after a little more thought.  I want the behavior as follows.

up arrow to act like "shift+tab"

down arrow to act like "tab"

newbie


Thursday, October 31, 2013 2:24 PM

I tried this code, but nothing happens at all.

Yes, click the quote button and you get the little gray box like above. You will actually have to think about what you are doing to use mine as I just grabbed it, it does not do anything except show an example. Guess I should have done better. Reeds code looks like it will run.

Hi Reed! Hows the lake?

Tom


Thursday, October 31, 2013 2:51 PM

Why can't something simple like the following on the forms keydown?  Why won't this work?  I get an error that Keys.tab is not a method.  I could have sworn I did this much easier in VB6 about 15 years ago. 

        If Keys.Down Then
            Keys.Tab()
        End If


Thursday, October 31, 2013 2:56 PM

I'm still getting used to these forums.  Thank you for the pointers.

I was referring to Reed's code.  After I add his code to my project the arrow keys still behave exactly the same as before.

I also want to clarify after a little more thought.  I want the behavior as follows.

up arrow to act like "shift+tab"

down arrow to act like "tab"

newbie

Did you put the code in a Form?  Did you remember to turn on the Form's KeyPreview?

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Thursday, October 31, 2013 2:59 PM

Why can't something simple like the following on the forms keydown?  Why won't this work?  I get an error that Keys.tab is not a method.  I could have sworn I did this much easier in VB6 about 15 years ago. 

        If Keys.Down Then
            Keys.Tab()
        End If

Because Keys.Tab is just a value not a method; it doesn't actually "do" anything, it just represents a particular key value. -EDIT- oh and Keys.Down is not Boolean so it would need to be compared to something.

I suppose you could use SendKeys instead but what would be the point?  The tab key cycles through the active control on the form and that is also what SelectNextControl does so it would be much more efficient than SendKeys.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Thursday, October 31, 2013 3:56 PM

Hi,

 Reed`s code seems to work fine for me in a new form project so i would guess that you have something in your code or perhaps a property setting somewhere that is causing it not to work. Anyways, here is another example using the Forms KeyDown event to do it.

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        KeyPreview = True
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyCode = Keys.Up Then
            e.Handled = True
            SelectNextControl(ActiveControl, False, True, False, True)
        ElseIf e.KeyCode = Keys.Down Then
            e.Handled = True
            SelectNextControl(ActiveControl, True, True, False, True)
        End If
    End Sub
End Class

Thursday, October 31, 2013 8:19 PM

absolutely nothing happens when I press the down or up arrow key.


Thursday, October 31, 2013 8:42 PM

absolutely nothing happens when I press the down or up arrow key.

Hi,

 If you where replying to me and none of Reeds or my code is doing anything then i have to ask, did you try it by creating a new Windows Forms Application project and placing some controls on it and then pasting the code i gave into the forms code? I just want to make sure your not using WPF application or something and also i want to make sure it is not something else in your current project that is causing this.


Thursday, October 31, 2013 8:48 PM

if I try the following

        If e.KeyCode = Keys.Up Then
            SendKeys.Send(Keys.Tab)

        End If

Then press the up arrow key the number "9" is displayed in the text box instead of tabbing to the next text box.  Why?


Thursday, October 31, 2013 9:18 PM

You are correct.  I started a completely new project and added the code and it works perfectly.

what could be happening with my app?

James


Thursday, October 31, 2013 9:24 PM

I do have my text boxes within a group box.  Also, could the tab index or tab stop of the text boxes be affecting this?

James


Thursday, October 31, 2013 9:26 PM

If I put the text boxes inside of a group box the code stops working.  Any work around for this?

James


Friday, November 1, 2013 1:45 AM | 1 vote

If I put the text boxes inside of a group box the code stops working.  Any work around for this?

James

There's always a work around it just depends if anybody wants to apply themselves to the level necessary to figure out the answer which was not part of the original question. Also if you already received an answer to your original question please propose whoever answered your original question as the answerer.

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Friday, November 1, 2013 2:43 AM

Wait, I meant to say HI MonkeyBoy! Hows the lake?


Friday, November 1, 2013 3:52 AM

Wait, I meant to say HI MonkeyBoy! Hows the lake?

Well. It looks more like a pond than a lake nowadays. I think you could drive a 4X4 across most of it if you had tall enough tires!

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Friday, November 1, 2013 12:15 PM

Wait, I meant to say HI MonkeyBoy! Hows the lake?

Well. It looks more like a pond than a lake nowadays. I think you could drive a 4X4 across most of it if you had tall enough tires!

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

Yes, that is what I was wondering. I was hoping the water level went up some as we had good rain in Albuquerque over the summer. Well, my email is on the How to Order page of my web site if you want to chat. I have been impressed with your expertise in your answers here.

Tom


Friday, November 1, 2013 1:18 PM

If I put the text boxes inside of a group box the code stops working.  Any work around for this?

James

Hi,

 After doing some experimenting i have found that the Up, Down, Left, and Right arrow keys are already set up to work similar to the Tab and Shft+Tab and there does not seem to be a way to get the app to ignore them whether you use the KeyDown event, the Protected Overrides OnKeyDown, or the Protected Overrides WndProc. I tried using the (e.cancel and e.Handled) in the KeyDown and OnKeyDown. I also tried detecting the WM_KEYDOWN in the WndProc and just returning without processing the key press if it detected the Up or Down arrow keys and even that did not seem to stop the arrow keys from selecting the next or last control on the form. There may be a way but, i guess i have not figured it out yet. I kind of had it working by using SendKeys to send a Tab or Shft+Tab but, in the reverse direction it stops at every control even in a groupbox and then going forward threw them it seemed to skip rite over the whole goroupbox. It is strange that it does this. Of coarse maybe i am overlooking something and someone else might know how to make the form ignore the Up or Down keys. If i find an answer i will be back.    :)


Friday, November 1, 2013 3:06 PM

Wait, I meant to say HI MonkeyBoy! Hows the lake?

Well. It looks more like a pond than a lake nowadays. I think you could drive a 4X4 across most of it if you had tall enough tires!

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

Yes, that is what I was wondering. I was hoping the water level went up some as we had good rain in Albuquerque over the summer. Well, my email is on the How to Order page of my web site if you want to chat. I have been impressed with your expertise in your answers here.

Tom

All right. Sounds good. I'll get hold of you in a day or two. Thanks!

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Friday, November 1, 2013 3:27 PM

I do have my text boxes within a group box.  Also, could the tab index or tab stop of the text boxes be affecting this?

James

Look at the documentation for SelectNextControl.  You can see the example code is passing four boolean parameters after the starting control; what do you think they might do?

If you change the "nested" parameter to True, then controls inside of controls will also be selected.  This can affect the overall tab order and you may need to exclude certain controls (set their TabStop to false) before things flow just the way you want (hence this parameter being set to False in the example code).

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Friday, November 1, 2013 5:03 PM

Look at the documentation for SelectNextControl.  You can see the example code is passing four boolean parameters after the starting control; what do you think they might do?

If you change the "nested" parameter to True, then controls inside of controls will also be selected.  This can affect the overall tab order and you may need to exclude certain controls (set their TabStop to false) before things flow just the way you want (hence this parameter being set to False in the example code).

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

Hey Reed,

 I tested your code in a new form project and set the "nested" parameter to True last night and it does the same thing as the test i did using SendKeys. As you go threw the controls in reverse it will select every control even in the groupbox but, if you go forward it skips past the groupbox. I have all tabstops set to true and are all in the correct tabindex order and used the code below. I even tried with the e.handled and e.suppressKeyPress set true. I am starting to think its a bug or something because i have tried all kinds of different approaches with no success so far. Then again maybe i am overlooking something.   :)

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        KeyPreview = True
    End Sub

    Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
            Case Keys.Up, Keys.Down
                Return True
            Case Else
                Return MyBase.IsInputKey(keyData)
        End Select
    End Function

    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        Select Case e.KeyCode
            Case Keys.Up
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextControl(ActiveControl, False, True, True, True)
            Case Keys.Down
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextControl(ActiveControl, True, True, True, True)
        End Select
        MyBase.OnKeyDown(e)
    End Sub
End Class

Friday, November 1, 2013 8:35 PM | 1 vote

There does seem to be something buggy with the first container on a form...  and using SendKeys has the exact same buggy behavior as calling SelectNextControl directly.  I'm not quite sure what is causing it...

-EDIT-

Actually it appears to be caused by the default arrow key behavior so a control which does not accept key input cannot precede a container control or the focus will shift twice, skipping over the contents of the container.  So I guess it's going to depend on the control layout.

There might be another way to go about this by manipulating Windows messages, but I'm not sure.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Friday, November 1, 2013 10:09 PM

There does seem to be something buggy with the first container on a form...  and using SendKeys has the exact same buggy behavior as calling SelectNextControl directly.  I'm not quite sure what is causing it...

-EDIT-

Actually it appears to be caused by the default arrow key behavior so a control which does not accept key input cannot precede a container control or the focus will shift twice, skipping over the contents of the container.  So I guess it's going to depend on the control layout.

There might be another way to go about this by manipulating Windows messages, but I'm not sure.

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

I looked into System messages and actually got the tab, not shift tab, but tab working. However you actually have to designate the control that the tab is to be used on that will cause focus to skip to the next control. Unfortunately textboxes have IntPtrs/hWnds or handles or whatever but the same name as far as system messages and SPY++ showed. Therefore you need the actual IntPtr/hWnd of the control that you want the message sent to perform it's action on. The problem with that is you can get all the IntPtrs for the child controls but you have no idea which one you are sending the tab message to so they would be out of sequence at best. I looked into it fairly thoroughly although I'm no expert in that area. But SPY++ would only show the hWnd or Class but not the controls Caption which I assume would be the controls name like TextBox1 or whatever. As it did show Form1 for the caption for a Form. And the messages themselves that I was capturing would have the x, y coordinates of the control the message was being sent to or received from. So after about 6 hours of that I gave up. Although system messages are pretty neat to work with except I could see how they could be pretty dangerous just by accidentally entering valid fields that mean something way different than what you want and cause something to perform something that would be very regrettable real quick.

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Saturday, November 2, 2013 5:26 AM

It will definitely be an at least somewhat involved process, and you've certain noted the potential downsides.

Every control should expose its handle as a property so that would give you the IntPtr you need for a specific control.  Or it may do to use Win32 API calls to get the focused control's handle (pretty sure there's a call for that... a form of FindWindowEx or something, I'd have to go look).

I kind of think that at then end of the day though it all comes down to a form design and layout which will work for this logic.  Depending on the controls involved the form may already cycle through everything using the arrow keys without any extra code; it just depends on whether we are talking about a bunch of buttons or a bunch of textboxes.  If its both then the whole thing probably isn't the best idea (imagine the frustration of trying to arrow back a character in a textbox).

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Monday, November 4, 2013 9:22 PM

I just got back in from out of the office.

I don't want to manipulate the left or right arrows.  I only want to manipulate the up/down arrows to act like a shift+tab/tab since the up/down arrow keys do not do anything right now.  It's just not very user friendly so I want to change that.

I have text boxes within frames (group box).  I cannot get any recommended solutions to work if the text controls are within a frame.

As mentioned above it seems buggy.  This really shouldn't be that difficult even for a newbie like me.


Monday, November 4, 2013 9:35 PM

I am seeing some strange behavior now.  I inserted the following code again.  Now the arrow keys will move between text controls.  But when I get to a particular frame it gets caught in a loop in that frame.  In other works when I get to that frame and press arrow down it will go to the next text control until it gets to the last text control in that frame.  then if I press arrow down again it will go back to the first text control within that frame instead of going to the text box within the next frame.  There are other weird behaviors when the focus seems to set on an option button with in a frame.  Any ideas?

    Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
            Case Keys.Up, Keys.Down
                Return True
            Case Else
                Return MyBase.IsInputKey(keyData)
        End Select
    End Function

    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        Select Case e.KeyCode
            Case Keys.Up
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextControl(ActiveControl, False, True, True, True)
            Case Keys.Down
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextControl(ActiveControl, True, True, True, True)
        End Select
        MyBase.OnKeyDown(e)
    End Sub


Monday, November 4, 2013 9:48 PM

What is a frame? The only frames I know about are for holding things on a wall or for a house or a segment of video or something.

Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


Monday, November 4, 2013 9:51 PM

lol...good one!  If I recall properly, VB6 referred to what is now called "group boxes" as "frames"


Tuesday, November 5, 2013 4:55 PM

Part of the issue is ensuring the TabIndex values of each textbox are incremental.  Note that when you add a textbox to a container (like a groupbox) the TabIndex restarts at 0 for controls within the container.

If you are only interested in navigating between textboxes then it might be best to just gather all of them into a single list and manually switch over them yourself.  Here's an example (again, make sure you've explicitly set the TabIndex of each textbox in the order desired).

Public Class Form1
    Private _AllTextBoxes As New List(Of TextBox)
    Private _FocusIndex As Integer

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        KeyPreview = True
        FindAllTextBoxes(Me)
        _AllTextBoxes.Sort(New Comparison(Of TextBox)(Function(tb1 As TextBox, tb2 As TextBox) tb1.TabIndex.CompareTo(tb2.TabIndex)))
        _AllTextBoxes(0).Focus()
    End Sub

    Private Sub FindAllTextBoxes(container As Control)
        For Each c As Control In container.Controls
            If TypeOf c Is TextBox Then
                AddHandler c.GotFocus, AddressOf TextBox_GotFocus
                _AllTextBoxes.Add(c)
            Else
                FindAllTextBoxes(c)
            End If
        Next
    End Sub

    Private Sub SelectNextTextBox(forward As Boolean)
        If forward Then
            _FocusIndex += 1
        Else
            _FocusIndex -= 1
        End If
        If _FocusIndex < 0 Then _FocusIndex = _AllTextBoxes.Count - 1
        If _FocusIndex = _AllTextBoxes.Count Then _FocusIndex = 0
        _AllTextBoxes(_FocusIndex).Focus()
    End Sub

    Private Sub TextBox_GotFocus(sender As Object, e As System.EventArgs)
        _FocusIndex = _AllTextBoxes.IndexOf(CType(sender, TextBox))
    End Sub

    Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
            Case Keys.Up, Keys.Down
                Return True
            Case Else
                Return MyBase.IsInputKey(keyData)
        End Select
    End Function

    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        Select Case e.KeyCode
            Case Keys.Up
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextTextBox(False)
            Case Keys.Down
                e.Handled = True
                e.SuppressKeyPress = True
                SelectNextTextBox(True)
        End Select
        MyBase.OnKeyDown(e)
    End Sub

End Class

Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


Wednesday, November 6, 2013 4:59 AM

Hi,

 The only way i found so far to actually get the result you want is by using a low level keyboard hook. I made a Class Library using one that will stop the up/down keys from being processed by your form and then use Sendkeys to simulate the Tab keys being pressed. I made it so that when you start it you have to give it a handle to the form you want the keys to be changed for. This way it does not effect other apps that use the arrow keys. If your interested then you can download the Class Library project named ArrowKeys from here on SkyDrive. Being it is a dll you may want to open the project and rebuild it if you want to be on the safe side. After that you can test it out by creating a new Form project and adding Reference to it by going to the VB menu and clicking (Project) and then (Add Reference...). Then select the (Browse) tab and browse to the dll file in the (ArrowKey\ArrowKey\bin\Release) folder and select it. Now you can add a few controls on the form including a groupbox with a few controls in it and use the code below to create the new class and start/stop it.

Public Class Form1
    Dim ak As New ArrowKey.UpDownTabs

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ak.StartKeySwap(MyBase.Handle) 'Start sending Tab Keys instead of using the Up/Down keys for this form
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        ak.StopKeySwap() 'Stop sending the Tab Keys for this form. DONT FORGET TO STOP IT WHEN THE FORM IS CLOSING
    End Sub
End Class

Wednesday, November 6, 2013 12:58 PM

 After thinking about it, it may be easier for you to just add a module to your program and use the code below in the module. You can add a module by going to the VB menu and clicking (Project) and then (Add Module...). This way you don`t need to add a reference to a class library and it is not cluttering up your forms code.

Imports System.Runtime.InteropServices

Module Module1
    Private Const WM_KEYDOWN As Integer = &H100
    Private Const WH_KEYBOARD_LL As Integer = 13
    Private hKeyboard As IntPtr = IntPtr.Zero
    Private hExe As IntPtr = IntPtr.Zero

    <DllImport("user32.dll", EntryPoint:="SetWindowsHookExW")> _
    Private Function SetWindowsHookExW(ByVal idHook As Integer, ByVal lpfn As KeyboardHookDelegate, ByVal hMod As System.IntPtr, ByVal dwThreadId As UInteger) As System.IntPtr
    End Function

    <DllImport("user32.dll", EntryPoint:="UnhookWindowsHookEx")> _
    Private Function UnhookWindowsHookEx(ByVal hhk As System.IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    <DllImport("user32.dll", EntryPoint:="CallNextHookEx")> _
    Private Function CallNextHookEx(ByVal hhk As System.IntPtr, ByVal nCode As Integer, ByVal wParam As System.IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
    End Function

    <DllImport("user32.dll", EntryPoint:="GetForegroundWindow")> Private Function GetForegroundWindow() As System.IntPtr
    End Function

    <DllImport("kernel32.dll", EntryPoint:="GetModuleHandleW")> _
    Private Function GetModuleHandleW(<InAttribute(), MarshalAs(UnmanagedType.LPTStr)> ByVal lpModuleName As String) As System.IntPtr
    End Function

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure KBDLLHOOKSTRUCT
        Public vkCode As UInteger
        Public scanCode As UInteger
        Public flags As UInteger
        Public time As UInteger
        Public dwExtraInfo As UInteger
    End Structure

    <MarshalAs(UnmanagedType.FunctionPtr)> Private callback As New KeyboardHookDelegate(AddressOf KeyboardCallback)

    Private Delegate Function KeyboardHookDelegate(ByVal nCode As Integer, ByVal wParam As System.IntPtr, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
    Private Function KeyboardCallback(ByVal nCode As Integer, ByVal wParam As System.IntPtr, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
        If nCode = 0 Then
            If wParam.ToInt32 = WM_KEYDOWN AndAlso GetForegroundWindow().Equals(hExe) Then
                Dim e As New KeyEventArgs(CType(lParam.vkCode, Keys))
                If e.KeyCode = Keys.Up Then
                    SendKeys.Send("+{TAB}")
                    Return 1
                ElseIf e.KeyCode = Keys.Down Then
                    SendKeys.Send("{TAB}")
                    Return 1
                End If
            End If
        End If
        Return CallNextHookEx(hKeyboard, nCode, wParam, lParam)
    End Function

    Public Function StartKeySwap(ByVal FormHandle As IntPtr) As Boolean
        hExe = FormHandle
        hKeyboard = SetWindowsHookExW(WH_KEYBOARD_LL, callback, GetModuleHandleW(Nothing), 0)
        If Not hKeyboard.Equals(IntPtr.Zero) Then Return True
    End Function

    Public Function StopKeySwap() As Boolean
        Return UnhookWindowsHookEx(hKeyboard)
    End Function
End Module

Then you can use this code in the Forms code to start and stop the Arrow keys from being used like Tab and Shft+Tab for your program.

Public Class Form1

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Module1.StopKeySwap() 'Make sure you stop it when the form is closing
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Module1.StartKeySwap(MyBase.Handle)
    End Sub
End Class