Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Keydown with up and down arrows

Posted on 2005-04-06
12
Medium Priority
?
507 Views
Last Modified: 2012-06-27

I need to use intercept the up and down arrow keystrokes.  I am using the keypreview on the form, and It works some of the time.  When ever other things get the focus set I no longer find out when the user hits the arrow keys.  

Is there any way to find out anytime the user pushes the up or down arrows regardless of where the foucs is set?

Thanks,
Tom
0
Comment
Question by:Tom_Hickerson
  • 6
  • 5
12 Comments
 
LVL 5

Expert Comment

by:Rubyn
ID: 13719818
Do you need to find out the keystokes even if the focus is out of your application?
0
 
LVL 1

Author Comment

by:Tom_Hickerson
ID: 13719898
No.  Just while the form is being displayed, and something on the form has the focus
0
 
LVL 5

Expert Comment

by:Rubyn
ID: 13719955
Use KeyPreview of Form true. Then place the code in KeyUp event of the form
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:Tom_Hickerson
ID: 13720091
I have an array of checkboxes, and when I click on one of the chekboxes then press the arrow up or down keys the procedure in the form key up event does not execute.

Try this...
put a list box and 3 checkboxes on a form

add this code, and set the KeyPreview to true.
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
List1.AddItem KeyCode
End Sub

Now click on check2, and press the up or down arrow key.  I get nothing on the list box unless I have gone past the checkboxes with the up or down arrow.  


Tom  
0
 
LVL 8

Expert Comment

by:List244
ID: 13720251
Tom_H, here is an idea:

Private LClick As Integer
Private Sub Check1_GotFocus(Index As Integer)
If Index > LClick Then
        Form_KeyUp vbKeyDown, 0 'The down arrow key must have been pressed
End If
If Index < LClick Then
        Form_KeyUp vbKeyUp, 0 'Up arrow was pressed
End If
LClick = Index
End Sub

Private Sub Check1_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
LClick = Index 'Use mouse down because it works BEFORE gotfocus, where click does not.
'The above line makes sure that clicks do not count as pressing up/down arrow keys in the gotfocus sub
End Sub

Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
List1.AddItem KeyCode
End Sub

That should create for you check boxes that report keyup, and keydown.
0
 
LVL 1

Author Comment

by:Tom_Hickerson
ID: 13720393

list244,

While you solution does solve the problem with my above example it does not solve the problem with my original code.  I still have problems with keypress events after command buttons are pressed also.  I could also use something like you indicated for every control, or do somthing like text1.setfocus at the end of every procedure, but I wanted something cleaner that I could add more controls without fixing code for each control.  It might not exist, but I wanted to see if anyone had any ideas.  If I don't get any solutions I will accept your answer.  

Thanks,
Tom

0
 
LVL 5

Accepted Solution

by:
Rubyn earned 2000 total points
ID: 13720675
Option Explicit

Public Const VK_UP = &H26
Public Const VK_DOWN = &H28

Private Const WH_KEYBOARD_LL = 13&
Private Const HC_ACTION = 0&

Private Type KBDLLHOOKSTRUCT
  vkCode As Long
  scanCode As Long
  flags As Long
  time As Long
  dwExtraInfo As Long
End Type

Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal cb As Long)

Private m_hDllKbdHook As Long

Public Sub HookStart()
   Let m_hDllKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0&)
End Sub

Public Sub HookStop()
    Call UnhookWindowsHookEx(m_hDllKbdHook)
End Sub

Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static kbdllhs As KBDLLHOOKSTRUCT
    If nCode = HC_ACTION Then
        If Not Screen.ActiveForm Is Nothing Then
            Call CopyMemory(kbdllhs, ByVal lParam, Len(kbdllhs))
            If kbdllhs.vkCode = VK_UP Then Call Screen.ActiveForm.Form_KeyUp(vbKeyUp, 0)
            If kbdllhs.vkCode = VK_DOWN Then Call Screen.ActiveForm.Form_KeyUp(vbKeyDown, 0)
        End If
    End If
    Let LowLevelKeyboardProc = CallNextHookEx(m_hDllKbdHook, nCode, wParam, lParam)
End Function
0
 
LVL 5

Expert Comment

by:Rubyn
ID: 13720703
You create a module and paste the above code.
On the startup form on form_load call HookStart and in form_unload call HookStop
Make the Form_KeyUp public
0
 
LVL 5

Expert Comment

by:Rubyn
ID: 13720748
I forgot to include On Error Resume Next. So if the form doesn't have the keyup event the application will not crash.

Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static kbdllhs As KBDLLHOOKSTRUCT
On Error Resume Next
....
End Function
0
 
LVL 1

Author Comment

by:Tom_Hickerson
ID: 13720814
I am getting an error in the public hookStart...

Compile Error:
Invalid use of AddressOf operator


0
 
LVL 5

Expert Comment

by:Rubyn
ID: 13720831
Did you paste the above code in a module?
0
 
LVL 1

Author Comment

by:Tom_Hickerson
ID: 13720907
No I did not.  It is working now.  Thanks.  I was also searching google groups, and I just came across this one that uses a timer and an api call.  It works also.

Private Declare Function GetAsyncKeyState _
  Lib "user32" (ByVal vKey As Long) As Integer
Private keymap(37 To 40) As Boolean
Private LastKey As Integer

Private Sub Form_Load()
  Timer1.Interval = 50
End Sub


Private Sub Timer1_Timer()
  Dim n As Long
  For n = 37 To 40
    ' This will work for the arrow keys only '
    If GetAsyncKeyState(n) And &H8000 Then
      If n <> LastKey Then
        List1.AddItem n
        LastKey = n
      End If
    End If
  Next n
  ' Remove key from last key if it has been lifted '
  If (GetAsyncKeyState(LastKey) And &H8000) Then
  Else
    LastKey = 0
  End If
End Sub

Thanks for the help guys,
Tom
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month21 days, 3 hours left to enroll

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question