Link to home
Start Free TrialLog in
Avatar of obregoru
obregoru

asked on

Postmessage, Shift Key & control Key usage

I'm using VB6, but y'all should be able to answer this.

I tried to use the postmessage command to send keystrokes to MS Word 97 (I'm using Word 97 as a test of my program) from a VB program.  I used the WM_KEYDOWN, WM_CHAR, and WM_KEYUP            commands.

                (I'm not creating a process instance, I'm just grabbing the hwnd of an already open app.)

                The order of messages are:
                1.  WM_KEYDOWN shift
                2.  WM_KEYDOWN "A"
                3.  WM_CHAR "A"
                4.  WM_KEYUP "A"

What happens is that a capital A and a lowercase a is sent.  When I remove the WM_CHAR,  only one a is sent (lower case).  When I put the caps lock on, then a capital A is sent.  All of the values are &H41 (65 , letter A).

                My suspiscion is that when I send the shift message, it doesn't "hold" while the next message is               being sent, ie, when I send the a, it checks that status of the shift key.

                I'm not sure if this is the way MS Word handles keystrokes, but I need to be able to send               keystrokes this way (not via Sendkeys or COM or any way.  I WANT to use the post message way).

                My question is, how do I force Shift and letter combinations, and especially, how do I force                 Control and letter combinations via postmessage/sendmessage  (send message won't work)?  Do I have to force  a caps locks?  What about CTRL, since there is no CTRL lock?  

                There are some apps besides Word that I need to send control combinations (ie CTRL + Z)

                Thanks,
                Ruben
Avatar of AlexVirochovsky
AlexVirochovsky

Easiest way to make it: using kebd_event function!
Example:
keybd_event('A', 'A',KEYEVENTF_KEYUP, 0);
See Windows doc about more deatiles:
Other possibility: use SetKeyboardState(for set many
codes).
Good Luck, Alex
Avatar of obregoru

ASKER

I need some sample code of this actually happening.  I don't know if I can use keybd_event or setkeyboard state for other tasks.

I tried the following (&H105D4 is the hwnd to Document 1 in word.) and it still gave me lower case keystrokes in the document.  (Seems to work in the VB environment, status of shift is true when the code runs.)


keybd_event(&H10, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0) 'shift down
PostMessage(&H105D4, WM_KEYDOWN, &H41, &H1E0001)  'A down
PostMessage(&H105D4, &H101, &H41, &HC01E0001) 'A up
Call keybd_event(&H10, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0) 'shift up

Tried all keybd_events instead of postmessages, no luck!
(I'm in NT4).  Maybe I'm passing the wrong paramters (the hwind is correct).

I need to use VB as a "front" end and send keystroke combinations to another application, such as Word 97.  (I can't use VB sendkeys.)

This seems to be difficult, so I'm increasing to points to 500.

Thanks.
Try setting the focus to the window prior to calling keybd_event().

The problem with posting/sending keyboard messages to an app is that its internal keyboard state doesn't get updated right.  Thus you can usually send simple keystrokes with decent results, but complex keystrokes, like ones involving contro andlor /shift can get messed up.  This depends on both the keystroke being send and the application that reads it (It depends on the code the app uses to handle the key.)  For this reason, your best bet is to use keybd_event(0 as it does update the internal keystate information.  It is completely reliable, whereas sending key messages is a little unpredictable.  The only hitch is that the application you want to have receive the key must have the focus.
You are always sending A (65) this is a capital letter.  If you use Shift you are asking for a lowercase a.  

A = 65
a = 97

You seem to be getting exactly the behavior you asked for.
That is why when you have caps lock on it came out as a capital letter.  Try it on your PC in a text editor.  As expected pressing the 'a' key will give you a lower case a. Pressing Shift+a gives you a capital A.  With Caps Lock on pressing 'a' gives you a capital A while pressing Shift+'a' gives you a lower case a.

Seems like you need to be sure whether you want to send upper or lower case of your keys. (I believe you will want lowercase as your default?)


>>Try setting the focus to the window prior to calling >>keybd_event().
Of couse, thui is right. Using keybd_event exectly equal
pressing key of Keyboard and only Active Windows get it!
Using SendMessage not so good, becouse , for example,
for sending 1 symbol  must use 4 SendMessage!

Here is the code to do it:

(The question was answered in the VB forum)

Thanks for the help anyway.


Private Declare Sub keybd_event Lib "user32" _
                                (ByVal bVk As Byte, _
                                ByVal bScan As Byte, _
                                ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
                                 
Private Declare Function FindWindow Lib "user32" Alias _
                                "FindWindowA" (ByVal lpClassName As String, _
                                ByVal lpWindowName As String) As Long
Private Declare Function SetFocusX Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
                  'setfocus is a VB reserved word, so we give it a new name
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

    Const VK_SHIFT = &H10
    Const KEYEVENTF_EXTENDEDKEY = &H1
    Const KEYEVENTF_KEYUP = &H2


Dim h As Long

         h = FindWindow(vbNullString, "Microsoft Word - Document2")
         If h = 0 Then
           MsgBox "Error: Invalid Handle"
           Exit Sub
         End If


         Call SetFocusX(h)
         Call SetForegroundWindow(h)
         Call keybd_event(&H10, 0, KEYEVENTF_EXTENDEDKEY, 0)
         Call keybd_event(65, 0, 0, 0)
         Call keybd_event(65, 0, KEYEVENTF_KEYUP, 0)
         Call keybd_event(&H10, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)

As I understand, you use keybd_event(my reply, that
you rejected, + nietod comment ) + SetFocus (from thui comment) and win!
Nu, and what you want make with Q? Dou you think,
that someone helps you(in such case you must point
out, who can submit Q), or you must cancel Q, if you
think, that anyone don't helps you!
Alex
yeah, but you gave me a B not an A... what's up with that?
ASKER CERTIFIED SOLUTION
Avatar of AlexVirochovsky
AlexVirochovsky

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
Alex, this is the second time you do this nasty trick.. Didn't you understand that the question has been answered by me already? Your answer should be rejected now!! That's just not right...

..-=ViKtOr=-..
Vikror, can be you reply in VB , but not here! Here
i post absolutly right reply for C++. Obregoru
can't use it in VB, may be, but it is C++ forum, not VB!!!!
Alex, I SAID IT ALREADY... I had answered the question while you were still wondering here... The thing is that I saw it in the VB area first... I could've LOCKED UP both questions my self but I didn't do it so this guy can get his points back... he already paid once, and there is no need to do it twice... OBREGORU, PLEASE REJECT ALEX'S ANSWER>>> HE SHOULD LEARN HOW E-E WORKS FIRST, AND THEN ANSWER....

btw, This is your second time (that ive seen you do it).... please be more careful... and this questions should be rejected... or I'll talk to Linda myself....

..-=ViKtOr=-..
Viktor, dou you understand, what you prepose?
Every expert, before reply to Q, must test: can be in
VB, Windows, Delfi, OWL, ... someone submit
same Q , and only after this reply!
This is a little hard, a?
Right way: if you see, that such Q have double,
you simply right  : Attentions, experts, it is double!
This way use Nietod, Chensu, AlexO, my modest person
and many others(but not you)!
Alex, what the hell are you talking about? This was not a double question because it's been posted in two different areas... but the person told you specifically that a solution has been found, so you shouldn't have answered the question after that... It's a different story if you had answered the question BEFORE an answer had been found.. the thing is that that individual knows both C and VB so s/he doesn't care where he's gonna find an answer.. he could easily translate it from one prog. language to another...

NOW: OBREGORU, I KNOW YOU'RE THERE!! JUST REJECT AND LETS GET OVER WITH THIS...

Alex, I'm sorry, but is not fare to get points for nothing.. the person had solved the problem by the time you answered... If I have to write another comment, I will talk to Linda myself, and this time I'm serious!!!

..-=ViKtOr=-..