Hi guys,
Ok, it's easy to get a program to detect when certain keys are pressed - but is it possible to actually send keypresses (like ctrl+F1 for instance) from a program to Windows ? ::)
best wishes, :)
Graham
two ways that I can find with the API
keybd_event
SendInput
fletchie did it with SendInput but I can't get it to run.
'C:\My Documents\MyProgs\IncFile\helper1.exe
'C:\WINDOWS\system\shell32.dll;4,1
DECLARE "user32",OpenClipboard(hwnd:WINDOW),INT
DECLARE "user32",CloseClipboard(),INT
DECLARE "user32",GetClipboardData(format:INT),INT
DECLARE "user32",SetClipboardData(format:INT,handle:INT),INT
DECLARE "user32",EmptyClipboard(),INT
DECLARE "user32",IsClipboardFormatAvailable(format:INT),INT
DECLARE "kernel32",GlobalAlloc(flags:INT,bytes:INT),INT
DECLARE "kernel32",GlobalLock(handle:INT),INT
DECLARE "kernel32",GlobalUnlock(handle:INT),INT
DECLARE "kernel32",lstrcpyA(dest:STRING,source:INT),INT
DECLARE "kernel32",RtlMoveMemory(dest:INT,source:STRING,length:INT),INT
declare "user32",SetWindowPos(Hwnd:int,HwndAfter:int,x:int,y:int,cx:int,cy:int,flags:int)
declare SendToClipBoard(text:string)
declare GetFromClipBoard(text:string)
SETID "CFTEXT",1
setid "CF_DSPTEXT",129
setid "CF_OEMTEXT",7
SETID "GHND",0x42
setid "WSTOPMOST",8
setid "HWND_TOPMOST",-1
declare "user32",GetWindow (hndw:int,WCmd:int),int
declare "user32",GetParent (hndw:int),int
declare "user32",GetWindowTextLengthA (hwnd:int),int
declare "user32",GetWindowTextA (hwnd:int,lpString:string,cch:int),int
declare "user32",SetActiveWindow (hwnd:int),int
setid "INPUT_KEYBOARD",1
setid "KEYEVENTF_KEYUP",2
declare DoAlt(k:int)
declare DoKey(k:int)
declare DoShift(k:int)
declare DoCtrl(k:int)
declare DoTab(k:int)
declare DoTwo(k:int,st:int)
declare DoKeyState(k:int,st:int)
Type INPUT_TYPE
def dwType:int
def wVk:word
def wScan:word
def dwFlags:int
def time:int
def dwExtraInfo:int
Endtype
Declare "user32",SendInput (nInputs:int, pInputs:INPUT_TYPE,cbsize:int),int
def inp:INPUT_TYPE
def run:int
inp.dwType=@INPUT_KEYBOARD
setid "GW_HWNDFIRST",0
setid "GW_HWNDNEXT",2
setid "GW_CHILD",5
def w1:window
window w1,100,100,400,200,@TOOLWINDOW,0,"IHelper",mainwin
control w1,"B,Refresh,10,10,80,30,0,1"
control w1,"B,Build,110,10,80,30,0,2"
control w1,"E,hello,10,50,380,110,@CTEDITMULTI|@CTEDITAUTOH|@CTEDITAUTOV|@HSCROLL|@VSCROLL,3"
setfont w1,"arial",10,400,0,3
SetWindowPos(w1,@HWND_TOPMOST,100,100,400,200,0)
run = 1
waituntil run=0
closewindow w1
end
'------------------------------------------------------------------------
sub Refresh
def dd:int
def fn,ni:string
DoAlt(9)
DoCtrl(0x24) :'goto start of prog
DoShift(0x23):'shift end
do
DoCtrl(asc("C")):'copy to clipboard
for dd=1 to 1000
wait 1
next dd
GetFromClipBoard(fn)
fn=ltrim$(fn)
ni=lcase$(fn)
if (left$(ni,3)="sub") | (left$(ni,3)="def") |(left$(ni,7)="declare")|(left$(ni,4)="type") | (left$(ni,5)="setid")
SendToClipBoard(fn)
CONTROLCMD w1,3, @EDPASTE
SendToClipBoard(chr$(13)+chr$(10))
ControlCMD w1,3,@EDPASTE
endif
Dokey(0x28):'down
doKey(0x24):' home
doShift(0x23):'shift end
until fn="'end"
DoKey(0x23)
return
'-----------------------------------------------------------------------------
sub Build
def x,y,xx,yy:int
def icon,fn,xy:string
def dd:int
DoAlt(9) :'flip to ibasic
DoCtrl(0x24) :'goto start of prog
DoShift(0x23):'shift end
DoCtrl(asc("C")):'copy to clipboard
for dd=1 to 1000
wait 1
next dd
GetFromClipBoard(fn)
fn=mid$(fn,2)
Dokey(0x28):'down
doShift(0x24):'shift home
doKey(0x27):'right
doShift(0x23):'shift end
DoCtrl(asc("C")):'copy to clipboard
for dd=1 to 1000
wait 1
next dd
DoCtrl(0x24)
GetFromClipBoard(icon)
DoCtrl(0x24)
xy=mid$(icon,instr(icon,";")+1)
x=val(left$(xy,instr(xy,",")-1))-1
y=val(mid$(xy,instr(xy,",")+1))-1
icon=left$(icon,instr(icon,";")-1)
DoAlt(asc("B"))
doKey(asc("M"))
DoTab(2)
SendToClipBoard(fn)
doCtrl(asc("V"))
DoTab(3)
DoKey(13)
SendToClipBoard(icon)
doCtrl(asc("V"))
doKey(0xd)
DoTab(4)
if x>0
for xx=1 to x
DoKey(0x27)
next xx
endif
if y>0
for yy=1 to y
DoKey(0x28)
next yy
endif
DoKey(13)
DoTab(5)
return
'----------------------------------------------------------------------------------
sub mainwin
select @class
CASE @IDCLOSEWINDOW
run = 0
case @idcontrol
select @controlid
case 1
Refresh
case 2
Build
endselect
endselect
return
'----------------------------------------------------------------------------------
sub DoTab(k:int)
def l:int
for l=1 to k
DoKey(9)
next l
return
'----------------------------------------------------------------------------------
sub DoCtrl(k:int)
DoTwo(k,0x11)
return
'-----------------------------------------------------------------
sub DoShift(k:int)
DoTwo(k,0x10)
return
'---------------------------------------------------------
sub DoAlt(k:int)
DoTwo(k,0x12)
return
'-----------------------------------------------------------
sub DoKey(k:int)
DokeyState(k,0)
DoKeyState(k,@KEYEVENTF_KEYUP)
return
'-------------------------------------------------------------
sub DoTwo(k:int,st:int)
DokeyState(st,0)
DokeyState(k,0)
DokeyState(k,@KEYEVENTF_KEYUP)
DokeyState(st,@KEYEVENTF_KEYUP)
return
'---------------------------------------------------
sub DoKeyState(k:int,st:int)
def qq:int
inp.wVk = k
inp.wScan = 0
inp.dwFlags = st
inp.time = 0
inp.dwExtraInfo = 0
qq=sendinput(1,inp,28)
return
'---------------------------------------------------
sub GetFromClipBoard(text:string)
DEF handle,lock:INT
OpenClipboard(w1)
handle = GetClipboardData(@CF_oemtext)
lock = GlobalLock(handle)
lstrcpyA(text,lock)
GlobalUnlock(handle)
CloseClipboard()
RETURN
'------------------------------------------------------
sub SendToClipBoard(text:string)
DEF handle,lock:INT
handle = GlobalAlloc(@GHND,255)
lock = GlobalLock(handle)
RtlMoveMemory(lock,text,len(text)+1)
GlobalUnlock(handle)
OpenClipboard(w1)
EmptyClipboard()
SetClipboardData(@CF_OEMTEXT,handle)
CloseClipboard()
return
'end
Hope that helps a little.
LarryMc
this should get you started :-)
http://www.ionicwind.com/forums/index.php?topic=3983.msg31354#msg31354 - see the last post.
'load notepad and send text to window. Copex.
$include "windows.inc"
Declare Import,FindWindowA(lpClassName:Pointer,lpWindowName:string),Int 'windows.inc lpClassName is defined as string.
INT hParent
openconsole
'
SYSTEM "notepad.exe"
print "asking notepad to load?"
_sleep(1000)
hParent = FindWindowA(NULL, "Untitled - Notepad")
if hParent <>0 'Valid window handle?
_SetForegroundWindow(hParent) 'Show the window
_SetFocus(hParent) 'Set window focus to new window
keyToPress( "Hello world\nHow are we to day" )
ENDIF
Print "press any key to end"
WAITCON
closeconsole
sub keyToPress(string txtToSend),int
string key=""
int loop=0
if len(txtToSend) = 0 then return FALSE
DO
loop++
key = mid$(txtToSend,loop,1)
' Simulate a key press
_keybd_event( _VkKeyScan(key),NULL,NULL,NULL)
_sleep(50) ' Pause so it looks like someone typing can be removed not required
' Simulate a key release
_keybd_event( _VkKeyScan(key),NULL,KEYEVENTF_KEYUP,NULL)
_sleep(50) ' Pause so it looks like someone typing can be removed not required
until loop = len(txtToSend)
return TRUE
ENDSUB
'http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/keybd_event.asp
'Or
'http://www.codeproject.com/system/keyboard.asp
'for more infomation
$include "windows.inc"
Declare Import,FindWindowA(lpClassName:Pointer,lpWindowName:Pointer),Int
INT hParent
openconsole
'
hParent = FindWindowA(NULL, "Untitled - Notepad")
if hParent <>0 'Valid window handle?
_SetForegroundWindow(hParent) 'Show the window
_SetFocus(hParent) 'Set window focus to new window
SendKeys( "true" )
ENDIF
Print "press any key to end"
WAITCON
closeconsole
end
'---------------------------------------------------------------------------------
sub SendKeys(KeyPress as string)
string key, numberLockStatus: numberLockStatus=""
pointer KeyState
int loop=0
KeyState = new(CHAR,255)
'Print _VkKeyScan(".")
/*
if _GetKeyboardState(*<CHAR>KeyState) <>0
if *<CHAR>keystate[VK_NUMLOCK] > 0
numberLockStatus="NumberLock Has been turned off"
ELSE
numberLockStatus="NumberLock Has been turned on"
endif
Endif
*/
DO
loop++
key = mid$(Keypress,loop,1)
' Simulate a key press
_keybd_event( _VkKeyScan(key),NULL,NULL,NULL)
' Simulate a key release
_keybd_event( _VkKeyScan(key),NULL,KEYEVENTF_KEYUP,NULL)
until loop = len(Keypress)
return
endsub
Thanks folks .. ;D .. I'll investigate those.
What it is .. I've been working for years on a 'chat' program (like Eliza).
It speaks to you when you type in some text :)
Previously, I've used a free program called Speakonia .. still available, but no longer being developed, and the computer-speak is a bit rough.
It's main benefit was that once running, if you copied any text to the clipboard, Speakonia spoke it as text-to-speech.
A newer program I have which has pretty good speech, disappointingly can't do the clipboard trick .. you have to press Cntl+F9 to speak selected text from another program.
So I'll have a play to see if I can get it to play ball .. ;D
happy Christmas, :)
Graham
Hence my question.