2009-12-12 17:20:25 -07:00
/*
www . sourceforge . net / projects / dfhack
Copyright ( c ) 2009 Petr Mr á zek ( peterix ) , Kenneth Ferland ( Impaler [ WrG ] ) , dorf
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any
damages arising from the use of this software .
Permission is granted to anyone to use this software for any
purpose , including commercial applications , and to alter it and
redistribute it freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must
not claim that you wrote the original software . If you use this
software in a product , an acknowledgment in the product documentation
would be appreciated but is not required .
2. Altered source versions must be plainly marked as such , and
must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source
distribution .
*/
2010-05-26 04:24:45 -06:00
# include "Internal.h"
# include "ContextShared.h"
# include "dfhack/modules/WindowIO.h"
2010-05-26 00:42:09 -06:00
# include "dfhack/DFProcess.h"
2009-12-12 17:20:25 -07:00
using namespace DFHack ;
2009-12-12 21:08:42 -07:00
// should always reflect the enum in DFkeys.h
const static int ksTable [ NUM_SPECIALS ] =
{
VK_RETURN ,
VK_SPACE ,
VK_BACK ,
VK_TAB ,
VK_CAPITAL ,
VK_LSHIFT ,
VK_RSHIFT ,
VK_LCONTROL ,
VK_RCONTROL ,
VK_MENU ,
0 , //XK_VoidSymbol, // WAIT
VK_ESCAPE ,
VK_UP ,
VK_DOWN ,
VK_LEFT ,
VK_RIGHT ,
VK_F1 ,
VK_F2 ,
VK_F3 ,
VK_F4 ,
VK_F5 ,
VK_F6 ,
VK_F7 ,
VK_F8 ,
VK_F9 ,
VK_F10 ,
VK_F11 ,
VK_F12 ,
VK_PRIOR ,
VK_NEXT ,
VK_INSERT ,
VK_DELETE ,
VK_HOME ,
VK_END ,
VK_DIVIDE ,
VK_MULTIPLY ,
VK_SUBTRACT ,
VK_ADD ,
VK_RETURN ,
VK_NUMPAD0 ,
VK_NUMPAD1 ,
VK_NUMPAD2 ,
VK_NUMPAD3 ,
VK_NUMPAD4 ,
VK_NUMPAD5 ,
VK_NUMPAD6 ,
VK_NUMPAD7 ,
VK_NUMPAD8 ,
VK_NUMPAD9 ,
VK_SEPARATOR
} ;
2009-12-12 17:20:25 -07:00
//Windows key handlers
struct window
{
HWND windowHandle ;
uint32_t pid ;
} ;
2009-12-22 14:19:39 -07:00
2009-12-12 17:20:25 -07:00
BOOL CALLBACK EnumWindowsProc ( HWND hwnd , LPARAM lParam )
{
uint32_t pid ;
2009-12-22 14:19:39 -07:00
2009-12-12 17:20:25 -07:00
GetWindowThreadProcessId ( hwnd , ( LPDWORD ) & pid ) ;
if ( pid = = ( ( window * ) lParam ) - > pid )
{
( ( window * ) lParam ) - > windowHandle = hwnd ;
return FALSE ;
}
2009-12-22 14:19:39 -07:00
return TRUE ;
2009-12-12 17:20:25 -07:00
}
2009-12-12 21:14:44 -07:00
2010-05-26 04:24:45 -06:00
class WindowIO : : Private
2009-12-22 14:19:39 -07:00
{
public :
Private ( Process * _p )
{
p = _p ;
} ;
~ Private ( ) { } ;
// our parent process
Process * p ;
} ;
2009-12-18 18:10:05 -07:00
2009-12-22 14:19:39 -07:00
// ctor
2010-05-26 04:24:45 -06:00
WindowIO : : WindowIO ( DFContextShared * schr )
2009-12-12 17:20:25 -07:00
{
2010-05-26 04:24:45 -06:00
d = new Private ( schr - > p ) ;
2009-12-22 14:19:39 -07:00
}
// dtor
2010-05-26 04:24:45 -06:00
WindowIO : : ~ WindowIO ( )
2010-02-25 05:41:57 -07:00
{
delete d ;
}
2009-12-12 17:20:25 -07:00
2009-12-22 14:19:39 -07:00
// TODO: also investigate possible problems with UIPI on Vista and 7
2010-05-26 04:24:45 -06:00
void WindowIO : : TypeStr ( const char * input , int delay , bool useShift )
2009-12-22 14:19:39 -07:00
{
2009-12-12 17:20:25 -07:00
//sendmessage needs a window handle HWND, so have to get that from the process HANDLE
window myWindow ;
2009-12-22 14:19:39 -07:00
myWindow . pid = d - > p - > getPID ( ) ;
2009-12-12 17:20:25 -07:00
EnumWindows ( EnumWindowsProc , ( LPARAM ) & myWindow ) ;
char cChar ;
2010-09-19 17:49:45 -06:00
DWORD dfProcess = GetWindowThreadProcessId ( myWindow . windowHandle , NULL ) ;
DWORD currentProcess = GetCurrentThreadId ( ) ;
AttachThreadInput ( currentProcess , dfProcess , TRUE ) ; //The two threads have to have attached input in order to change the keyboard state, which is needed to set the shift state
2009-12-22 14:19:39 -07:00
while ( ( cChar = * input + + ) ) // loops through chars
2009-12-12 17:20:25 -07:00
{
short vk = VkKeyScan ( cChar ) ; // keycode of char
if ( useShift | | ( vk > > 8 ) & 1 ) // char is capital, so need to hold down shift
{
2010-09-19 17:49:45 -06:00
vk = vk & 0xFF ; // remove the shift state from the virtual key code
2009-12-18 18:10:05 -07:00
BYTE keybstate [ 256 ] = { 0 } ;
BYTE keybstateOrig [ 256 ] = { 0 } ;
GetKeyboardState ( ( LPBYTE ) & keybstateOrig ) ;
GetKeyboardState ( ( LPBYTE ) & keybstate ) ;
keybstate [ VK_SHIFT ] | = 0x80 ; //Set shift state to on in variable
SetKeyboardState ( ( LPBYTE ) & keybstate ) ; //set the current state to the variable
SendMessage ( myWindow . windowHandle , WM_KEYDOWN , vk , 0 ) ;
SendMessage ( myWindow . windowHandle , WM_KEYUP , vk , 0 ) ;
SetKeyboardState ( ( LPBYTE ) & keybstateOrig ) ; // reset the shift state to the original state
2009-12-12 17:20:25 -07:00
}
else
{
2009-12-18 18:10:05 -07:00
SendMessage ( myWindow . windowHandle , WM_KEYDOWN , vk , 0 ) ;
SendMessage ( myWindow . windowHandle , WM_KEYUP , vk , 0 ) ;
2009-12-12 17:20:25 -07:00
}
}
2010-09-19 17:49:45 -06:00
AttachThreadInput ( currentProcess , dfProcess , FALSE ) ; //detach the threads
2009-12-12 17:20:25 -07:00
Sleep ( delay ) ;
}
2009-12-22 14:19:39 -07:00
2010-05-26 04:24:45 -06:00
void WindowIO : : TypeSpecial ( t_special command , int count , int delay )
2009-12-12 17:20:25 -07:00
{
if ( command ! = WAIT )
{
HWND currentWindow = GetForegroundWindow ( ) ;
window myWindow ;
2009-12-22 14:19:39 -07:00
myWindow . pid = d - > p - > getPID ( ) ;
2009-12-12 17:20:25 -07:00
EnumWindows ( EnumWindowsProc , ( LPARAM ) & myWindow ) ;
for ( int i = 0 ; i < count ; i + + )
{
2009-12-18 18:10:05 -07:00
SendMessage ( myWindow . windowHandle , WM_KEYDOWN , ksTable [ command ] , 0 ) ;
SendMessage ( myWindow . windowHandle , WM_KEYUP , ksTable [ command ] , 0 ) ;
2009-12-12 17:20:25 -07:00
}
Sleep ( delay ) ;
}
else
{
Sleep ( delay * count ) ;
}
}