Avatar of Kazari
Kazari asked on

PostMessage WM_KEYDOWN with Shift/Ctrl/Alt + Key

Hi,

I'm working on an automation application for a proprietary windows-based host emulator in Windows XP.  The application is written in VB6 and works well at passing keys to the host emulator using WM_KEYDOWN messages via PostMessage API calls.  The problem that I have is that I don't know how to send keys that have a Shift/Ctrl/Alt component.  For example, the following works great:

     PostMessage hWnd, WM_KEYDOWN, vbKeyC, &H1&                    '  Lowercase "c"
     PostMessage hWnd, WM_KEYDOWN, vbKeyUp, &H1&                  '  Up Arrow key
     PostMessage hWnd, WM_KEYDOWN, vbKeyPageDown, &H1&       '  Page Down key

How do I do the same for Shift-c (Capital C), Shift-ArrowUp, Ctrl-PgDn, or Alt-c?  Posting a WM_KEYDOWN message for vbKeyShift/vbKeyControl has no effect before any of the above.  The result is the same (unshifted).

Before anyone asks, I do not wish to change the focus from my application to the host when sending each key.  (The application controls several host windows at the same time.)  PostMessage does exactly what I want, except I can't figure out how to Shift/Ctrl/Alt the keys.

Any help would be appreciated...

E.
Visual Basic Classic

Avatar of undefined
Last Comment
jsw3nson

8/22/2022 - Mon
AlexFM

Since WM_KEYDOWN message parameters don't contain information about pressed Ctrl and Shift keys, it is impossible.
To post Alt+... use WM_SYSKEYDOWN messages.

ASKER
Kazari

I'm pretty new to API programming as well as bit-manipulation.  It looks like WM_SYSKEYDOWN sent via PostMessage might do the trick, but I am not sure how to format the lParam parameter to pass the proper Shift/Ctrl/Alt information.

How would I go about defining lParam, setting bit values, and sending WM_SYSKEYDOWN messages to the host emulator that correspond to the following four examples:

     Shift-c (Capital C), Shift-ArrowUp, Ctrl-PgDn, or Alt-c?

Thank you for your help!
AlexFM

You can post WM_SYSKEYDOWN message to get Alt+... combination (exactly as you do this with WM_KEYDOWN). It's impossible to post Shift+ and Ctrl+ combinations using WM_KEYDOWN and WM_SYSKEYDOWN because they don't contain such information. If you write that posting a WM_KEYDOWN message for vbKeyShift/vbKeyControl before other keys has no effect, you need to set keyboard focus to the target window and use VB SendKeys function. I don't see another way.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
ASKER
Kazari

Argh.  I was hoping to avoid setting focus.  It is important that my application retains focus in *real-time*, traps *all* keys and sends specific keydown messages to the appropriate background host session window.  The application manages four separate host sessions.  If I lose focus to a host, I lose the ability to trap keys independent of the host windows and any keys that I press in the meantime may unavoidably go to the wrong host session while focus is away from my application.  (I hope that makes sense.)

Having said that, is there a way to accomplish what I need within windows?  PostMessage WM_KEYDOWN gets me 80% to where I want to be.  I can do Shift-AlphaChars that way with no problem as well, I guess.  WM_SYSKEYDOWN may be able to handle ALT, but I'm still stumped on putting this all together...

My code looks similar to the following (without getting into the actual host window selection code, Index is passed ficticiously below to identify the host window):

Private Sub txtTrap_KeyDown(Index as Integer, KeyCode As Integer, Shift As Integer)

    Dim hWnd As Long
    Dim ShiftDown, CtrlDown, AltDown As Boolean
   
    ShiftDown = (Shift And vbShiftMask) > 0
    CtrlDown = (Shift And vbCtrlMask) > 0
    AltDown = (Shift And vbAltMask) > 0
   
    hWnd = FindWindow(vbNullString, "HostSession" & Str(Index))
   
    If hWnd <> 0 Then
        If ShiftDown Then PostMessage hWnd, WM_KEYDOWN, vbKeyShift, &H1&       ' <--- Does Not Work

        If AltDown Then
             PostMessage hWnd, WM_SYSKEYDOWN, KeyCode, <lParam?>    ' Post message with Alt key flag as per AlexFM?
             PostMessage hWnd, WM_SYSKEYUP, KeyCode, <lParam?>
        Else
             PostMessage hWnd, WM_KEYDOWN, KeyCode, &H1&                 ' Post message with key code
             PostMessage hWnd, WM_KEYUP, KeyCode, &HC0010001
        End If

        If ShiftDown Then PostMessage hWnd, WM_KEYUP, vbKeyShift, &HC0010001   ' <--- Does Not Work
    End If
End Sub

Also, as I look at it now... can WM_SYSKEYDOWN be used to send a message to a window that does not have focus?  The little I surmised from the bits and pieces of documentation I found states that it is used to send message to the window with the current focus.  So many questions...  <sigh>
AlexFM

>> Can WM_SYSKEYDOWN be used to send a message to a window that does not have focus?
I don't know exactly, just try this.

By the way, what a the values if lParam when you send Shift key? What is H1, for example? Try to see real lParam values using Spy++.
AlexFM

For example, I see in Spy++:
00360001 (DOWN)
C0360001 (UP)
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
joboy

Public Const KEYEVENTF_EXTENDEDKEY = &H1
Public Const KEYEVENTF_KEYUP = &H2
Public Const VK_SHIFT = &H10
Public Const VK_CONTROL = &H11

Public Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

You can use the above keybd_event API to turn the shift key's, etc state on an off

Use it in a similar way to you previous post i.e.
  If hWnd <> 0 Then
       If ShiftDown Then keybd_event vk_shift, 0,0,0

       If AltDown Then
             PostMessage hWnd, WM_SYSKEYDOWN, KeyCode, <lParam?>    ' Post message with Alt key flag as per AlexFM?
            PostMessage hWnd, WM_SYSKEYUP, KeyCode, <lParam?>
       Else
            PostMessage hWnd, WM_KEYDOWN, KeyCode, &H1&                 ' Post message with key code
            PostMessage hWnd, WM_KEYUP, KeyCode, &HC0010001
       End If

       If ShiftDown Then keybd_event vk_shift,0, KEYEVENTF_KEYUP,0
   End If
End Sub
ASKER
Kazari

The above keybd_event code takes care of the Shift/Ctrl issues beautifully so far... thanks, joboy!  I still have to test it under actual use, as I'm concerned that the keybd_event keys may interfere with *real-time* keyboard events that are coming in all the time.

I still have a problem with the WM_SYSKEYDOWN/UP messages not working for Alt + KeyCode.  I'd appreciate some help formatting the messages.
ASKER CERTIFIED SOLUTION
joboy

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
Kazari

Sorry about the delay but was out of town for a bit and other work took priority on return...  Still having trouble with a couple of items:

1.  Posting WM_CHAR works great, except for the SPACE key (32).  Any suggestions?  I suppose I can test for SPACE and use WM_KEYDOWN instead of WM_CHAR in code.  Just found it strange that it does not work.

2.  I'm getting interference from *real time* keys when using keybd_event to send keys to background windows.  For example, if I am trapping a Ctrl-O and want to send a Shift-F10 to all host emulator windows, the Ctrl key is down (physically) and a Ctrl-Shift-F10 gets sent to the background windows, instead of Shift-F10.  (Joeseph's code works well when it is executed from a button click event when no keys are being pressed by the user.)

Anyone have a way to send specific WM_KEYDOWN messages for Shift/Ctrl + key to hWnd in the background w/o a general keyboard event?

Joeseph, you're getting partial credit so far for getting me as far as you have.  Thank you.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
ASKER
Kazari

No further replies...  I'd like to reduce the points to 100 and give them to Joseph for his partial answer unless someone has more to offer.

Thanks again, Joseph.
srimanth

No Comment has been added lately, so it's time clean to up this TA.
I will leave a recommendation in the CleanUp topic area:
[Reduce points to 100 -> Accept joboy's comment as answer]
Please leave any comments here within the next seven days.

Visit the URL if u require help on closing the question.
https://www.experts-exchange.com/help/closing.jsp

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

srimanth
EE CV
jsw3nson

Kazari,

If you found a solution, you can get some easy points by helping me out...

https://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_21590264.html
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.