home *** CD-ROM | disk | FTP | other *** search
- // KeyPush.lib - PM routines to control, or mimic, the pushing of
- // ver.1 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.
- //
- //**** KeyPushFocusID(): Select focus window specification for this library
- // SYNTAX: int KeyPushFocusID(NULL) // this is the default
- // int KeyPushFocusID(string TopLevelTitle[,TempMakeActive])
- // int KeyPushFocusID(int TopLevelHandle[,TempMakeActive])
- // int KeyPushFocusID(int FocusWindowHandle)
- // WHERE: NULL: if NULL or 0 then will always send to the currently active focus window
- // TopLevelTitle: ascii string - will send to focus window of this top-level window
- // TopLevelHandle: handle for top-level window - will send to focus window of this top-level window
- // FocusWindowHandle: will send directly to this window handle
- // TempMakeActive: This window (or top-level window) for this application
- // must be the active window while the keystrokes are
- // sent, and will temporarily be made active. The default
- // is TRUE for TopLevelTitle and TopLevelHandle methods, else
- // this doesn't apply and does not switch active window.
- // RETURN: Return window that would get focus NOW according to this setting, which
- // may be NULL if this setting wouldn't work
- // NOTE: For TopLevelTitle and TopLevelHandle methods, these library routines
- // may need to temporarily alter the activation of different windows if
- // you don't specify TempMakeActive=False, which will look messy if the
- // window you're sending to is not currently the active window. In these
- // situations, or if you're sending lots of KeyPushxxx messages, you may
- // want to make the application active first or get the FocusWindowHandle
- // if the window won't change. For top level windows where this is not
- // TempMakeActive is not given or is True, then will not make the application
- // active but will only send to sub-window that last had active focus.
- //
- //
- //**** KeyStroke(): Press and release a key or combination of keys
- // SYNTAX: int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]byte Character)
- // int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]int VirtualKeyCode)
- // int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]string KeyString)
- // WHERE: Holdkey...: 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.
- // Character: ascii character to send
- // VirtualKeyCode: one of the VK_ key codes (see below)
- // KeyString: Ascii string to send
- // RETURN: Return handle keys were sent to; 0 if no handle found
- // EXAMPLES: To press the 'S' key: KeyStroke('S');
- // To type a sentence: KeyStroke("On top of Old Smokey!\n");
- // To type Alt-F1: KeyStroke("VK_ALT,VK_F1);
- // To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R');
- //
- //
- //**** SpeedKeys(): Send character messages
- // SYNTAX: int SpeedKeys(string AsciiString[,DelayBetweenKeys])
- // int SpeedKeys(byte Character[,DelayBetweenKeys])
- // WHERE: AsciiString: string of characters to send
- // Character: single character to send
- // DelayBetweenKeys: Approximate time, in milliseconds, to wait after
- // sending each key message
- // NOTE: Speed keys sends only WM_CHAR messages to an application and is much
- // faster than 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.
- //
- //
- //**** VKeyDown(): Press down a key (no release yet)
- // SYNTAX: int VKeyDown(int KeyCode)
- // WHERE: KeyCode: Virtual VK_ key or character key
- // RETURN: Return handle keys were sent to; 0 if no handle found
- //
- //
- //**** VKeyUP(): Release a key (that has been pressed down)
- // SYNTAX: int VKeyUP(int KeyCode)
- // WHERE: KeyCode: Virtual VK_ key or character key
- // RETURN: Return handle keys were sent to; 0 if no handle found
- //
- //
-
- #include <WinMsg.lib>
- #include <GiveMem.lib>
- #include <WinTools.lib>
-
- /*** Virtual key values *************************************************/
- #define VK_BUTTON1 0x01
- #define VK_BUTTON2 0x02
- #define VK_BUTTON3 0x03
- #define VK_BREAK 0x04
- #define VK_BACKSPACE 0x05
- #define VK_TAB 0x06
- #define VK_BACKTAB 0x07
- #define VK_NEWLINE 0x08
- #define VK_SHIFT 0x09
- #define VK_CTRL 0x0A
- #define VK_ALT 0x0B
- #define VK_ALTGRAF 0x0C
- #define VK_PAUSE 0x0D
- #define VK_CAPSLOCK 0x0E
- #define VK_ESC 0x0F
- #define VK_SPACE 0x10
- #define VK_PAGEUP 0x11
- #define VK_PAGEDOWN 0x12
- #define VK_END 0x13
- #define VK_HOME 0x14
- #define VK_LEFT 0x15
- #define VK_UP 0x16
- #define VK_RIGHT 0x17
- #define VK_DOWN 0x18
- #define VK_PRINTSCRN 0x19
- #define VK_INSERT 0x1A
- #define VK_DELETE 0x1B
- #define VK_SCRLLOCK 0x1C
- #define VK_NUMLOCK 0x1D
- #define VK_ENTER 0x1E
- #define VK_SYSRQ 0x1F
- #define VK_F1 0x20
- #define VK_F2 0x21
- #define VK_F3 0x22
- #define VK_F4 0x23
- #define VK_F5 0x24
- #define VK_F6 0x25
- #define VK_F7 0x26
- #define VK_F8 0x27
- #define VK_F9 0x28
- #define VK_F10 0x29
- #define VK_F11 0x2A
- #define VK_F12 0x2B
- #define VK_F13 0x2C
- #define VK_F14 0x2D
- #define VK_F15 0x2E
- #define VK_F16 0x2F
- #define VK_F17 0x30
- #define VK_F18 0x31
- #define VK_F19 0x32
- #define VK_F20 0x33
- #define VK_F21 0x34
- #define VK_F22 0x35
- #define VK_F23 0x36
- #define VK_F24 0x37
- #define VK_ENDDRAG 0x38
- #define VK_MENU VK_F10
-
-
- KeyPushFocusID(pFocusID,pTempMakeActive)
- {
- gFocusIDIsTopLevel = False;
- if ( !pFocusID ) {
- gFocusID = 0;
- gKPTempMakeActive = False;
- } else if ( 0 != DataDimension(pFocusID) ) {
- // find window based on string
- if ( !(gFocusID = GetWindowHandle(pFocusID)) )
- return 0;
- gFocusIDIsTopLevel = True;
- } else {
- // determine if this is one of the top level windows
- lEnum = WinBeginEnumWindows(HWND_DESKTOP);
- while ( lChild = WinGetNextWindow(lEnum) ) {
- if ( pFocusID == lChild ) {
- gFocusIDIsTopLevel = True;
- break;
- }
- }
- WinEndEnumWindows(lEnum);
- gFocusID = pFocusID;
- }
- gKPTempMakeActive = ( va_arg() < 2 ) ? True : pTempMakeActive ;
-
- // gFocusID parameter is set. Return window handle as regular KeyPush calls would
- KeyPushInitialize();
- KeyPushTerminate();
- return gKPFocusWindow;
- }
-
-
- KeyStroke(pKey1,pKey2,pKey3/*etc...*/)
- {
- if ( KeyPushInitialize() ) {
- lArgCount = va_arg();
- // if more than one parameter, then hold down all but the last one
- for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
- KeyDown(va_arg(lKeyC-1));
-
- lKey = va_arg(lArgCount-1);
- // Treat differently depending on whether Virtual Key Code, char, or string
- if ( CMM_BYTE == DataType(lKey) ) {
- if ( 1 == DataDimension(lKey) ) {
- // send entire string one character at a time
- for ( lIdx = 0; lKey[lIdx]; lIdx++ ) {
- KeyDown(lKey[lIdx]);
- KeyUp(lKey[lIdx]);
- }
- } else {
- // send a single character out the port
- KeyDown(lKey);
- KeyUp(lKey);
- }
- } else {
- // simply a virtual key code
- KeyDown(lKey);
- KeyUp(lKey);
- }
-
- // if more than one parameter, then reverse release all but the last one
- for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
- KeyUp(va_arg(lArgCount-lKeyC-1));
- }
- KeyPushTerminate();
- return gKPFocusWindow;
- }
-
- #define WM_CHAR 0x007a
- #define WM_TRANSLATEACCEL 0x004b
-
- /* WM_CHAR fs field bits */
- #define KC_CHAR 0x0001
- #define KC_VIRTUALKEY 0x0002
- #define KC_SCANCODE 0x0004
- #define KC_SHIFT 0x0008
- #define KC_CTRL 0x0010
- #define KC_ALT 0x0020
- #define KC_KEYUP 0x0040
- #define KC_PREVDOWN 0x0080
- #define KC_LONEKEY 0x0100
- #define KC_DEADKEY 0x0200
- #define KC_COMPOSITE 0x0400
- #define KC_INVALIDCOMP 0x0800
- #define KC_TOGGLE 0x1000
- #define KC_INVALIDCHAR 0x2000
- #define KC_DBCSRSRVD1 0x4000
- #define KC_DBCSRSRVD2 0x8000
-
- gKPLatestKeyDown = FALSE; // True on call to key down, false on KeyUp
-
- KeyDown(pKey)
- {
- if ( KeyPushInitialize() ) {
- // Save the current state of the 256-byte keyboard buffer
- lKeyTable = GetKeyboardTable();
-
- gKPLatestKeyDown = TRUE;
-
- if ( CMM_BYTE == DataType(pKey) ) {
- // pushing just a character
- lfsflags = KC_CHAR;
- lusch = pKey;
- lusvk = 0;
- } else {
- // pushing a virtual key
- lfsflags = KC_VIRTUALKEY;
- lusch = 0;
- lusvk = pKey;
- if ((lKeyTable[pKey] = (lKeyTable[pKey] | 0x80) ^ 1) & 0x01)
- lfsflags |= KC_TOGGLE;
- SetKeyboardTable(lKeyTable);
- }
-
- if ( lKeyTable[VK_SHIFT] & 0x80 )
- lfsflags |= KC_SHIFT;
- if ( lKeyTable[VK_ALT] & 0x80 )
- lfsflags |= KC_ALT;
- if ( lKeyTable[VK_CTRL] & 0x80 )
- lfsflags |= KC_CTRL;
-
- SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
- }
- KeyPushTerminate();
- return gKPFocusWindow;
- }
-
- KeyUp(pKey)
- {
- if ( KeyPushInitialize() ) {
- // Save the current state of the 256-byte keyboard buffer
- lKeyTable = GetKeyboardTable();
-
- // set some fsflags based on keys currently pressed
- lfsflags = KC_KEYUP /*| KC_PREVDOWN*/;
-
- if ( CMM_BYTE == DataType(pKey) ) {
- // pushing just a character
- lfsflags |= KC_CHAR;
- if ( (lKeyTable[VK_CTRL] & 0x80) && isalpha(pKey) )
- // convert to control character
- lusch = toupper(pKey) - 'A' + 1;
- else
- lusch = pKey;
- lusvk = 0;
- } else {
- // pushing a virtual key
- lfsflags |= KC_VIRTUALKEY;
- lusch = 0;
- lusvk = pKey;
- if ((lKeyTable[pKey] &= 0x7F) & 0x01);
- lfsflags |= KC_TOGGLE;
- SetKeyboardTable(lKeyTable);
- }
-
- if ( lKeyTable[VK_SHIFT] & 0x80 )
- lfsflags |= KC_SHIFT;
- if ( lKeyTable[VK_ALT] & 0x80 )
- lfsflags |= KC_ALT;
- if ( lKeyTable[VK_CTRL] & 0x80 )
- lfsflags |= KC_CTRL;
-
- if ( gKPLatestKeyDown )
- lfsflags |= KC_LONEKEY;
- gKPLatestKeyDown = FALSE;
-
- // send message to window that this key is being pressed
- SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
- }
- KeyPushTerminate();
- return gKPFocusWindow;
- }
-
- SpeedKeys(pAsciiString,pDelayBetweenCharacters)
- {
- if ( KeyPushInitialize() ) {
- if ( 1 == DataDimension(pAsciiString) ) { lChar = pAsciiString; }
- else { lChar[1] = '\0'; lChar[0] = pAsciiString; }
- for ( ; lChar[0]; lChar++ ) {
- lParam1 = ((KC_CHAR | KC_LONEKEY)) | (1 << 16);
- WinSendMsg(gKPFocusWindow,WM_CHAR,lParam1,lChar[0]);
- if ( 1 < va_arg() )
- suspend(pDelayBetweenCharacters);
- }
- }
- KeyPushTerminate();
- return gKPFocusWindow;
- }
-
-
- /***********************************************************
- *** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES ***
- ***********************************************************/
-
- gFocusID = 0;
- gFocusIDIsTopLevel = False; // set true if using Focus ID that is top-level window
- gKeyPushInitializeDepth = 0; // keep track how many times recursively called
- gKPFocusWindow; // KeyPushInitialize sets to window
- gKPSaveActiveWindow = 0;
- gKPTempMakeActive = True;
-
- KeyPushInitialize()
- {
- // keep track of how many times called. get actual ID to send to on first
- // level, on recursive calls revert to first return. If need to activate
- // window then do so. Return FALSE for failure, else non-false is TRUE
- if ( 0 == gKeyPushInitializeDepth++ ) {
- gKPSaveActiveWindow = 0; // assume don't need to change focus
- if ( !gFocusID ) {
- // take whatever is the focus window
- gKPFocusWindow = GetFocus();
- } else if ( !IsWindow(gFocusID) ) {
- gKPFocusWindow = 0; // gFocusID is not valid
- } else if ( !gFocusIDIsTopLevel ) {
- gKPFocusWindow = gFocusID; // this isn't top level, so is actual window to send to
- } else {
- // this is a top level window, if KeyPushFocusID() set up to make active
- // when sending keystrokes then do so, else send to the child that was
- // the focus when this window was active
- if ( gFocusID == (lActive=GetActiveWindow()) ) {
- gKPFocusWindow = GetFocus();
- } else {
- if ( gKPTempMakeActive ) {
- gKPSaveActiveWindow = lActive;
- SetActiveWindow(gFocusID);
- gKPFocusWindow = GetFocus();
- } else {
- gKPFocusWindow = GetFocusChild(gFocusID);
- }
- }
- }
-
- }
- return gKPFocusWindow;
- }
-
- KeyPushTerminate()
- {
- // undo what KeyPushInitialize did. restore active window if KeyPushInitialize()
- // activated it. Must call same number of times as KeyPushInitialize.
- if ( 0 == --gKeyPushInitializeDepth ) {
- if ( gKPSaveActiveWindow ) {
- SetActiveWindow(gKPSaveActiveWindow);
- }
- }
- }
-
- #define HWND_DESKTOP 1
- #define ORD_WIN32SETKEYBOARDSTATETABLE 921
-
- GetKeyboardTable() // return 256 byte buffer for current keyboard state
- {
- lTable[255] = '\0'; // initialize 256-byte key table
- DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
- HWND_DESKTOP,lTable,FALSE);
- return(lTable);
- }
-
- SetKeyboardTable(pKeyBuf) // set the 256 byte buffer for current keyboard state
- {
- DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
- HWND_DESKTOP,pKeyBuf,TRUE);
- }
-
-
- /***********************************/
- /*** SEND KEY MESSAGES TO WINDOW ***/
-
- SendMessageAndAccelTable(pParam1,pParam2)
- // Send this message and send an accelerator table message
- {
- // see that the current window has been given access to the shared
- // memory table memory
- lSharedMemory = GiveMemoryToWindow(gKPFocusWindow);
-
- // copy the message to the globally allocated and shared memory
- // build blob message to give to accelerator table
- poke( lSharedMemory, gKPFocusWindow, UWORD32 );
- poke( lSharedMemory+4, WM_CHAR, UWORD32 );
- poke( lSharedMemory+8, pParam1, UWORD32 );
- poke( lSharedMemory+12, pParam2, UWORD32 );
-
- // send message to window accelerator in case it wants to translate
- WinSendMsg(gKPFocusWindow,WM_TRANSLATEACCEL,lSharedMemory,0);
- // send translated message to the window
- WinSendMsg(peek(lSharedMemory,UWORD32),peek(lSharedMemory+4,UWORD32),
- peek(lSharedMemory+8,UWORD32),peek(lSharedMemory+12,UWORD32));
- }
-