Tip: SendKeys procedure (Windows)

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Tip: SendKeys procedure (Windows)

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

UPDATE: This currently only works with English keyboards (sorry!).
This means you CANNOT compile it as a Unicode executable (yet).
I am looking into this to see if I can update it ASAP for you.

Here is something that you might find useful. It lets you type keys to other
windows, which you specify by either handle or title. If the target window is in
the background and doesn't have the focus, it is activated before typing starts.

To use it, call the procedure like so: r=SendKeys(handle,window$,keys$)
Specify either the target handle or window$ title, but not both. If you specify
both, the title takes priority and the handle is ignored. The procedure returns
0 for failure to type, otherwise 1 for success.

To type special keys, put them inside curly braces. So to type the Escape key,
you'd specify {ESCAPE} in keys$. Naturally this means you cannot type curly
braces themselves... so add this functionality yourself if you really need them.
Take care to ensure that any opening brace is followed by a closing one, as the
procedure does not check for this.

To hold down the ALT, CONTROL, or SHIFT keys when typing, use the designations
{ALTDOWN}, {CONTROLDOWN}, and {SHIFTDOWN}. Use the opposite of these to
release them again. Look at the procedure to see the other "special" key
assignments.

I hope you like this... it took a while to get it perfect, so let me know if it
fails on a particular set of keystrokes that you want to type. Thanks! :)

(Fred, could this become a native command in future release, please?)

Code: Select all

; SendKeys procedure by PB -- do whatever you want with it.  :)
; Syntax: r=SendKeys(handle,window$,keys$) ; r = 0 for failure.
; Specify either a handle or window$ title to type to, but not both!
; You cannot type curly braces { } as part of the keystrokes, sorry!

Procedure SendKeys(handle,window$,keys$)
  If window$"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle.
  If IsWindow_(handle)=0 ; Does the target window actually exist?
    ProcedureReturn 0 ; Nope, so report 0 for failure to type.
  Else
    ; This block gives the target window the focus before typing.
    thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
    thread2=GetWindowThreadProcessId_(handle,0)
    If thread1thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
    SetForegroundWindow_(handle) ; Target window now has the focus for typing.
    Sleep_(125) ; 1/8 second pause before typing to prevent fast CPU problems.
    ; Now the actual typing starts.
    keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key before typing.
    keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key before typing.
    keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key before typing.
    keybd_event_(#VK_LWIN,0,#KEYEVENTF_KEYUP,0) ; Release WINDOWS key before typing.
    For r=1 To Len(keys$)
      vk=0 : vk$=Mid(keys$,r,1)
      If vk$="{" ; Special key found.
        s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key.
        s$=Mid(keys$,r+1,s) ; Get special key name.
        Select s$ ; Get virtual key code of special key.
          Case "ALTDOWN" : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down.
          Case "ALTUP" : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT.
          Case "BACKSPACE" : vk=#VK_BACK
          Case "CONTROLDOWN" : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down.
          Case "CONTROLUP" : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL.
          Case "DELAY" : vk=0 : Sleep_(1000) ; Delay typing for one second.
          Case "DELETE" : vk=#VK_DELETE
          Case "DOWN" : vk=#VK_DOWN
          Case "END" : vk=#VK_END
          Case "ENTER" : vk=#VK_RETURN
          Case "ESCAPE" : vk=#VK_ESCAPE
          Case "F1" : vk=#VK_F1
          Case "F2" : vk=#VK_F2
          Case "F3" : vk=#VK_F3
          Case "F4" : vk=#VK_F4
          Case "F5" : vk=#VK_F5
          Case "F6" : vk=#VK_F6
          Case "F7" : vk=#VK_F7
          Case "F8" : vk=#VK_F8
          Case "F9" : vk=#VK_F9
          Case "F10" : vk=#VK_F10
          Case "F11" : vk=#VK_F11
          Case "F12" : vk=#VK_F12
          Case "HOME" : vk=#VK_HOME
          Case "INSERT" : vk=#VK_INSERT
          Case "LEFT" : vk=#VK_LEFT
          Case "PAGEDOWN" : vk=#VK_NEXT
          Case "PAGEUP" : vk=#VK_PRIOR
          Case "PRINTSCREEN" : vk=#VK_SNAPSHOT
          Case "RIGHT" : vk=#VK_RIGHT
          Case "SCROLL" : vk=#VK_SCROLL
          Case "SPACE" : vk=#VK_SPACE
          Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down.
          Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT.
          Case "TAB" : vk=#VK_TAB
          Case "UP" : vk=#VK_UP
          Case "WINDOWS" : vk=#VK_LWIN
        EndSelect
        If Left(s$,3)"ALT" And Left(s$,7)"CONTROL" And Left(s$,5)"SHIFT"
          If vk0
            keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key.
          EndIf
        EndIf
        r+s+1 ; Continue getting the keystrokes that follow the special key.
      Else
        vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found.
        If vk>303 And shifted=0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character.
        keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
        If vk>303 And shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character.
      EndIf
    Next
    If thread1thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window!
    keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key in case user forgot.
    keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key in case user forgot.
    keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key in case user forgot.
    keybd_event_(#VK_LWIN,0,#KEYEVENTF_KEYUP,0) ; Release WINDOWS key in case user forgot.
    ProcedureReturn 1 ; Report successful typing!  :)
  EndIf
EndProcedure

RunProgram("notepad.exe") ; Start Notepad...
Repeat : Delay(1) : Until FindWindow_(0,"Untitled - Notepad")0 ; ...and wait for it to open.
SendKeys(0,"Untitled - Notepad","Doesn't PureBasic kick serious butt! ;){ENTER}")
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by naw.

Genius - How did you know that I was looking for a program to *remote control* Apps. Just what I needed to do some benchmarking work (simulated users)...

Just made a couple of changes to *externalise* the Key Sequences into a Loadable Macro File:




==========================
In Global Section:
Launch - Initial Program To Launch/Startup
Title - Default Title to Use of *Launched* Program
Delay - Big delay after Launching Initial Program
Items - # of commands / Keys to send
Description - Pop up text that appears before Application is Launched...

In Macro Section:
cmd1 - Text / Keys to send
del1 - Delay in milisecs
tit1 - Title of Window to send the Text to (overrides the "Title")

macro.naw file:
==========================

[Global]
Items=8
Launch=C:\WINNT\NOTEPAD.EXE
Title=Untitled - Notepad
Delay=3000
Description=This Macro Should Open Notepad, do a search and replace, close the replace dialog...

[Macro]
cmd1=This is a Text Entry{RETURN}
del1=1000

cmd2=This is another Text Entry{RETURN}
del2=1000

cmd3={CONTROLDOWN}h
del3=1000

tit4=Replace
cmd4=another{TAB}
del4=1000

tit5=Replace
cmd5=yet another{ALTDOWN}a
del5=1000

tit6=Replace
cmd6={RETURN}{TAB}{TAB}{TAB}{TAB}{TAB}{RETURN}

del7=1000
cmd7={RETURN}{RETURN}Hello World{RETURN}


===================================
PBs ripped off code :wink: with a few minor changes...
===================================
; SendKeys procedure by PB -- do whatever you want with it. :)
; Syntax: r=SendKeys(handle,window$,keys$) ; r = 0 for failure.
; Specify either a handle or window$ title to type to, but not both!
; You cannot type curly braces { } as part of the keystrokes, sorry!
;
Procedure Alert(m$)
MessageRequester("Alert",m$,#MB_ICONINFORMATION)
EndProcedure


Procedure$ FN_Space(Num)
For Counter = 1 To Num : Tmp$ + " " : Next Counter
ProcedureReturn Tmp$
EndProcedure

Procedure.s FN_readINI(inifile.s, section.s, key.s)
result.s = FN_Space(255)
Empty.s = ""
Ret = GetPrivateProfileString_(section, key, empty, @result, 255, inifile.s)
ProcedureReturn result
EndProcedure

Procedure.l FN_writeINI( inifile.s,section.s, key.s, value.s)
result = WritePrivateProfileString_(section, key, value, inifile)
ProcedureReturn result
EndProcedure

Procedure SendKeys(handle,window$,keys$)
If window$"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle.
If IsWindow_(handle)=0 ; Does the target window actually exist?
ProcedureReturn 0 ; Nope, so report 0 for failure to type.
Else
; This block gives the target window the focus before typing.
thread1=GetWindowThreadProcessID_(GetForegroundWindow_(),0)
thread2=GetWindowThreadProcessID_(handle,0)
If thread1thread2 : AttachThreadInput_(thread1,thread2,#TRUE) : EndIf
SetForegroundWindow_(handle) ; Target window now has the focus for typing.
Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems.
; Now the actual typing starts.
For r=1 To Len(keys$)
vk$=Mid(keys$,r,1)
If vk$="{" ; Special key found.
s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key.
s$=Mid(keys$,r+1,s) ; Get special key name.
Select s$ ; Get virtual key code of special key.
Case "ALTDOWN" : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down.
Case "ALTUP" : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT.
Case "BACKSPACE" : vk=#VK_BACK
Case "CONTROLDOWN" : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down.
Case "CONTROLUP" : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL.
Case "DELETE" : vk=#VK_DELETE
Case "DOWN" : vk=#VK_DOWN
Case "END" : vk=#VK_END
Case "ENTER" : vk=#VK_RETURN
Case "F1" : vk=#VK_F1
Case "F2" : vk=#VK_F2
Case "F3" : vk=#VK_F3
Case "F4" : vk=#VK_F4
Case "F5" : vk=#VK_F5
Case "F6" : vk=#VK_F6
Case "F7" : vk=#VK_F7
Case "F8" : vk=#VK_F8
Case "F9" : vk=#VK_F9
Case "F10" : vk=#VK_F10
Case "F11" : vk=#VK_F11
Case "F12" : vk=#VK_F12
Case "ESCAPE" : vk=#VK_ESCAPE
Case "HOME" : vk=#VK_HOME
Case "INSERT" : vk=#VK_INSERT
Case "LEFT" : vk=#VK_LEFT
Case "PAGEDOWN" : vk=#VK_NEXT
Case "PAGEUP" : vk=#VK_PRIOR
Case "PRINTSCREEN" : vk=#VK_SNAPSHOT
Case "RETURN" : vk=#VK_RETURN
Case "RIGHT" : vk=#VK_RIGHT
Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down
Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT.
Case "TAB" : vk=#VK_TAB
Case "UP" : vk=#VK_UP
EndSelect

If Left(s$,3)"ALT" And Left(s$,7)"CONTROL" And Left(s$,5)"SHIFT"
keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key.
EndIf

r=r+s+1 ; Continue getting the keystrokes that follow the special key.

Else
vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found.
If vk>304 And shifted=0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character.
keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
If vk>304 And shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character.
EndIf
Next
If thread1thread2 : AttachThreadInput_(thread1,thread2,#FALSE) : EndIf ; Finished typing to target window!
keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key if user forgot.
keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key if user forgot.
keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key if user forgot.
ProcedureReturn 1 ; Report successful typing! :)
EndIf
EndProcedure

Procedure GoMacro(x$,t$,m$)

desc$=FN_ReadINI(m$,"Global","Description"): If (desc$) : Alert(desc$): EndIf

If (RunProgram(x$,"",0))


Delay(Val(FN_ReadINI(m$,"Global","Delay"))+1)
maxctr=Val(FN_ReadINI(m$,"Global","Items"))
For ctr=1 To maxctr
cmd$=FN_ReadINI(m$,"Macro","Cmd"+Str(ctr))
del=Val(FN_ReadINI(m$,"Macro","Del"+Str(ctr)))
tit$=FN_ReadINI(m$,"Macro","Tit"+Str(ctr))
Delay(del)

If (tit$): SendKeys(0,tit$, cmd$): Else: SendKeys(0,t$,cmd$): EndIf
Next

Else: Alert("Couldnt start "+x$)

EndIf


EndProcedure



Dim SPCL.s(40)

SPCL(01)="ALTDOWN"
SPCL(02)="ALTUP"
SPCL(03)="BACKSPACE"
SPCL(04)="CONTROLDOWN"
SPCL(05)="CONTROLUP"
SPCL(06)="DELETE"
SPCL(07)="DOWN"
SPCL(08)="END"
SPCL(09)="ENTER"
SPCL(10)="F1"
SPCL(11)="F2"
SPCL(12)="F3"
SPCL(13)="F4"
SPCL(14)="F5"
SPCL(15)="F6"
SPCL(16)="F7"
SPCL(17)="F8"
SPCL(18)="F9"
SPCL(19)="F10"
SPCL(20)="F11"
SPCL(21)="F12"
SPCL(22)="ESCAPE"
SPCL(23)="HOME"
SPCL(24)="INSERT"
SPCL(25)="LEFT"
SPCL(26)="PAGEDOWN"
SPCL(27)="PAGEUP"
SPCL(28)="PRINTSCREEN"
SPCL(29)="RETURN"
SPCL(30)="RIGHT"
SPCL(31)="SHIFTDOWN"
SPCL(32)="SHIFTUP"
SPCL(33)="TAB"
SPCL(34)="UP"


WID=OpenWindow(1, 100, 100, 400, 600, #PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget, "MACRO CONTROL")
CreateGadgetList(WindowID())
TextGadget(1,10,10,200,16,"List of *Special Keys*"): ComboBoxGadget(2,10,30,200,800)
For x=1 To 40: If SPCL(x): AddGadgetItem(2,-1,SPCL(x)): EndIf: Next: SetGadgetState(1,2)
;TextGadget(3,220,10,200,16,"Open *Special Key* char"): StringGadget(4,360,10,16,16,"{")
;TextGadget(5,220,30,200,16,"Close *Special Key* char"): StringGadget(6,360,30,16,16,"}")
ButtonGadget(7,10,70,100,26,"Launch Program"): StringGadget(8,10,100,170,18,"")
TextGadget(9,10,130,100,16,"Titlebar Text"): StringGadget(10,10,150,170,18,"")
ButtonGadget(11,220,70,100,26,"Open Macro File"): StringGadget(12,220,100,170,18,"")
ButtonGadget(20,220,130,170,46,"Run Macro Against Program"):

TextGadget(13,10,190,380,80,"[url]mailto:Nigel_Wale@uk.ibm.com[/url]"+Chr(13)+Chr(13)+"nawMacro.exe - simple Macro Program for windows - good for benchmarking or automating certain tasks"+Chr(13)+Chr(13)+"example:")
TextGadget(14,20,270,380,400,Chr(13)+"[Global]"+Chr(13)+"Items=6"+Chr(13)+"Launch=C:\WINNT\NOTEPAD.EXE"+Chr(13)+"Title=Untitled - Notepad"+Chr(13)+Chr(13)+"[Macro]"+Chr(13)+"cmd1=This is a Text Entry{RETURN}"+Chr(13)+"del1=1000"+Chr(13)+"cmd2=This is another Text Entry{RETURN}"+Chr(13)+"del2=1000"+Chr(13)+"cmd3={CONTROLDOWN}h"+Chr(13)+"del3=1000"+Chr(13)+"tit4=Replace"+Chr(13)+"cmd4=another{TAB}"+Chr(13)+"del4=1000"+Chr(13)+"tit5=Replace"+Chr(13)+"cmd5=yet another{ALTDOWN}a"+Chr(13)+"del5=1000"+Chr(13)+"cmd6={RETURN}{RETURN}Hello World{RETURN}"+Chr(13)+"del6=1000")

QUIT=0

Repeat: wevent=WaitWindowEvent()
Select wevent
Case #WM_DROPFILES:
Case #WM_CLOSE : QUIT=1
Case #PB_EventCloseWindow: QUIT=1
Case #PB_EventGadget:
Select EventGadgetID()
Case 7: SetGadgetText(8,OpenFileRequester("Program To Launch","*.exe","*.exe",1))
Case 11: SetGadgetText(12,OpenFileRequester("Macro File","macro.naw","*.naw",1)):
SetGadgetText(10,FN_ReadINI(GetGadgetText(10)+GetGadgetText(12),"Global","Title"))
SetGadgetText(8,FN_ReadINI(GetGadgetText(8)+GetGadgetText(12),"Global","Launch"))
Case 20:
If (GetGadgetText(8) And GetGadgetText(10) And GetGadgetText(12)):
GoMacro(GetGadgetText(8),GetGadgetText(10),GetGadgetText(12)):
Else: Alert("Must Specify:"+Chr(13)+" Open / Close *Special Character"+Chr(13)+"Launch Program & Macro File"):
EndIf
Default:
EndSelect
Case #PB_EventMenu:
Select EventMenuID():
Case 1:
Default:
EndSelect
EndSelect
Until QUIT=1
anticro
New User
New User
Posts: 2
Joined: Thu Oct 14, 2004 11:43 am

Post by anticro »

Great thanks for this code! THX THX THX! I was on search for something like this, but not able to do the work myself (API-newbie). :D

I will use it in a script interpreter without changes. :)
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Post by Kwai chang caine »

Great code PB 8)

But i have a problem, when i write the "\ " character, your code write "8"

Code: Select all

RunProgram("notepad.exe") ; Start Notepad... 
Repeat : Delay(1) : Until FindWindow_(0,"Untitled - Notepad")<>0 ; ...and wait for it to open. 
SendKeys(0,"Untitled - Notepad","\\\") 
Result :cry:

Code: Select all

888
They are probably a problem with the shift, but i don't found :oops:
ImageThe happiness is a road...
Not a destination
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

It outputs \\\ here for me. Are you using an English keyboard? Shift + \ on
an English keyboard results in | and not 8, so I don't think you are?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I bet he uses a French Keyboard...

@Caine
is the \ located on shift-8 ?
oh... and have a nice day.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4326
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

I am using an OmniKey / PLUS US English keyboard... Shift + 8 = * here,

Shift + \ = |

I think you can buy a good ALPS IBM Keyboard on eBay Caine! It is worth it. Once you get used to the keypressure your typing speed will increase rapidly!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I was asking Caine for the Layout of the French Keyboard, thought this causes the problem.

on a german Keyboard, "\" is on [AlternateGraphics]+ß <- see the "sz" properly? it's Chr($DF)

on Shift-8 is "(", btw "[" is [AlternateGraphics]+8

oh, and "*" is on shift-"+", it's the key next to [RETURN] in the second row...

anyhow, I don't think he is interested in buying an english or US keyboard.
how should he access the accents there?
oh... and have a nice day.
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Kaeru Gaman wrote:I bet he uses a French Keyboard...
is the \ located on shift-8 ?
On a french keyboard, the '\' is 'AltGr + 8'.

The '8' key on a french keyboard :

8
_\
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Post by Kwai chang caine »

Yes exactly, my friend GNOZAL as right :D

I'm french then, i have a french keyboard.
Fortunetaly, because i speak english like spanish cow, then if i have a US keyboard.....not useful i explain to you the mess :lol:
ImageThe happiness is a road...
Not a destination
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

ah, I get the problem.

the routine here has problems sending the [AltGr] press.
iirc the English/US keyboard does not have such a key...?

so, sending "@" sould result in "q", sending "€" in "e", "µ" in "m", etc...
(at least on a german keyboard)
oh... and have a nice day.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Post by Kwai chang caine »

Yes i found a solution on a german forum

http://www.purebasic.fr/german/viewtopi ... 551#149551

Apparently this code works for the "\" french :D
ImageThe happiness is a road...
Not a destination
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

I have modified this one too

Code: Select all

; Author: Danilo
; Date: 07. April 2003
; Modif : 2. July 2008 by djes


; Posted 07 April 2003 by Danilo on german forum

;SendKeys(handel,Window$,Keys$)

;Handel ......... ist ein Handel zu einen Fenster bekommst du wenn du das Fenster erzeugst.
;Window$ ........ Ist der Name des Fesnters, wenn du den Handel nicht kennst. In dem Fall gibt man dan Handel = 0 an.
;Keys$ .......... Sind die Tasten die du schicken möchtest, wobei du Sondertasten in {} Einschliest (zb. {CONTROLDOWN})

; SendKeys procedure by PB -- do whatever you want with it. :)
; Syntax: r=SendKeys(handle,window$,keys$) ; r = 0 for failure.
; Specify either a handle or window$ title to type to, but not both!
; You cannot type curly braces { } as part of the keystrokes, sorry!
;

;
Declare  SendKeys(handle,window$,keys$)

m$= "This example types some text to Notepad, then clears and closes it."+Chr(13)
m$=m$+"Open a new Notepad window, then click the OK button and watch! :)"
MessageRequester("SendKeys example",m$,#MB_ICONINFORMATION)
;
RunProgram("notepad.exe","","",0)
w$="Sans titre - Bloc-notes" ; Specifies target window name.
Delay(1000) : SendKeys(0,w$,"\\\ Je tape des 8 à la place des \\\") ; Type some dummy text.
;Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}a{CONTROLUP}") ; Select it all.
;Delay(1000) : SendKeys(0,w$,"{DELETE}")      ; Delete it.

;Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}p{CONTROLUP}")

;Delay(1000) : SendKeys(0,w$,"{ALTDOWN}{F4}") ; Close the Notepad Window


; ****************************************************************************************
; ****************************************************************************************
; ************************ PROCEDURE ****************************************************
; ****************************************************************************************
; ****************************************************************************************



Procedure SendKeys(handle,window$,keys$)
    If window$<>"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle.
    If IsWindow_(handle)=0 ; Does the target window actually exist?
        ProcedureReturn 0 ; Nope, so report 0 for failure to type.
    Else
        ; This block gives the target window the focus before typing.
        thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
        thread2=GetWindowThreadProcessId_(handle,0)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
        SetForegroundWindow_(handle) ; Target window now has the focus for typing.
        Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems.
        ; Now the actual typing starts.
        For r=1 To Len(keys$)
            vk$=Mid(keys$,r,1)
            If vk$="{" ; Special key found.
                s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key.
                s$=Mid(keys$,r+1,s) ; Get special key name.
                Select s$ ; Get virtual key code of special key.
                    Case "ALTDOWN" : alted = 1 : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down.
                    Case "ALTUP" : alted = 0 : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT.
                    Case "BACKSPACE" : vk=#VK_BACK
                    Case "CONTROLDOWN" : ctrled = 1 : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down.
                    Case "CONTROLUP" : ctrled = 0 : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL.
                    Case "DELETE" : vk=#VK_DELETE
                    Case "DOWN" : vk=#VK_DOWN
                    Case "END" : vk=#VK_END
                    Case "ENTER" : vk=#VK_RETURN
                    Case "F1" : vk=#VK_F1
                    Case "F2" : vk=#VK_F2
                    Case "F3" : vk=#VK_F3
                    Case "F4" : vk=#VK_F4
                    Case "F5" : vk=#VK_F5
                    Case "F6" : vk=#VK_F6
                    Case "F7" : vk=#VK_F7
                    Case "F8" : vk=#VK_F8
                    Case "F9" : vk=#VK_F9
                    Case "F10" : vk=#VK_F10
                    Case "F11" : vk=#VK_F11
                    Case "F12" : vk=#VK_F12
                    Case "ESCAPE" : vk=#VK_ESCAPE
                    Case "HOME" : vk=#VK_HOME
                    Case "INSERT" : vk=#VK_INSERT
                    Case "LEFT" : vk=#VK_LEFT
                    Case "PAGEDOWN" : vk=#VK_NEXT
                    Case "PAGEUP" : vk=#VK_PRIOR
                    Case "PRINTSCREEN" : vk=#VK_SNAPSHOT
                    Case "RETURN" : vk=#VK_RETURN
                    Case "RIGHT" : vk=#VK_RIGHT
                    Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down.
                    Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT.
                    Case "TAB" : vk=#VK_TAB
                    Case "UP" : vk=#VK_UP
                EndSelect
                If Left(s$,3)<>"ALT" And Left(s$,7)<>"CONTROL" And Left(s$,5)<>"SHIFT"
                    keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key.
                EndIf
                r=r+s+1 ; Continue getting the keystrokes that follow the special key.
            Else
                ;LoadKeyboardLayout_("000040c",#KLF_ACTIVATE|#KLF_REORDER)
                vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character.
                If (vk&$0200)<>0 And ctrled = 0 :  keybd_event_(#VK_CONTROL,0,0,0) : EndIf 
                If (vk&$0400)<>0 And alted = 0 :   keybd_event_(#VK_MENU,0,0,0) : EndIf
                keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character.
                If (vk&$0200)<>0 And ctrled = 0  : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) : EndIf 
                If (vk&$0400)<>0 And alted = 0   : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) : EndIf 
            EndIf
        Next

        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window!
        keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key if user forgot.
        keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key if user forgot.
        keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key if user forgot.
        ProcedureReturn 1 ; Report successful typing! :)
    EndIf
EndProcedure 
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Post by Kwai chang caine »

Hello DJES, glad i talk to you :D
Thanks for your modification 8)
That's right, this code works fine.

But it's funny, it's works so fine that he never stop now :D
I say that, it's for move the "SCHMILBLICK" because i use the deutch code, but it's strange no, whar are you think about that :D

Code: Select all

; Author: Danilo 
; Date: 07. April 2003 
; Modif : 2. July 2008 by djes 


; Posted 07 April 2003 by Danilo on german forum 

;SendKeys(handel,Window$,Keys$) 

;Handel ......... ist ein Handel zu einen Fenster bekommst du wenn du das Fenster erzeugst. 
;Window$ ........ Ist der Name des Fesnters, wenn du den Handel nicht kennst. In dem Fall gibt man dan Handel = 0 an. 
;Keys$ .......... Sind die Tasten die du schicken möchtest, wobei du Sondertasten in {} Einschliest (zb. {CONTROLDOWN}) 

; SendKeys procedure by PB -- do whatever you want with it. :) 
; Syntax: r=SendKeys(handle,window$,keys$) ; r = 0 for failure. 
; Specify either a handle or window$ title to type to, but not both! 
; You cannot type curly braces { } as part of the keystrokes, sorry! 
; 

; 
Declare  SendKeys(handle,window$,keys$) 

m$= "This example types some text to Notepad, then clears and closes it."+Chr(13) 
m$=m$+"Open a new Notepad window, then click the OK button and watch! :)" 
MessageRequester("SendKeys example",m$,#MB_ICONINFORMATION) 
; 
RunProgram("notepad.exe","","",0) 
w$="Sans titre - Bloc-notes" ; Specifies target window name. 
Delay(1000) : SendKeys(0,w$,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\\///___----[[[####{{{~~~&&&&|||^^^@@@@]]]]===))))") ; Type some dummy text. 
Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}a{CONTROLUP}") ; Select it all. 
Delay(1000) : SendKeys(0,w$,"{DELETE}")      ; Delete it. 

Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}p{CONTROLUP}") 

Delay(1000) : SendKeys(0,w$,"{ALTDOWN}{F4}") ; Close the Notepad Window 


; **************************************************************************************** 
; **************************************************************************************** 
; ************************ PROCEDURE **************************************************** 
; **************************************************************************************** 
; **************************************************************************************** 



Procedure SendKeys(handle,window$,keys$) 
    If window$<>"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle. 
    If IsWindow_(handle)=0 ; Does the target window actually exist? 
        ProcedureReturn 0 ; Nope, so report 0 for failure to type. 
    Else 
        ; This block gives the target window the focus before typing. 
        thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0) 
        thread2=GetWindowThreadProcessId_(handle,0) 
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf 
        SetForegroundWindow_(handle) ; Target window now has the focus for typing. 
        Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems. 
        ; Now the actual typing starts. 
        For r=1 To Len(keys$) 
            vk$=Mid(keys$,r,1) 
            If vk$="{" ; Special key found. 
                s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key. 
                s$=Mid(keys$,r+1,s) ; Get special key name. 
                Select s$ ; Get virtual key code of special key. 
                    Case "ALTDOWN" : alted = 1 : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down. 
                    Case "ALTUP" : alted = 0 : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT. 
                    Case "BACKSPACE" : vk=#VK_BACK 
                    Case "CONTROLDOWN" : ctrled = 1 : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down. 
                    Case "CONTROLUP" : ctrled = 0 : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL. 
                    Case "DELETE" : vk=#VK_DELETE 
                    Case "DOWN" : vk=#VK_DOWN 
                    Case "END" : vk=#VK_END 
                    Case "ENTER" : vk=#VK_RETURN 
                    Case "F1" : vk=#VK_F1 
                    Case "F2" : vk=#VK_F2 
                    Case "F3" : vk=#VK_F3 
                    Case "F4" : vk=#VK_F4 
                    Case "F5" : vk=#VK_F5 
                    Case "F6" : vk=#VK_F6 
                    Case "F7" : vk=#VK_F7 
                    Case "F8" : vk=#VK_F8 
                    Case "F9" : vk=#VK_F9 
                    Case "F10" : vk=#VK_F10 
                    Case "F11" : vk=#VK_F11 
                    Case "F12" : vk=#VK_F12 
                    Case "ESCAPE" : vk=#VK_ESCAPE 
                    Case "HOME" : vk=#VK_HOME 
                    Case "INSERT" : vk=#VK_INSERT 
                    Case "LEFT" : vk=#VK_LEFT 
                    Case "PAGEDOWN" : vk=#VK_NEXT 
                    Case "PAGEUP" : vk=#VK_PRIOR 
                    Case "PRINTSCREEN" : vk=#VK_SNAPSHOT 
                    Case "RETURN" : vk=#VK_RETURN 
                    Case "RIGHT" : vk=#VK_RIGHT 
                    Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down. 
                    Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT. 
                    Case "TAB" : vk=#VK_TAB 
                    Case "UP" : vk=#VK_UP 
                EndSelect 
                If Left(s$,3)<>"ALT" And Left(s$,7)<>"CONTROL" And Left(s$,5)<>"SHIFT" 
                    keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key. 
                EndIf 
                r=r+s+1 ; Continue getting the keystrokes that follow the special key. 
            Else 
                ;LoadKeyboardLayout_("000040c",#KLF_ACTIVATE|#KLF_REORDER) 
                vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found 
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character. 
                If (vk&$0200)<>0 And ctrled = 0 :  keybd_event_(#VK_CONTROL,0,0,0) : EndIf 
                If (vk&$0400)<>0 And alted = 0 :   keybd_event_(#VK_MENU,0,0,0) : EndIf 
                keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key. 
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character. 
                If (vk&$0200)<>0 And ctrled = 0  : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) : EndIf 
                If (vk&$0400)<>0 And alted = 0   : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) : EndIf 
            EndIf 
        Next 

        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window! 
        keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key if user forgot. 
        keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key if user forgot. 
        keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key if user forgot. 
        ProcedureReturn 1 ; Report successful typing! :) 
    EndIf 
EndProcedure 
Thank to your help and all the friend of this post 8)
ImageThe happiness is a road...
Not a destination
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Yes, there was a "missing feature" if you include "{" in your text that are not to specify special tags.

Code: Select all

; Author: Danilo
; Date: 07. April 2003
; Modif : 2. July 2008 by djes


; Posted 07 April 2003 by Danilo on german forum

;SendKeys(handel,Window$,Keys$)

;Handel ......... ist ein Handel zu einen Fenster bekommst du wenn du das Fenster erzeugst.
;Window$ ........ Ist der Name des Fesnters, wenn du den Handel nicht kennst. In dem Fall gibt man dan Handel = 0 an.
;Keys$ .......... Sind die Tasten die du schicken möchtest, wobei du Sondertasten in {} Einschliest (zb. {CONTROLDOWN})

; SendKeys procedure by PB -- do whatever you want with it. :)
; Syntax: r=SendKeys(handle,window$,keys$) ; r = 0 for failure.
; Specify either a handle or window$ title to type to, but not both!
;

;
Declare  SendKeys(handle,window$,keys$)

m$= "This example types some text to Notepad, then clears and closes it."+Chr(13)
m$=m$+"Open a new Notepad window, then click the OK button and watch! :)"
MessageRequester("SendKeys example",m$,#MB_ICONINFORMATION)
;
RunProgram("notepad.exe","","",0)
w$="Sans titre - Bloc-notes" ; Specifies target window name.
Delay(1000) : SendKeys(0,w$,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\\///___----[[[####{{{~~~&&&&|||^^^@@@@]]]]===))))") ; Type some dummy text.
Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}a{CONTROLUP}") ; Select it all.
Delay(1000) : SendKeys(0,w$,"{DELETE}")      ; Delete it.

Delay(1000) : SendKeys(0,w$,"{CONTROLDOWN}p{CONTROLUP}")

Delay(1000) : SendKeys(0,w$,"{ALTDOWN}{F4}") ; Close the Notepad Window


; ****************************************************************************************
; ****************************************************************************************
; ************************ PROCEDURE ****************************************************
; ****************************************************************************************
; ****************************************************************************************



Procedure SendKeys(handle,window$,keys$)
    If window$<>"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle.
    If IsWindow_(handle)=0 ; Does the target window actually exist?
        ProcedureReturn 0 ; Nope, so report 0 for failure to type.
    Else
        ; This block gives the target window the focus before typing.
        thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
        thread2=GetWindowThreadProcessId_(handle,0)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
        SetForegroundWindow_(handle) ; Target window now has the focus for typing.
        Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems.
        ; Now the actual typing starts.
        For r=1 To Len(keys$)
            vk$=Mid(keys$,r,1)
            If vk$="{" ; Special key found.
                s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key.
                s$=Mid(keys$,r+1,s) ; Get special key name.
                notakey=#False
                Select s$ ; Get virtual key code of special key.
                    Case "ALTDOWN" : alted = 1 : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down.
                    Case "ALTUP" : alted = 0 : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT.
                    Case "BACKSPACE" : vk=#VK_BACK
                    Case "CONTROLDOWN" : ctrled = 1 : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down.
                    Case "CONTROLUP" : ctrled = 0 : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL.
                    Case "DELETE" : vk=#VK_DELETE
                    Case "DOWN" : vk=#VK_DOWN
                    Case "END" : vk=#VK_END
                    Case "ENTER" : vk=#VK_RETURN
                    Case "F1" : vk=#VK_F1
                    Case "F2" : vk=#VK_F2
                    Case "F3" : vk=#VK_F3
                    Case "F4" : vk=#VK_F4
                    Case "F5" : vk=#VK_F5
                    Case "F6" : vk=#VK_F6
                    Case "F7" : vk=#VK_F7
                    Case "F8" : vk=#VK_F8
                    Case "F9" : vk=#VK_F9
                    Case "F10" : vk=#VK_F10
                    Case "F11" : vk=#VK_F11
                    Case "F12" : vk=#VK_F12
                    Case "ESCAPE" : vk=#VK_ESCAPE
                    Case "HOME" : vk=#VK_HOME
                    Case "INSERT" : vk=#VK_INSERT
                    Case "LEFT" : vk=#VK_LEFT
                    Case "PAGEDOWN" : vk=#VK_NEXT
                    Case "PAGEUP" : vk=#VK_PRIOR
                    Case "PRINTSCREEN" : vk=#VK_SNAPSHOT
                    Case "RETURN" : vk=#VK_RETURN
                    Case "RIGHT" : vk=#VK_RIGHT
                    Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down.
                    Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT.
                    Case "TAB" : vk=#VK_TAB
                    Case "UP" : vk=#VK_UP
                    Default
                      notakey = #True
                EndSelect
                If notakey=#False
                  If Left(s$,3)<>"ALT" And Left(s$,7)<>"CONTROL" And Left(s$,5)<>"SHIFT"
                      keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key.
                  EndIf
                  r=r+s+1 ; Continue getting the keystrokes that follow the special key.
                Else
                  vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found
                  keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
                EndIf
            Else
                ;LoadKeyboardLayout_("000040c",#KLF_ACTIVATE|#KLF_REORDER)
                vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character.
                If (vk&$0200)<>0 And ctrled = 0 :  keybd_event_(#VK_CONTROL,0,0,0) : EndIf
                If (vk&$0400)<>0 And alted = 0 :   keybd_event_(#VK_MENU,0,0,0) : EndIf
                keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
                If (vk&$0100)<>0 And shifted = 0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character.
                If (vk&$0200)<>0 And ctrled = 0  : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) : EndIf
                If (vk&$0400)<>0 And alted = 0   : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) : EndIf
            EndIf
        Next

        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window!
        keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key if user forgot.
        keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key if user forgot.
        keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key if user forgot.
        ProcedureReturn 1 ; Report successful typing! :)
    EndIf
EndProcedure 
Post Reply