Link to home
Start Free TrialLog in
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.
Avatar of AlexFM
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.

Avatar of Kazari

ASKER

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!
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.
Avatar of Kazari

ASKER

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>
>> 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++.
For example, I see in Spy++:
00360001 (DOWN)
C0360001 (UP)
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
Avatar of Kazari

ASKER

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
Avatar of joboy
joboy

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Kazari

ASKER

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.
Avatar of Kazari

ASKER

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.
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
Kazari,

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

https://www.experts-exchange.com/questions/21590264/Send-Alt-key-to-a-window.html