Hi
I want to ask if somebody has tied to send keystrokes to calc.exe from another process. My first attempt was to send WM_KEYDOWN / WM_KEYUP messages but I failed. I tried it with the keybd_event api and this seems to work but it has a serious drawback. I had to build in a little sleep delay to make sure that each message reaches the message loop. WaitForInputIdle doesn?t work without this delay! If I call the keybd_event? api too fast, repeated chars go lost. Due to this artefact, I want to know if it is possible to use the SendMessage api with WM_KEYxxx. The code I?m using now is:

; Method:? ? REdtIptor.SendToCalc
; Purpose:? ?Sends the selected text to the Calc.exe application.
; Arguments: None.
; Return:? ? Nothing.

SendChar macro Char:req
? ? .if $invoke(WaitForInputIdle, .hCalcPrc, CALC_KEY_TIMEOUT) != 0
? ? ? jmp @@Exit
? ? .endif
? ? invoke keybd_event, Char, 0, 0, 0? ? ? ? ? ? ? ? ? ? ?;Switch calculator to hexadecimal
? ? invoke Sleep, 50? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;Give Calc enough time to detect Keystroks
endm

Method REdtIptor.SendToCalc, uses ebx edi esi
? ? local dSelBeg:dword, dSelEnd:dword, dCharCount:dword, pBuffer:Pointer, dFlags:dword

? ? SetObject esi
? ? .if $OCall(esi.OpenCalc) == TRUE
? ? ? invoke SetForegroundWindow, .hCalcWnd? ? ? ? ? ;Set as forgound window to enable it
? ? ? mov ecx, .pOwner? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;? to receive keyboard strokes
? ? ? mov ebx, .ChildTxt.hEdit
? ? ? invoke CallWindowProc, .pPrevWndProc, ebx, EM_GETSEL, addr dSelBeg, addr dSelEnd
? ? ? mov eax, dSelEnd
? ? ? sub eax, dSelBeg
? ? ? mov dCharCount, eax
? ? ? push eax
? ? ? inc eax
? ? ? mov pBuffer, $MemAlloc(eax)
? ? ? invoke CallWindowProc, .pPrevWndProc, ebx, EM_GETSELTEXT, 0, pBuffer

? ? ? pop ebx
? ? ? add ebx, pBuffer? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;ebx -> end of string
? ? ? dec ebx? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;Skip terminator zero
? ? ? .while ebx >= pBuffer
? ? ? ? .if byte ptr == " "
? ? ? ? ? dec ebx
? ? ? ? .elseif byte ptr == "h"
? ? ? ? ? SendChar VK_F5? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;Switch calculator to hexadecimal
? ? ? ? ? SendChar VK_F12? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;Switch calculator to qword
? ? ? ? ? .break
? ? ? ? .elseif byte ptr == "y"
? ? ? ? ? SendChar VK_F8? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;Switch calculator to binary
? ? ? ? ? SendChar VK_F12? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;Switch calculator to qword
? ? ? ? ? .break
? ? ? ? .else
? ? ? ? ? SendChar VK_F6? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;Switch calculator to decimal
? ? ? ? ? .break
? ? ? ? .endif
? ? ? .endw

? ? ? xor eax, eax
? ? ? mov dFlags, eax? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;1 if 1st char different from "0"
? ? ? mov edi, pBuffer
? ? ? add dCharCount, edi
? ? ? .while edi < dCharCount
? ? ? ? xor ebx, ebx
? ? ? ? mov bl, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;edi -> char buffer
? ? ? ? inc edi
? ? ? ? .if dFlags == 0? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;Don't send unnecessary "0" chars
? ? ? ? ? .if bl != "0"
? ? ? ? ? ? inc dFlags
? ? ? ? ? .endif
? ? ? ? .endif
? ? ? ? .if dFlags != 0
? ? ? ? ? .if bl == "."
? ? ? ? ? ? SendChar 00BEh
? ? ? ? ? .else
? ? ? ? ? ? .if ((bl > "0" - 1) && (bl < "9" + 1)) || ((bl > "A" - 1) && (bl < "F" + 1))
? ? ? ? ? ? ? SendChar ebx
? ? ? ? ? ? .endif
? ? ? ? ? .endif
? ? ? ? .endif
? ? ? .endw

? ? ? .if dFlags == 0? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?;if nothing was sent
? ? ? ? SendChar "0"? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;? send a "0"
? ? ? .endif

@@Exit:
? ? ? MemFree pBuffer
? ? .endif
MethodEnd


Biterider
Posted on 2005-07-23 16:25:20 by Biterider
Both WM_KEYDOWN and WM_KEYUP will send a WM_CHAR. To get WM_KEYxxx to send the WM_CHAR use PostMessage.

Regards

Posted on 2005-07-23 17:22:10 by minor28
I am not completely sure that sending keystrokes directly will work reliably as the threads inputs are not synchronized. I think that the best idea is to open the process and use AttachThreadInput...

Windows created in different threads typically process input independently of each other. That is, they have their own input states (focus, active, capture windows, key state, queue status, and so on), and they are not synchronized with the input processing of other threads. By using the AttachThreadInput function, a thread can attach its input processing to another thread. This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread. This also allows threads to get key-state information. These capabilities are not generally possible.


AttachThreadInput
Posted on 2005-07-29 01:51:51 by donkey
Hi Donkey
Currently I'm still using the Sleep api to delay the SendMessages due to that the sent messages arrive out of order if I don't do it. I will try AttachThreadInput...  Thanks!

Biterider
Posted on 2005-07-29 01:54:11 by Biterider
Hi Donkey
It works perfectly even without delays! Thanks!  8)

Biterider
Posted on 2005-07-29 07:33:29 by Biterider
No probs Biterider.
Posted on 2005-07-31 21:56:21 by donkey