// KeyPush.lib - Windows routines to control, or mimic, the pushing of // keys on the keyboard. This is one method of controlling // windows applications. The functions in this library work // by sending keyboard messages to the focus window as if // the key messages were actually being sent by Windows. // //------------------------------- KeyStroke() ------------------------------- // KeyStroke([Holdkey1,HoldKey2,HoldKey3...]Character) // KeyStroke([Holdkey1,HoldKey2,HoldKey3...]VirtualKeyCode) // KeyStroke([Holdkey1,HoldKey2,HoldKey3...]KeyString) // - Press and release a key or keys. If HoldKeys are given then will mimic // that these keys are pressed before KeyCode or KeyString, and then // will press and release KeyCode or KeyString, and then will release // HoldKeys in reverse order. // Examples: To press the 'S' key: KeyStroke('S'); // To type a sentence: KeyStroke("On top of Old Smokey!"); // To type Alt-F1: KeyStroke(VK_ALT,VK_F1); // To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R'); // //------------------------------- VKeyDown() ------------------------------- // VKeyDown(KeyCode) // - Press virtual key for Window. // Key is not released. // Example: KeyDown(VK_SHIFT) // //------------------------------- VKeyUp() ------------------------------- // VKeyUp(KeyCode) // - Release key for focus Window. // Example: KeyUp(VK_SHIFT) // //------------------------------- SpeedKeys() ------------------------------- // SpeedKeys(AsciiString[,DelayBetweenKeys]) // Speed keys sends only WM_CHAR messages to an application and is much // faster thatn KeyStroke(), but should only be used for regular ascii // strings passed to applications that don't need to for each specific // keystroke. So, if KeyStroke() is too slow and you're entering a // stretch of plain text, then use this function. If DelayBetweenKeys // parameter is given then this is how many milliseconds to wait between // each keystroke. // //----------------------------- FocusWindow ------------------------------- // FocusWindow // This integer controls the value return by GetFocus(). If it is zero // Then GetFocus() will query Windows for whatever Window has the // current focus, else GetFocus() return FocusWindow. // //------------------------------ GetFocus() ------------------------------- // GetFocus() // Return the window handle that keystrokes are to be sent to. If // FocusWindow is non-zero then this returns FocusWindow, else this // queries Windows for the handle of the window with the current focus. FocusWindow = 0; // If this is 0, then will send messages to whatever window // has the focus. If this is not-zero then will send // the FocuseWindow window handle. #define VK_LBUTTON 0x01 #define VK_RBUTTON 0x02 #define VK_CANCEL 0x03 #define VK_MBUTTON 0x04 #define VK_BACK 0x08 #define VK_TAB 0x09 #define VK_CLEAR 0x0C #define VK_RETURN 0x0D #define VK_SHIFT 0x10 #define VK_CONTROL 0x11 #define VK_MENU 0x12 #define VK_ALT VK_MENU #define VK_PAUSE 0x13 #define VK_CAPITAL 0x14 #define VK_ESCAPE 0x1B #define VK_SPACE 0x20 #define VK_PRIOR 0x21 #define VK_NEXT 0x22 #define VK_END 0x23 #define VK_HOME 0x24 #define VK_LEFT 0x25 #define VK_UP 0x26 #define VK_RIGHT 0x27 #define VK_DOWN 0x28 #define VK_SELECT 0x29 #define VK_PRINT 0x2A #define VK_EXECUTE 0x2B #define VK_SNAPSHOT 0x2C #define VK_INSERT 0x2D #define VK_DELETE 0x2E #define VK_HELP 0x2F /* VK_A thru VK_Z are the same as their ASCII equivalents: 'A' thru 'Z' */ /* VK_0 thru VK_9 are the same as their ASCII equivalents: '0' thru '9' */ #define VK_NUMPAD0 0x60 #define VK_NUMPAD1 0x61 #define VK_NUMPAD2 0x62 #define VK_NUMPAD3 0x63 #define VK_NUMPAD4 0x64 #define VK_NUMPAD5 0x65 #define VK_NUMPAD6 0x66 #define VK_NUMPAD7 0x67 #define VK_NUMPAD8 0x68 #define VK_NUMPAD9 0x69 #define VK_MULTIPLY 0x6A #define VK_ADD 0x6B #define VK_SEPARATOR 0x6C #define VK_SUBTRACT 0x6D #define VK_DECIMAL 0x6E #define VK_DIVIDE 0x6F #define VK_F1 0x70 #define VK_F2 0x71 #define VK_F3 0x72 #define VK_F4 0x73 #define VK_F5 0x74 #define VK_F6 0x75 #define VK_F7 0x76 #define VK_F8 0x77 #define VK_F9 0x78 #define VK_F10 0x79 #define VK_F11 0x7A #define VK_F12 0x7B #define VK_F13 0x7C #define VK_F14 0x7D #define VK_F15 0x7E #define VK_F16 0x7F #define VK_NUMLOCK 0x90 KeyStroke(Key1,Key2,Key3/*etc...*/) { _argCount = va_arg(); // if more than one parameter, then hold down all but the last one for ( k = 1; k < _argCount; k++ ) VKeyDown(va_arg(k-1)); _key = va_arg(_argCount-1); // Treat differently depending on whether Virtual Key Code, char, or string if ( CMM_BYTE == DataType(_key) ) { if ( 1 == DataDimension(_key) ) { // send entire string one character at a time for ( k = 0; _key[k]; k++ ) CharacterStroke(_key[k]); } else { // send a single character out the port CharacterStroke(_key); } } else { // simply a virtual key code VKeyDown(_key); VKeyUp(_key); } // if more than one parameter, then reverse release all but the last one for ( k = 1; k < _argCount; k++ ) VKeyUp(va_arg(_argCount-k-1)); } VKeyDown(KeyCode) { // Save the current state of the 256-byte keyboard buffer _keyBuffer = GetKeyboardState(); // build hi word of lParam for the WM_KEYDOWN or WM_SYSKEYDOWN message // 1: Get Scan Code for this virtual key _HiWord = MapVirtualKey(KeyCode,0); // 2: Set bit for if this is an extended key if ( (VK_PRIOR <= KeyCode && KeyCode <= VK_HELP) || (VK_F1 <= KeyCode && KeyCode <= VK_F16) ) _HiWord |= 0x100; // 3: If ALT key is down but not the control key, then set that bit // and change message to WM_SYSKEYDOWN if ( (KeyCode == VK_ALT || (GetKeyState(VK_ALT) & 0x8000) ) && !(GetKeyState(VK_CONTROL) & 0x8000) ) _HiWord |= 0x2000, _message = WM_SYSKEYDOWN; else _message = WM_KEYDOWN; // save in _keyBuffer that this key is now down _keyBuffer[KeyCode] = (_KeyBuffer[KeyCode] ^ 0x01) | 0x80; SetKeyboardState(_keyBuffer); // send message to window that this key is being pressed PostMessage(GetFocus(),_message,KeyCode,1,_HiWord); } VKeyUp(KeyCode) { // Save the current state of the 256-byte keyboard buffer _keyBuffer = GetKeyboardState(); // build hi word of lParam for the WM_KEYUP or WM_SYSKEYUP message // 1: Get Scan Code for this virtual key _HiWord = MapVirtualKey(KeyCode,0); // 2: Set bit for if this is an extended key if ( (VK_PRIOR <= KeyCode && KeyCode <= VK_HELP) || (VK_F1 <= KeyCode && KeyCode <= VK_F16) ) _HiWord |= 0x100; // 3: If ALT key is down but not the control key, then set that bit // and change message to WM_SYSKEYDOWN if ( (KeyCode == VK_ALT || (GetKeyState(VK_ALT) & 0x8000) ) && !(GetKeyState(VK_CONTROL) & 0x8000) ) _HiWord |= 0x2000, _message = WM_SYSKEYUP; else _message = WM_KEYUP; // 4: set hi 2 bits that key WAS down _HiWord |= 0xC000; // save in _keyBuffer that this key is now up _keyBuffer[KeyCode] &= 0x7F; SetKeyboardState(_keyBuffer); // send message to window that this key is being pressed PostMessage(GetFocus(),_message,KeyCode,1,_HiWord); } SpeedKeys(AsciiString,DelayBetweenKeys) { _focus = GetFocus(); for ( c = AsciiString; c[0]; c++ ) { PostMessage(_focus,WM_CHAR,c[0],1,0); // DelayBetweenKeys is optional. If not supplied then no delay if ( 1 < va_arg() ) suspend(DelayBetweenKeys); } } /*********************************************************** *** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES *** ***********************************************************/ CharacterStroke(c) // press this character. This is only tricky in that { // must check SHIFT state for alphabetic characters // Get virtual codes for this character _vkeystate = DynamicLink("KEYBOARD","VKKEYSCAN",SWORD16,PASCAL,c) if ( -1 != _vkeystate ) { vkey = _vkeystate & 0xFF; switch( _vkeystate >> 8 ) { case 0: // no shift state case 1: // shift state if ( (0 != (GetKeyState(VK_SHIFT) & 0x80)) ^ (0 != (GetKeyState(VK_CAPITAL) & 0x01)) ^ (0 != (_vkeystate & 0x100)) ) { // need to toggle the shift key to change case of this character if ( GetKeyState(VK_SHIFT) & 0x80 ) VKeyUp(VK_SHIFT), KeyStroke(vkey), VKeyDown(VK_SHIFT); else KeyStroke(VK_SHIFT,vkey); } else KeyStroke(vkey); break; case 2: // control character KeyStroke(VK_CONTROL,vkey); break; case 6: // control + alt KeyStroke(VK_CONTROL,VK_ALT,vkey); break; case 7: // SHIFT+CONTROL+ALT KeyStroke(VK_SHIFT,VK_CONTROL,VK_ALT,vkey); break; default: // unknown break; } } } GetKeyboardState() // return 256 byte buffer for current keyboard state { _keyBuf[255] = '\0'; // initialize a 256-byte array DynamicLink("USER","GETKEYBOARDSTATE",SWORD16,PASCAL,_keyBuf); return(_KeyBuf); } SetKeyboardState(_keyBuf) // set the 256 byte buffer for current keyboard state { DynamicLink("USER","SETKEYBOARDSTATE",SWORD16,PASCAL,_keyBuf); } GetKeyState(VKey) { return( DynamicLink("USER","GETKEYSTATE",SWORD16,PASCAL,VKey) ); } MapVirtualKey(wCode,wMapType) { return( DynamicLink("KEYBOARD","MAPVIRTUALKEY",UWORD16,PASCAL,wCode,wMapType) ); } GetFocus() // return handle of Window with the focus { return( FocusWindow ? FocusWindow : DynamicLink("USER","GETFOCUS",UWORD16,PASCAL) ); }