Keystrokes to Windows

BlitzMax Forums/BlitzMax Programming/Keystrokes to Windows

I was thinking today that I'd like to write a max program that automates some repditave tasks I have to do in windows.

Does anybody know if its possible for me to send keystrokes to other apps from max.

Example, send alt-tab to the system, then send a string of keystrokes, then a tab, another sting of keystrokes etc??

Hi,

I can't help with the solution, but I thought I'd drop you this link.

http://www.autohotkey.com

It's a superb free proggy

Tom

here is a post where this was discussed somewhat:

http://www.blitzmax.com/Community/posts.php?topic=48863

Jay,

I managed to get the AUTOIT dll to work with bmax. You need to download the free package (the dll is within the zipfile) from http://www.autoitscript.com/autoit3/downloads.php

I have not completed doing all the AUTOIT functions but have completed several. Pls feel free to continue this work. The AUTOIT_Send function is what you need.

The following is an example of what it can do

Strict
Include "incl_Autoit.bmx"

'You need to call AUTOIT_INIT() before using any of the AUTOIT functions
Local r=AutoIT_Init()

AUTOIT_ClipPut("This is text is in the Clipboard") 'Put text to clipboard
Local c$=AUTOIT_Clipget() 'Get text from clipboard

WinExec("Notepad.exe",1) 'runs notepad
AUTOIT_WinWaitActive("Untitled","",1000) 'Wait for Notepad window for 1000ms

AUTOIT_AutoItSetOption("SendKeyDelay", 10) ' Delay keypresses
AUTOIT_Send(c) 'send string to window
AUTOIT_Send("{ALTDOWN}{F4}{ALTUP}")  'send ALT-F4 to active window
'or AUTOIT_Send("!{F4})

End


The functions are described well in the help files. Note that the functions available from the dll are different from the Macro functions.

The include file (which was going to be a mod - but I dont know when I will do this) is as per below

Rem
bbdoc: Max2D
End Rem
Rem
Module pub.AUTOITX3

ModuleInfo "Version: 0.30"
ModuleInfo "Author: Assari"
ModuleInfo "License: Public Domain"
ModuleInfo "Copyright: read licence from hiddensoft"
ModuleInfo "Modserver: none"
ModuleInfo "Based on AUTOITX dll from www.hiddensoft.com"
EndRem

Const AU_Default:Int=(-2147483647)

Extern "win32"
  Function  WinExec(lpCmdLine:Byte Ptr,nCmdShow:Int)
End Extern

Local path$="D:\assari\blitzmax\autoit-v3\AutoItX"  'CHANGE THIS TO YOUR OWN LOCATION!!!
Global DLLHandle=loadlibraryA(path$+"AutoitX3.dll")
'===========================================================================
Rem
bbdoc: Initialise the AUTOITX system
returns: 10
about:
Initialise the AUTOITX system. Must execute this command before using the other functions
End Rem
Global AutoIT_Init()"win32"=GetProcAddress(DLLHandle, "AU3_Init") 'Init(void);
'===========================================================================
' Could not get this to work 
'Global AutoIT_Error:Long()"win32"=GetProcAddress(DLLHandle, "AU3_Error") 'Init(void);

'===========================================================================
'ENVIRONMENTAL MANAGEMENT
Global AutoITX_ClipGet(szClip:Byte Ptr, nBufSize:Int)"win32"=GetProcAddress(DLLHandle, "AU3_ClipGet") 'ClipGet(char *szClip, int nBufSize);
Rem
bbdoc: Gets text from clipboard
returns: Returns a string containing the text on the clipboard
about:
Get text from the clipboard. If textsize is not specified then it defaults to 255 characters
Usage: text$=AUTOIT_ClipGet$() OR text$=AUTOIT_ClipGet$(1000)
EndRem
Function AUTOIT_ClipGet$(nBufSize:Int=255)
Local stuff:Byte[nBufSize]
	AUTOITX_ClipGet(stuff,nBufSize)
	Local ret$=string.FromCString(stuff)
	Return ret$
End Function

Global AutoITX_ClipPut(szClip:Byte Ptr)"win32"=GetProcAddress(DLLHandle, "AU3_ClipPut") 'ClipPut(const char *szClip);
Rem
bbdoc: Put text to clipboard
returns: 1 for success, 0 for failure
about:
Place text onto clipboard
Usage: AUTOIT_ClipPut("A piece of text") OR AUTOIT_ClipPut(text$)
EndRem
Function AutoIT_ClipPut(szClip:String)
  Return AutoITX_ClipPut(szClip)
EndFunction

'===========================================================================
'FILE DIRECTORY And DISK MANAGEMENT

Global AutoITX_IniDelete(szFilename:Byte Ptr, szSection:Byte Ptr, szkey:Byte Ptr)"win32"=GetProcAddress(DLLHandle, "AU3_IniDelete") 'IniDelete(const char *szFilename, const char *szSection, const char *szKey);
Rem
bbdoc: Deletes a value from a standard format .ini file.
returns: 1 for success, 0 for failure
about:
Place text onto clipboard
Usage: AUTOIT_IniDelete ("filename", "section" [, "key"])
EndRem
Function IniDelete(szFilename:String, szSection:String, szkey:String="")
	Return IniDelete(szFilename, szSection, szkey)
End Function

'===============================================================================
Global AutoITX_IniRead(szFilename:Byte Ptr, szSection:Byte Ptr, szkey:Byte Ptr, szDefault:Byte Ptr, szValue:Byte Ptr,  nBufSize:Int)"win32"=GetProcAddress(DLLHandle, "AU3_IniRead") 
'IniRead(const char *szFilename, const char *szSection, const char *szKey, const char *szDefault, char *szValue, int nBufSize);
Rem
bbdoc: Reads a value from a standard format .ini file.
returns: 1 for success, 0 for failure
about:
A standard ini file looks like:
[SectionName]
Key=Value
Usage: AUTOIT_IniRead ("filename", "section", "key", "default")
EndRem

Function AutoIT_IniRead$(szFilename:String, szSection:String, szkey:String, szDefault:Byte Ptr)
Local stuff:Byte[255]
	Local r=AUTOITX_IniRead(szFilename, szSection, szKey, szDefault, stuff,255)
	Local ret$=String.FromCString(stuff)
	Return ret$
End Function

'================================================================================
Global AutoITX_IniWrite(szFilename:Byte Ptr, szSection:Byte Ptr, szkey:Byte Ptr, szValue:Byte Ptr)"win32"=GetProcAddress(DLLHandle, "AU3_IniWrite")
 'IniWrite(const char *szFilename, const char *szSection, const char *szKey, const char *szValue);
Rem
bbdoc: Writes a value to a standard format .ini file.
returns: 1 for success, 0 for failure
about:
A standard ini file looks like:
[SectionName]
Key=Value
Usage: AUTOIT_IniWrite( "filename", "section", "key", "default")
EndRem
Function AutoIT_IniWrite(szFilename:String, szSection:String, szkey:String, szValue:String)
   Return AutoITX_IniWrite(szFilename, szSection, szkey, szValue)
End Function

'============================================================================
'KEYBOARD CONTROL

Global AutoITX_Send(f:Byte Ptr, nmode:Long)"win32"=GetProcAddress(DLLHandle,"AU3_Send")
Rem
bbdoc: Sends simulated keystrokes to the active window.
returns: none
about:
The "Send" command syntax is similar to that of ScriptIt and the Visual Basic "SendKeys" command. Characters are sent as written with the exception of the following characters:

'!' = ALT e.g. !{F4} is interpreted as ALT-F4
'+'=This tells AutoIt to send a SHIFT keystroke, therefore Send("Hell+o") would send the text "HellO". Send("!+a") would send "ALT+SHIFT+a".
'^'=This tells AutoIt to send a CONTROL keystroke, therefore Send("^!a") would send "CTRL+ALT+a".
'#'=The hash now sends a Windows keystroke; therefore, Send("#r") would send Win+r which launches the Run dialog box.
Certain special keys can be sent and should be enclosed in braces: pls refer to the AUTOITX help file
End Rem

Function AUTOIT_Send(f:String, nmode:Long=0)
   Return AUTOITX_Send(f,nmode)
End Function

'==============================================================================
'MESSAGE BOXES AND DIALOGS

Global AutoITX_ToolTip(szTip:Byte Ptr, nx:Long, nY:Long)"win32"=GetProcAddress(DLLHandle, "AU3_ToolTip") 
'ToolTip(const char *szTip, /*[in,defaultvalue(AU3_INTDEFAULT)]*/long nX, /*[in,defaultvalue(AU3_INTDEFAULT)]*/long nY);
Rem
bbdoc: Creates a tooltip anywhere on the screen.
returns: none
about:
If the x and y coordinates are omitted the, tip is placed near the mouse cursor. If the coords would cause the tooltip to run off screen, it is repositioned to visible.
Tooltip appears until it is cleared, until script terminates, or sometimes until it is clicked upon. You may use a linefeed character to create multi-line tooltips.
Usage: AUTOIT_ToolTip "text" [, x, y]
EndRem

Function AutoIT_Tooltip(szTip:String, nx:Long=AU_DEFAULT, nY:Long=AU_DEFAULT)
    Return AutoITX_Tooltip(szTip, nx, nY)
End Function

'==============================================================================
'MISC FUNCTIONS


'============================================================================
Global AutoIT_AutoItSetOption(szOption:Byte Ptr, nValue:Long)"win32"=GetProcAddress(DLLHandle, "AU3_AutoItSetOption") 'AutoItSetOption(const char *szOption, long nValue);

Global AutoIT_BlockInput(nFlag:Int)"win32"=GetProcAddress(DLLHandle, "AU3_BlockInput") 'BlockInput(long nFlag);
Global AutoIT_CDTray(szDrive, szAction:Byte Ptr)"win32"=GetProcAddress(DLLHandle, "AU3_CDTray") 'CDTray(const char *szDrive, const char *szAction);
Global AutoIT_IsAdmin()"win32"=GetProcAddress(DLLHandle, "AU3_IsAdmin") 'IsAdmin(void);

'============================================================================
Global AutoITX_MouseClick(szButton:Byte Ptr,  nX:Long, nY:Long,  nClicks: Long, nSpeed:Long)"win32"=GetProcAddress(DLLHandle, "AU3_MouseClick") 
'MouseClick(/*[in,defaultvalue("LEFT")]*/const char *szButton,
' /*[in,defaultvalue(AU3_INTDEFAULT)]*/Long nX, /*[in,defaultvalue(AU3_INTDEFAULT)]*/Long nY,
' /*[in,defaultvalue(1)]*/Long nClicks, /*[in,defaultvalue(-1)]*/Long nSpeed);
Function AutoIT_MouseClick(szButton:String="LEFT",  nX:Long=AU_DEFAULT, nY:Long=AU_DEFAULT,  nClicks: Long=1, nSpeed:Long=-1)
	 Local r=AutoITX_MouseClick(szButton,  nX, nY,  nClicks, nSpeed)
	Return r
End Function

'============================================================================
Global AutoITX_WinWaitNotActive(szTitle:Byte Ptr, szText:Byte Ptr, nTimeOut:Long)"win32"=GetProcAddress(DLLHandle, "AU3_WinWaitNotActive") 
'WinWaitNotActive(const char *szTitle, /*[in,defaultvalue("")]*/const char *szText, 
'/*[in,defaultvalue(0)]*/Long nTimeout);
Function AutoIT_WinWaitNotActive(szTitle:String, szText:String="", nTimeOut:Long=0)
  Return AutoITX_WinWaitNotActive(szTitle, szText, nTimeOut)
End Function

'============================================================================
Global AutoITx_WinGetTitle(szTitle:Byte Ptr, szText:Byte Ptr, szRetText:Byte Ptr, nBufSize:Int)"win32"=GetProcAddress(DLLHandle, "AU3_WinGetTitle") 'WinGetTitle(const char *szTitle, /*[in,defaultvalue("")]*/const char *szText, char *szRetText, int nBufSize);
Function AUTOIT_WinGetTitle:String(szTitle:String="", szText:String="", nBufSize:Int=255)
Local stuff:Byte[nBufSize]
	AUTOITX_WinGetTitle(szTitle, szText,stuff, nBufSize)
	Return String.FromCString(stuff)
End Function
'============================================================================
Global AutoITX_WinKill(szTitle:Byte Ptr, sztext:Byte Ptr)"win32"=GetProcAddress(DLLHandle, "AU3_WinKill") 'WinKill(const char *szTitle, /*[in,defaultvalue("")]*/const char *szText);
Function AUTOIT_WinKill(szTitle:String, szText:String="")
	 Return AUTOITX_WinKill(szTitle, szText)
EndFunction
'============================================================================
Global AutoIT_Sleep(nMilliseconds:Long)"win32"=GetProcAddress(DLLHandle, "AU3_Sleep") 'Sleep(long nMilliseconds);
'============================================================================
Global AutoITX_WinWaitActive(szTitle:Byte Ptr, szText:Byte Ptr,  nTimeOut:Long)"win32"=GetProcAddress(DLLHandle, "AU3_WinWaitActive") 
'WinWaitActive(const char *szTitle, /*[in,defaultvalue("")]*/const char *szText, /*[in,defaultvalue(0)]*/long nTimeout);
Function AUTOIT_WinWaitActive(szTitle:String, szText:String="", nTimeOut:Long=0)
	Return AUTOITX_WinWaitActive(szTitle, szText, nTimeOut)
End Function
'============================================================================



Thanks Guys,

I installed autohotkey last night and it looks like what I need.

I'll read up on Autoit now.

Are there any websites I can go an shop around for useful little dll like this that free to distribute with my game?

Autoit does have a DLL that you can distribute free with commercial products. i confirmed that very thing today as i found it very interesting.

Hey assari this is really interesting, but I got the DLL and tried your code but blitz just crashes when compiling the example code.

I changed the example code to this and bcc.exe still crashes and then blitz says "Build Error: failed to compile"
Strict
Include "incl_Autoit.bmx"
End

Hi,
It seems that the 1.16 compiler does not like the previous method I was using to declare the functions.

I do not have time yet to go through and change everything but this code works for me. Try it out and see what happens. Do not forget to change the dll location
Const AU_Default:Int=(-2147483647)

Extern "win32"
  Function  WinExec(lpCmdLine$z,nCmdShow:Int)
End Extern

Local path$="D:\assari\blitzmax\autoit-v3\AutoItX"  'CHANGE THIS TO YOUR OWN LOCATION!!!
Global DLLHandle=loadlibraryA(path$+"AutoitX3.dll")
Global AutoIT_Init()"win32"=GetProcAddress(DLLHandle, "AU3_Init") 'Init(void);
Global AutoITX_ClipGet(szClip:Byte Ptr, nBufSize:Int)"win32"=GetProcAddress(DLLHandle, "AU3_ClipGet") 

Function AUTOIT_ClipGet$(nBufSize:Int=255)
Local stuff:Byte[nBufSize]
	AUTOITX_ClipGet(stuff,nBufSize)
	Local ret$=string.FromCString(stuff)
	Return ret$
End Function

Global AutoIT_ClipPut(szClip$z)"win32"=GetProcAddress(DLLHandle, "AU3_ClipPut") 'ClipPut(const char *szClip);
Global AutoIT_WinWaitActive(szTitle$z, szText$z,  nTimeOut:Long)"win32"=GetProcAddress(DLLHandle, "AU3_WinWaitActive") 
Global AutoIT_AutoItSetOption(szOption$z, nValue:Long)"win32"=GetProcAddress(DLLHandle, "AU3_AutoItSetOption") 
Global AutoITX_Send(f$z, nmode:Long)"win32"=GetProcAddress(DLLHandle,"AU3_Send")
Function AUTOIT_Send(f:String, nmode:Long=0)
   Return AUTOITX_Send(f,nmode)
End Function

Local r=AutoIT_Init()

AUTOIT_ClipPut("This text is in the Clipboard") 'Put text to clipboard
Local c$=AUTOIT_Clipget() 'Get text from clipboard

WinExec("Notepad.exe",1) 'runs notepad
AUTOIT_WinWaitActive("Untitled","",1000) 'Wait for Notepad window for 1000ms

AUTOIT_AutoItSetOption("SendKeyDelay", 10) ' Delay keypresses
AUTOIT_Send(c) 'send string to window
AUTOIT_Send("{ALTDOWN}{F4}{ALTUP}")  'send ALT-F4 to active window
'or AUTOIT_Send("!{F4})

End




This is awesome, thanks! But its messing with my variables. The for loop exits and go becomes some huge nember.

Strict

Const AU_Default:Int=(-2147483647)

Extern "win32"
  Function  WinExec(lpCmdLine$z,nCmdShow:Int)
End Extern

Local path$="c:\autoit-v3\AutoItX"  'CHANGE THIS TO YOUR OWN LOCATION!!!
Global DLLHandle=loadlibraryA(path$+"AutoitX3.dll")
Global AutoIT_Init()"win32"=GetProcAddress(DLLHandle, "AU3_Init") 'Init(void);
Global AutoITX_ClipGet(szClip:Byte Ptr, nBufSize:Int)"win32"=GetProcAddress(DLLHandle, "AU3_ClipGet") 

Function AUTOIT_ClipGet$(nBufSize:Int=255)
Local stuff:Byte[nBufSize]
	AUTOITX_ClipGet(stuff,nBufSize)
	Local ret$=string.FromCString(stuff)
	Return ret$
End Function

Global AutoIT_ClipPut(szClip$z)"win32"=GetProcAddress(DLLHandle, "AU3_ClipPut") 'ClipPut(const char *szClip);
Global AutoIT_WinWaitActive(szTitle$z, szText$z,  nTimeOut:Long)"win32"=GetProcAddress(DLLHandle, "AU3_WinWaitActive") 
Global AutoIT_AutoItSetOption(szOption$z, nValue:Long)"win32"=GetProcAddress(DLLHandle, "AU3_AutoItSetOption") 
Global AutoITX_Send(f$z, nmode:Long)"win32"=GetProcAddress(DLLHandle,"AU3_Send")
Function AUTOIT_Send(f:String, nmode:Long=0)
   Return AUTOITX_Send(f,nmode)
End Function



Local r=AutoIT_Init()

Delay 1000
WinExec("Notepad.exe",1) 'runs notepad
AUTOIT_WinWaitActive("Untitled","",1000) 'Wait for Notepad window for 1000ms
AUTOIT_AutoItSetOption("SendKeyDelay", 20)

Local go
For go=1 To 5
	Print "go="+go
	AUTOIT_Send("asdf")
Next
Print "for loop exited"
Print "go="+go

End


on my system go=6 on exit as expected.

okay it works fine with debug on.
But with debug off... I don't get how it can change my variables. Here is a simpler example

Local r=AutoIT_Init()

Delay 1000
WinExec("Notepad.exe",1) 'runs notepad
AUTOIT_WinWaitActive("Untitled","",1000) 'Wait for Notepad window for 1000ms

Local go
Print "go="+go
AUTOIT_Send("a")
Print "go="+go

End


outputs:

Building untitled3
Compiling:untitled3.bmx
flat assembler  version 1.64
3 passes, 4866 bytes.
Linking:untitled3.exe
Executing:untitled3.exe
go=0
go=10688816

Process complete


Yup, I'm getting the same error. works w debug on and error w/out. Floats works but not string, byte or int
Building forum
Compiling:forum.bmx
flat assembler  version 1.64
3 passes, 12257 bytes.
Linking:forum.exe
Executing:forum.exe
go=0
go=2089893474

Process complete
WinXP SP2

hey, this is cool, I'm still using this stuff.
The new blitzmax update makes it not work again. It doesn't like the $z

Please fix it for me. You have to constantly maintain the code now that you made it! hahaha!

According to this thread http://www.blitzmax.com/Community/posts.php?topic=57496&hl=cstring this is a BlitzMax bug and will be fixed soon.

okay gotcha