4
votes

first time posting, fairly new to VBA and coding.

I have an Excel 2010 userform with a button to open a spreadsheet. I have the button create a new file instead, when a modifier key is held down.

I wrote the following code:

Private Sub CommandButton4_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Debug.Print "X" & Shift
If Shift = 4 Then
    CommandButton4.Caption = "New File"
    NewFile = True
    CommandButton4.ControlTipText = "New File"
End If
End Sub

Private Sub CommandButton4_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Debug.Print "Y"
CommandButton4.Caption = "Open File"
NewFile = False
CommandButton4.ControlTipText = "Open File"
End Sub

For every key EXCEPT Alt, both KeyDown and KeyUp events fire. For example, pressing Shift, I get a debug output: X1 Y X1 Y

However, pressing Alt I get: X4 Y Y X4 Y Y

Everything else in my form works correctly, but I have no idea why every other Alt KeyDown isn't registering. How can there be a KeyUp without a KeyDown?

I've searched high and low for an answer, bug report, or fix and can't find one. Any ideas?

1

1 Answers

2
votes

You can solve your challenge easily with an API call to detect if the ALT key is down.

Insert this into a new module

Public Declare Function GetKeyState Lib "user32" (ByVal key As Long) As Integer

and try this:

Private Sub CommandButton1_Click()
    If GetKeyState(KeyCodeConstants.vbKeyMenu) And &H8000 Then
        MsgBox "Yes"
    Else
        MsgBox "no"
    End If
End Sub

vbKeyMenu is the ALT key. The And &H8000 is required to look at the 'live' keystate only (the return value has another bit that is toggled on and off, see here)

EDIT: The Phenomenon you're seeing is the following:
After you press ALT and see X4 Y, press the down key. You'll see the userform's system menu pop up. The alt key follows it's purpose and moves the focus to the system menu and back to the button on the next press. If the Button has the focus, the userform obviously handles the keypress first and moves the focus to the system menu before the button receives a keydown.