home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / CENVIW9.ZIP / KEYPUSH.LIB < prev    next >
Text File  |  1994-03-08  |  15KB  |  407 lines

  1. // KeyPush.lib - Windows routines to control, or mimic, the pushing of
  2. // ver.1         keys on the keyboard.  This is one method of controlling
  3. //               windows applications.  The functions in this library work
  4. //               by sending keyboard messages to the focus window as if
  5. //               the key messages were actually being sent by Windows.
  6. //
  7. //**** KeyPushFocusID(): Select focus window specification for this library
  8. // SYNTAX: int KeyPushFocusID(NULL)   // this is the default
  9. //         int KeyPushFocusID(string TopLevelTitle)
  10. //         int KeyPushFocusID(int TopLevelHandle)
  11. //         int KeyPushFocusID(int FocusWindowHandle)
  12. // WHERE: NULL: if NULL or 0 then will always send to the currently active focus window
  13. //        TopLevelTitle: ascii string - will send to focus window of this top-level window
  14. //        TopLevelHandle: handle for top-level window - will send to focus window of this top-level window
  15. //        FocusWindowHandle: will send directly to this window handle
  16. // RETURN: Return window that would get focus NOW according to this setting, which
  17. //         may be NULL if this setting wouldn't work
  18. // NOTE: For TopLevelTitle and TopLevelHandle methods, these library routines
  19. //       may need to temporarily alter the activation of different windows, which
  20. //       will look messy if the window you're sending to is not currently the
  21. //       active window.  In these situations, or if you're sending lots of
  22. //       KeyPushxxx messages, you may want to make the application active
  23. //       first or get the FocusWindowHandle if the window won't change.
  24. //       If this function is never called then defaults to NULL: active focus window.
  25. //
  26. //
  27. //**** KeyStroke(): Press and release a key or combination of keys
  28. // SYNTAX: int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]byte Character)
  29. //         int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]int VirtualKeyCode)
  30. //         int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]string KeyString)
  31. // WHERE: Holdkey...: mimic that these keys are pressed before KeyCode or KeyString, and then
  32. //                    will press and release KeyCode or KeyString, and then will release
  33. //                    HoldKeys in reverse order.
  34. //        Character: ascii character to send
  35. //        VirtualKeyCode: one of the VK_ key codes (see below)
  36. //        KeyString: Ascii string to send
  37. // RETURN: Return handle keys were sent to; 0 if no handle found
  38. // EXAMPLES: To press the 'S' key: KeyStroke('S');
  39. //           To type a sentence: KeyStroke("On top of Old Smokey!\r");
  40. //           To type Alt-F1: KeyStroke(VK_ALT,VK_F1);
  41. //           To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R');
  42. //
  43. //
  44. //**** SpeedKeys(): Send character messages
  45. // SYNTAX: int SpeedKeys(string AsciiString[,DelayBetweenKeys])
  46. //         int SpeedKeys(byte Character[,DelayBetweenKeys])
  47. // WHERE: AsciiString: string of characters to send
  48. //        Character: single character to send
  49. //        DelayBetweenKeys: Approximate time, in milliseconds, to wait after
  50. //                          sending each key message
  51. // NOTE: Speed keys sends only WM_CHAR messages to an application and is much
  52. //       faster than KeyStroke(), but should only be used for regular ascii
  53. //       strings passed to applications that don't need to for each specific
  54. //       keystroke.  So, if KeyStroke() is too slow and you're entering a
  55. //       stretch of plain text, then use this function.
  56. //
  57. //
  58. //**** VKeyDown(): Press down a key (no release yet)
  59. // SYNTAX: int VKeyDown(int KeyCode)
  60. // WHERE: KeyCode: Virtual VK_ key or character key
  61. // RETURN: Return handle keys were sent to; 0 if no handle found
  62. //
  63. //
  64. //**** VKeyUP(): Release a key (that has been pressed down)
  65. // SYNTAX: int VKeyUP(int KeyCode)
  66. // WHERE: KeyCode: Virtual VK_ key or character key
  67. // RETURN: Return handle keys were sent to; 0 if no handle found
  68. //
  69. //
  70. //***** GetFocus(): Get window with the input focus
  71. // SYNTAX: int GetFocus()
  72. // RETURN: Return handle of window that owns keyboard focus
  73. // NOTE: This will return the handle of window that actually has Windows
  74. //       keyboard focus, not necessarily that window that was described
  75. //       in the call to KeyPushFocusID()
  76. //
  77. //
  78.  
  79. #define VK_LBUTTON   0x01
  80. #define VK_RBUTTON   0x02
  81. #define VK_CANCEL    0x03
  82. #define VK_MBUTTON   0x04
  83. #define VK_BACK      0x08
  84. #define VK_TAB       0x09
  85. #define VK_CLEAR     0x0C
  86. #define VK_RETURN    0x0D
  87. #define VK_SHIFT     0x10
  88. #define VK_CONTROL   0x11
  89. #define VK_MENU      0x12
  90. #define VK_ALT       VK_MENU
  91. #define VK_PAUSE     0x13
  92. #define VK_CAPITAL   0x14
  93. #define VK_ESCAPE    0x1B
  94. #define VK_SPACE     0x20
  95. #define VK_PRIOR     0x21
  96. #define VK_NEXT      0x22
  97. #define VK_END       0x23
  98. #define VK_HOME      0x24
  99. #define VK_LEFT      0x25
  100. #define VK_UP        0x26
  101. #define VK_RIGHT     0x27
  102. #define VK_DOWN      0x28
  103. #define VK_SELECT    0x29
  104. #define VK_PRINT     0x2A
  105. #define VK_EXECUTE   0x2B
  106. #define VK_SNAPSHOT  0x2C
  107. #define VK_INSERT    0x2D
  108. #define VK_DELETE    0x2E
  109. #define VK_HELP      0x2F
  110. /* VK_A thru VK_Z are the same as their ASCII equivalents: 'A' thru 'Z' */
  111. /* VK_0 thru VK_9 are the same as their ASCII equivalents: '0' thru '9' */
  112. #define VK_NUMPAD0   0x60
  113. #define VK_NUMPAD1   0x61
  114. #define VK_NUMPAD2   0x62
  115. #define VK_NUMPAD3   0x63
  116. #define VK_NUMPAD4   0x64
  117. #define VK_NUMPAD5   0x65
  118. #define VK_NUMPAD6   0x66
  119. #define VK_NUMPAD7   0x67
  120. #define VK_NUMPAD8   0x68
  121. #define VK_NUMPAD9   0x69
  122. #define VK_MULTIPLY  0x6A
  123. #define VK_ADD       0x6B
  124. #define VK_SEPARATOR 0x6C
  125. #define VK_SUBTRACT  0x6D
  126. #define VK_DECIMAL   0x6E
  127. #define VK_DIVIDE    0x6F
  128. #define VK_F1        0x70
  129. #define VK_F2        0x71
  130. #define VK_F3        0x72
  131. #define VK_F4        0x73
  132. #define VK_F5        0x74
  133. #define VK_F6        0x75
  134. #define VK_F7        0x76
  135. #define VK_F8        0x77
  136. #define VK_F9        0x78
  137. #define VK_F10       0x79
  138. #define VK_F11       0x7A
  139. #define VK_F12       0x7B
  140. #define VK_F13       0x7C
  141. #define VK_F14       0x7D
  142. #define VK_F15       0x7E
  143. #define VK_F16       0x7F
  144. #define VK_NUMLOCK   0x90
  145.  
  146. #include <Message.lib>
  147. #include <WinTools.lib>
  148.  
  149. KeyPushFocusID(pFocusID)
  150. {
  151.    if ( !pFocusID ) {
  152.       gFocusID = 0;
  153.    } else if ( 0 != DataDimension(pFocusID) ) {
  154.       // find window based on string
  155.       if ( !(gFocusID = GetWindowHandle(pFocusID)) )
  156.          return 0;
  157.    } else {
  158.       gFocusID = pFocusID;
  159.    }
  160.  
  161.    // gFocusID parameter is set.  Return window handle as regular KeyPush calls would
  162.    KeyPushInitialize();
  163.    KeyPushTerminate();
  164.    return gKPFocusWindow;
  165. }
  166.  
  167.  
  168. KeyStroke(pKey1,pKey2,pKey3/*etc...*/)
  169. {
  170.    if ( KeyPushInitialize() ) {
  171.       lArgCount = va_arg();
  172.  
  173.       // if more than one parameter, then hold down all but the last one
  174.       for ( lHoldKey = 1; lHoldKey < lArgCount; lHoldKey++ )
  175.          VKeyDown(va_arg(lHoldKey-1));
  176.  
  177.       // keystroke on remaining key
  178.       lKey = va_arg(lArgCount-1);
  179.       // Treat differently depending on whether Virtual Key Code, char, or string
  180.       if ( CMM_BYTE == DataType(lKey) ) {
  181.          if ( 1 == DataDimension(lKey) ) {
  182.             // send entire string one character at a time
  183.             for ( li = 0; lKey[li]; li++ )
  184.                CharacterStroke(lKey[li]);
  185.          } else {
  186.             // send a single character out the port
  187.             CharacterStroke(lKey);
  188.          }
  189.       } else {
  190.          // simply a virtual key code
  191.          VKeyDown(lKey);
  192.          VKeyUp(lKey);
  193.       }
  194.  
  195.       // release all the keys that were held down
  196.       for ( lHoldKey = 1; lHoldKey < lArgCount; lHoldKey++ )
  197.          VKeyUp(va_arg(lHoldKey-1));
  198.  
  199.    }
  200.    KeyPushTerminate();
  201.    return gKPFocusWindow;
  202. }
  203.  
  204.  
  205. VKeyDown(pKeyCode)
  206. {
  207.    if ( KeyPushInitialize() ) {
  208.       // Save the current state of the 256-byte keyboard buffer
  209.       lKeyBuffer = GetKeyboardState();
  210.  
  211.       // build hi word of lParam for the WM_KEYDOWN or WM_SYSKEYDOWN message
  212.       // 1: Get Scan Code for this virtual key
  213.       lHiWord = MapVirtualKey(pKeyCode,0);
  214.  
  215.       // 2: Set bit for if this is an extended key
  216.       if ( (VK_PRIOR <= pKeyCode && pKeyCode <= VK_HELP)
  217.         || (VK_F1 <= pKeyCode && pKeyCode <= VK_F16) )
  218.          lHiWord |= 0x100;
  219.  
  220.       // 3: If ALT key is down but not the control key, then set that bit
  221.       //    and change message to WM_SYSKEYDOWN
  222.       if ( (pKeyCode == VK_ALT  ||  (GetKeyState(VK_ALT) & 0x80) )
  223.         && !(GetKeyState(VK_CONTROL) & 0x80) )
  224.          lHiWord |= 0x2000, lMsg = WM_SYSKEYDOWN;
  225.       else
  226.          lMsg = WM_KEYDOWN;
  227.  
  228.       // save in lKeyBuffer that this key is now down
  229.       lKeyBuffer[pKeyCode] = (lKeyBuffer[pKeyCode] ^ 0x01) | 0x80;
  230.       SetKeyboardState(lKeyBuffer);
  231.  
  232.       // send message to window that this key is being pressed
  233.       PostMessage(gKPFocusWindow,lMsg,pKeyCode,1,lHiWord);
  234.    }
  235.    KeyPushTerminate();
  236.    return gKPFocusWindow;
  237. }
  238.  
  239.  
  240. VKeyUp(pKeyCode)
  241. {
  242.    if ( KeyPushInitialize() ) {
  243.       // Save the current state of the 256-byte keyboard buffer
  244.       lKeyBuffer = GetKeyboardState();
  245.  
  246.       // build hi word of lParam for the WM_KEYUP or WM_SYSKEYUP message
  247.       // 1: Get Scan Code for this virtual key
  248.       lHiWord = MapVirtualKey(pKeyCode,0);
  249.  
  250.       // 2: Set bit for if this is an extended key
  251.       if ( (VK_PRIOR <= pKeyCode && pKeyCode <= VK_HELP)
  252.         || (VK_F1 <= pKeyCode && pKeyCode <= VK_F16) )
  253.          lHiWord |= 0x100;
  254.  
  255.       // 3: If ALT key is down but not the control key, then set that bit
  256.       //    and change message to WM_SYSKEYDOWN
  257.       if ( (pKeyCode == VK_ALT  ||  (GetKeyState(VK_ALT) & 0x80) )
  258.         && !(GetKeyState(VK_CONTROL) & 0x80) )
  259.          lHiWord |= 0x2000, lMsg = WM_SYSKEYUP;
  260.       else
  261.          lMsg = WM_KEYUP;
  262.  
  263.       // 4: set hi 2 bits that key WAS down
  264.       lHiWord |= 0xC000;
  265.  
  266.       // save in lKeyBuffer that this key is now up
  267.       lKeyBuffer[pKeyCode] &= 0x7F;
  268.       SetKeyboardState(lKeyBuffer);
  269.  
  270.       // send message to window that this key is being pressed
  271.       PostMessage(gKPFocusWindow,lMsg,pKeyCode,1,lHiWord);
  272.    }
  273.    KeyPushTerminate();
  274.    return gKPFocusWindow;
  275. }
  276.  
  277. SpeedKeys(pAsciiString,pDelayBetweenKeys)
  278. {
  279.    if ( KeyPushInitialize() ) {
  280.       // if just one character then only send that
  281.       if ( 1 == DataDimension(pAsciiString) ) { lChar = pAsciiString; }
  282.       else { lChar[1] = '\0'; lChar[0] = pAsciiString; }
  283.       for ( ; lChar[0]; lChar++ ) {
  284.          PostMessage(gKPFocusWindow,WM_CHAR,lChar[0],1,0);
  285.          // DelayBetweenKeys is optional. If not supplied then no delay
  286.          if ( 1 < va_arg() )
  287.             suspend(pDelayBetweenKeys);
  288.       }
  289.    }
  290.    KeyPushTerminate();
  291.    return gKPFocusWindow;
  292. }
  293.  
  294.  
  295. /***********************************************************
  296.  *** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES ***
  297.  ***********************************************************/
  298.  
  299. gFocusID = 0;
  300. gKeyPushInitializeDepth = 0;  // keep track how many times recursively called
  301. gKPFocusWindow;  // KeyPushInitialize sets to window
  302. gKPSaveActiveWindow = 0;
  303.  
  304. KeyPushInitialize()
  305. {
  306.    // keep track of how many times called.  get actual ID to send to on first
  307.    // level, on recursive calls revert to first return.  If need to activate
  308.    // window then do so.  Return FALSE for failure, else non-false is TRUE
  309.    if ( 0 == gKeyPushInitializeDepth++ ) {
  310.       gKPSaveActiveWindow = 0; // assume don't need to change focus
  311.       if ( !gFocusID ) {
  312.          // take whatever is the focus window
  313.          gKPFocusWindow = GetFocus();
  314.       } else if ( !IsWindow(gFocusID) ) {
  315.          gKPFocusWindow = 0;  // gFocusID is not valid
  316.       } else if ( GetParent(gFocusID) ) {
  317.          gKPFocusWindow = gFocusID; // this isn't parent, so is actual window to send to
  318.       } else {
  319.          // this is a top level window, and so it must be active and then
  320.          // take its focus window
  321.          if ( gFocusID != (lActive=GetActiveWindow()) ) {
  322.             // this isn't active, and so must make it active
  323.             gKPSaveActiveWindow = lActive;
  324.             SetActiveWindow(gFocusID);
  325.          }
  326.          gKPFocusWindow = GetFocus();
  327.       }
  328.  
  329.    }
  330.    return gKPFocusWindow;
  331. }
  332.  
  333. KeyPushTerminate()
  334. {
  335.    // undo what KeyPushInitialize did. restore active window if KeyPushInitialize()
  336.    // activated it.  Must call same number of times as KeyPushInitialize.
  337.    if ( 0 == --gKeyPushInitializeDepth ) {
  338.       if ( gKPSaveActiveWindow ) {
  339.          SetActiveWindow(gKPSaveActiveWindow);
  340.       }
  341.    }
  342. }
  343.  
  344.  
  345. CharacterStroke(pChar) // press this character.  This is only tricky in that
  346. {                      // must check SHIFT state for alphabetic characters
  347.    // Get virtual codes for this character
  348.    lVKeyState = DynamicLink("KEYBOARD","VKKEYSCAN",SWORD16,PASCAL,pChar)
  349.    if ( -1 != lVKeyState ) {
  350.       lVKey = lVKeyState & 0xFF;
  351.       switch( lVKeyState >> 8 ) {
  352.          case 0:  // no shift state
  353.          case 1:  // shift state
  354.             if ( (0 != (GetKeyState(VK_SHIFT) & 0x80)) ^
  355.                  (0 != (GetKeyState(VK_CAPITAL) & 0x01)) ^
  356.                  (0 != (lVKeyState & 0x100)) ) {
  357.                // need to toggle the shift key to change case of this character
  358.                if ( GetKeyState(VK_SHIFT) & 0x80 )
  359.                   VKeyUp(VK_SHIFT), KeyStroke(lVKey), VKeyDown(VK_SHIFT);
  360.                else
  361.                   KeyStroke(VK_SHIFT,lVKey);
  362.             } else
  363.                KeyStroke(lVKey);
  364.             break;
  365.          case 2:  // control character
  366.             KeyStroke(VK_CONTROL,lVKey);
  367.             break;
  368.          case 6:  // control + alt
  369.             KeyStroke(VK_CONTROL,VK_ALT,lVKey);
  370.             break;
  371.          case 7:  // SHIFT+CONTROL+ALT
  372.             KeyStroke(VK_SHIFT,VK_CONTROL,VK_ALT,lVKey);
  373.             break;
  374.          default: // unknown
  375.             break;
  376.       }
  377.    }
  378. }
  379.  
  380. GetKeyboardState()   // return 256 byte buffer for current keyboard state
  381. {
  382.    lKeyBuf[255] = '\0'; // initialize a 256-byte array
  383.    DynamicLink("USER","GETKEYBOARDSTATE",SWORD16,PASCAL,lKeyBuf);
  384.    return lKeyBuf;
  385. }
  386.  
  387. SetKeyboardState(pKeyBuf)  // set the 256 byte buffer for current keyboard state
  388. {
  389.    DynamicLink("USER","SETKEYBOARDSTATE",SWORD16,PASCAL,pKeyBuf);
  390. }
  391.  
  392. GetKeyState(pVKey)
  393. {
  394.    return( DynamicLink("USER","GETKEYSTATE",SWORD16,PASCAL,pVKey) );
  395. }
  396.  
  397. MapVirtualKey(pCode,pMapType)
  398. {
  399.    return( DynamicLink("KEYBOARD","MAPVIRTUALKEY",UWORD16,PASCAL,pCode,pMapType) );
  400. }
  401.  
  402. GetParent(pHwnd)
  403. {
  404.    return DynamicLink("USER","GETPARENT",UWORD16,PASCAL,pHwnd);
  405. }
  406.  
  407.