| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 | 
							- #include "stdafx.h"
 
- #include "sendkeys.h"
 
- /* 
 
- * ----------------------------------------------------------------------------- 
 
- * Copyright (c) 2004 lallous <[email protected]>
 
- * All rights reserved.
 
- * 
 
- * Redistribution and use in source and binary forms, with or without
 
- * modification, are permitted provided that the following conditions
 
- * are met:
 
- * 1. Redistributions of source code must retain the above copyright
 
- *    notice, this list of conditions and the following disclaimer.
 
- * 2. Redistributions in binary form must reproduce the above copyright
 
- *    notice, this list of conditions and the following disclaimer in the
 
- *    documentation and/or other materials provided with the distribution.
 
- * 
 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
- * SUCH DAMAGE.
 
- * ----------------------------------------------------------------------------- 
 
- The Original SendKeys copyright info
 
- ---------------------------------------
 
- SendKeys (sndkeys32.pas) routine for 32-bit Delphi.
 
- Written by Ken Henderson
 
- Copyright (c) 1995 Ken Henderson <[email protected]>
 
- History
 
- ----------
 
- 04/19/2004
 
-   * Initial version development
 
- 04/21/2004
 
-   * Added number of times specifier to special keys
 
-   * Added {BEEP X Y}
 
-   * Added {APPACTIVATE WindowTitle}
 
-   * Added CarryDelay() and now delay works properly with all keys
 
-   * Added SetDelay() method
 
-   * Fixed code in AppActivate that allowed to pass both NULL windowTitle/windowClass
 
- 05/21/2004
 
-   * Fixed a bug in StringToVKey() that caused the search for RIGHTPAREN to be matched as RIGHT
 
-   * Adjusted code so it compiles w/ VC6
 
- 05/24/2004
 
-   * Added unicode support
 
- Todo
 
- -------
 
- * perhaps add mousecontrol: mousemove+mouse clicks
 
- * allow sending of normal keys multiple times as: {a 10}
 
- */
 
- const WORD CSendKeys::VKKEYSCANSHIFTON = 0x01;
 
- const WORD CSendKeys::VKKEYSCANCTRLON  = 0x02;
 
- const WORD CSendKeys::VKKEYSCANALTON   = 0x04;
 
- const WORD CSendKeys::INVALIDKEY       = 0xFFFF;
 
- const BYTE CSendKeys::ExtendedVKeys[MaxExtendedVKeys] =
 
- {
 
-     VK_UP, 
 
-     VK_DOWN,
 
-     VK_LEFT,
 
-     VK_RIGHT,
 
-     VK_HOME,
 
-     VK_END,
 
-     VK_PRIOR, // PgUp
 
-     VK_NEXT,  //  PgDn
 
-     VK_INSERT,
 
-     VK_DELETE,
 
- 	VK_CONTROL,
 
- 	VK_SHIFT,
 
- };
 
- CSendKeys::CSendKeys()
 
- {
 
-   m_nDelayNow = m_nDelayAlways = m_keyDownDelay = 0;
 
- }
 
- // Delphi port regexps:
 
- // ---------------------
 
- // search: .+Name:'([^']+)'.+vkey:([^\)]+)\)
 
- // replace: {"\1", \2}
 
- //
 
- // **If you add to this list, you must be sure to keep it sorted alphabetically
 
- // by Name because a binary search routine is used to scan it.**
 
- //
 
- CSendKeys::key_desc_t CSendKeys::KeyNames[CSendKeys::MaxSendKeysRecs] = 
 
- {
 
-   {_T("ADD"), VK_ADD}, 
 
-   {_T("APPS"), VK_APPS},
 
-   {_T("AT"), '@', true},
 
-   {_T("BACKSPACE"), VK_BACK},
 
-   {_T("BKSP"), VK_BACK},
 
-   {_T("BREAK"), VK_CANCEL},
 
-   {_T("BS"), VK_BACK},
 
-   {_T("CAPSLOCK"), VK_CAPITAL},
 
-   {_T("CARET"), '^', true},
 
-   {_T("CLEAR"), VK_CLEAR},
 
-   {_T("DECIMAL"), VK_DECIMAL}, 
 
-   {_T("DEL"), VK_DELETE},
 
-   {_T("DELETE"), VK_DELETE},
 
-   {_T("DIVIDE"), VK_DIVIDE}, 
 
-   {_T("DOWN"), VK_DOWN},
 
-   {_T("END"), VK_END},
 
-   {_T("ENTER"), VK_RETURN},
 
-   {_T("ESC"), VK_ESCAPE},
 
-   {_T("ESCAPE"), VK_ESCAPE},
 
-   {_T("F1"), VK_F1},
 
-   {_T("F10"), VK_F10},
 
-   {_T("F11"), VK_F11},
 
-   {_T("F12"), VK_F12},
 
-   {_T("F13"), VK_F13},
 
-   {_T("F14"), VK_F14},
 
-   {_T("F15"), VK_F15},
 
-   {_T("F16"), VK_F16},
 
-   {_T("F2"), VK_F2},
 
-   {_T("F3"), VK_F3},
 
-   {_T("F4"), VK_F4},
 
-   {_T("F5"), VK_F5},
 
-   {_T("F6"), VK_F6},
 
-   {_T("F7"), VK_F7},
 
-   {_T("F8"), VK_F8},
 
-   {_T("F9"), VK_F9},
 
-   {_T("HELP"), VK_HELP},
 
-   {_T("HOME"), VK_HOME},
 
-   {_T("INS"), VK_INSERT},
 
-   {_T("LEFT"), VK_LEFT},
 
-   {_T("LEFTBRACE"), '{', true},
 
-   {_T("LEFTPAREN"), '(', true},
 
-   {_T("LWIN"), VK_LWIN},
 
-   {_T("MULTIPLY"), VK_MULTIPLY}, 
 
-   {_T("NUMLOCK"), VK_NUMLOCK},
 
-   {_T("NUMPAD0"), VK_NUMPAD0}, 
 
-   {_T("NUMPAD1"), VK_NUMPAD1}, 
 
-   {_T("NUMPAD2"), VK_NUMPAD2}, 
 
-   {_T("NUMPAD3"), VK_NUMPAD3}, 
 
-   {_T("NUMPAD4"), VK_NUMPAD4}, 
 
-   {_T("NUMPAD5"), VK_NUMPAD5}, 
 
-   {_T("NUMPAD6"), VK_NUMPAD6}, 
 
-   {_T("NUMPAD7"), VK_NUMPAD7}, 
 
-   {_T("NUMPAD8"), VK_NUMPAD8}, 
 
-   {_T("NUMPAD9"), VK_NUMPAD9}, 
 
-   {_T("PERCENT"), '%', true},
 
-   {_T("PGDN"), VK_NEXT},
 
-   {_T("PGUP"), VK_PRIOR},
 
-   {_T("PLUS"), '+', true},
 
-   {_T("PRTSC"), VK_PRINT},
 
-   {_T("RIGHT"), VK_RIGHT},
 
-   {_T("RIGHTBRACE"), '}', true},
 
-   {_T("RIGHTPAREN"), ')', true},
 
-   {_T("RWIN"), VK_RWIN},
 
-   {_T("SCROLL"), VK_SCROLL},
 
-   {_T("SEPARATOR"), VK_SEPARATOR}, 
 
-   {_T("SNAPSHOT"), VK_SNAPSHOT},
 
-   {_T("SUBTRACT"), VK_SUBTRACT}, 
 
-   {_T("TAB"), VK_TAB},
 
-   {_T("TILDE"), '~', true}, 
 
-   {_T("UP"), VK_UP},
 
-   {_T("WIN"), VK_LWIN}
 
- };
 
- // calls keybd_event() and waits, if needed, till the sent input is processed
 
- void CSendKeys::KeyboardEvent(BYTE VKey, BYTE ScanCode, LONG Flags)
 
- {
 
- 	keybd_event(VKey, ScanCode, Flags, 0);
 
- 	if (m_bWait)
 
- 	{
 
- 		MSG KeyboardMsg;
 
- 		while (::PeekMessage(&KeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
 
- 		{
 
- 			::TranslateMessage(&KeyboardMsg);
 
- 			::DispatchMessage(&KeyboardMsg);
 
- 		}
 
- 	}
 
- }
 
- // Checks whether the specified VKey is an extended key or not
 
- bool CSendKeys::IsVkExtended(BYTE VKey)
 
- {
 
-   for (int i=0;i<MaxExtendedVKeys;i++)
 
-   {
 
-     if (ExtendedVKeys[i] == VKey)
 
-       return true;
 
-   }
 
-   return false;
 
- }
 
- CString CSendKeys::VkString(BYTE VKey)
 
- {
 
- 	for (int i = 0; i < MaxSendKeysRecs; i++)
 
- 	{
 
- 		if (KeyNames[i].VKey == VKey)
 
- 			return KeyNames[i].keyName;
 
- 	}
 
- 	return _T("");
 
- }
 
- void CSendKeys::AllKeysUp()
 
- {
 
- 	for (int key = 0; key < 256; key++)
 
- 	{
 
- 		//If the key is pressed, send a key up, having other keys down interferes with sending ctrl-v, -c and -x
 
- 		short val = GetKeyState(key);
 
- 		if (val & 0x8000)
 
- 		{
 
- 			SendKeyUp(key);
 
- 			//CString cs;
 
- 			//cs.Format(_T("key was down, sending key up %d, value: %d\n"), key, val);
 
- 			//OutputDebugString(cs);
 
- 		}
 
- 	}
 
- 	//Force these to be up, i was having trouble with the right shift key, i think things were
 
- 	//getting confused between the basic shift and lshift, but not sure.
 
- 	SendKeyUp(VK_LSHIFT);
 
- 	SendKeyUp(VK_RSHIFT);
 
- 	SendKeyUp(VK_LCONTROL);
 
- 	SendKeyUp(VK_RCONTROL);
 
- 	SendKeyUp(VK_LMENU);
 
- 	SendKeyUp(VK_RMENU);
 
- }
 
- // Generates KEYUP
 
- void CSendKeys::SendKeyUp(BYTE VKey)
 
- {
 
-   BYTE ScanCode = LOBYTE(::MapVirtualKey(VKey, 0));
 
-   KeyboardEvent(VKey, 
 
-                 ScanCode, 
 
-                 KEYEVENTF_KEYUP | (IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0));
 
- }
 
- void CSendKeys::SendKeyDown(BYTE VKey, WORD NumTimes, bool GenUpMsg, bool bDelay)
 
-  {
 
-   WORD Cnt = 0;
 
-   BYTE ScanCode = 0;
 
-   bool NumState = false;
 
-   if (VKey == VK_NUMLOCK)
 
-   {
 
-     DWORD dwVersion = ::GetVersion();
 
-     for (Cnt=1; Cnt<=NumTimes; Cnt++)
 
-     {
 
-       if (bDelay)
 
-         CarryDelay();
 
-       // snippet based on:
 
-       // http://www.codeproject.com/cpp/togglekeys.asp
 
-       if (dwVersion < 0x80000000)
 
-       {
 
-         ::keybd_event(VKey, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
 
-         ::keybd_event(VKey, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
 
-       }
 
-       else
 
-       {
 
-         // Win98 and later
 
-         if ( ((DWORD)(HIBYTE(LOWORD(dwVersion))) >= 10) )
 
-         {
 
-           // Define _WIN32_WINNT > 0x0400
 
-           // to compile
 
-           INPUT input[2] = {0};
 
-           input[0].type = input[1].type = INPUT_KEYBOARD;
 
-           input[0].ki.wVk = input[1].ki.wVk = VKey;
 
-           input[1].ki.dwFlags = KEYEVENTF_KEYUP;
 
-           ::SendInput(sizeof(input) / sizeof(INPUT), input, sizeof(INPUT));
 
-         }
 
-         // Win95
 
-         else
 
-         {
 
-           KEYBOARDSTATE_t KeyboardState;
 
-           NumState = GetKeyState(VK_NUMLOCK) & 1 ? true : false;
 
-           GetKeyboardState(&KeyboardState[0]);
 
-           if (NumState)
 
-             KeyboardState[VK_NUMLOCK] &= ~1;
 
-           else
 
-             KeyboardState[VK_NUMLOCK] |= 1;
 
-           SetKeyboardState(&KeyboardState[0]);
 
-         }
 
-       }
 
-     }
 
-     return;
 
-   }
 
-   // Get scancode
 
-   ScanCode = LOBYTE(::MapVirtualKey(VKey, 0));
 
-   // Send keys
 
-   for (Cnt=1; Cnt<=NumTimes; Cnt++)
 
-   {
 
-     // Carry needed delay ?
 
-     if (bDelay)
 
-       CarryDelay();
 
-     KeyboardEvent(VKey, ScanCode, IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0);
 
- 	if(m_keyDownDelay > 0)
 
- 	{
 
- 		Sleep(m_keyDownDelay);
 
- 	}
 
- 	if (GenUpMsg)
 
- 	{
 
- 		SendKeyUp(VKey);
 
- 	}
 
-   }
 
- }
 
- // Checks whether a bit is set
 
- bool CSendKeys::BitSet(BYTE BitTable, UINT BitMask)
 
- {
 
-   return BitTable & BitMask ? true : false;
 
- }
 
- // Sends a single key
 
- void CSendKeys::SendKey(WORD MKey, WORD NumTimes, bool GenDownMsg)
 
- {
 
-   // Send appropriate shift keys associated with the given VKey
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANSHIFTON))
 
-     SendKeyDown(VK_SHIFT, 1, false);
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANCTRLON))
 
-     SendKeyDown(VK_CONTROL, 1, false);
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANALTON))
 
-     SendKeyDown(VK_MENU, 1, false);
 
-   // Send the actual VKey
 
-   SendKeyDown(LOBYTE(MKey), NumTimes, GenDownMsg, true);
 
-   // toggle up shift keys
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANSHIFTON))
 
-     SendKeyUp(VK_SHIFT);
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANCTRLON))
 
-     SendKeyUp(VK_CONTROL);
 
-   if (BitSet(HIBYTE(MKey), VKKEYSCANALTON))
 
-     SendKeyUp(VK_MENU);
 
- }
 
- // Implements a simple binary search to locate special key name strings
 
- WORD CSendKeys::StringToVKey(LPCTSTR KeyString, int &idx)
 
- {
 
-   bool Found = false, Collided;
 
-   int  Bottom = 0, 
 
-        Top = MaxSendKeysRecs,
 
-        Middle = (Bottom + Top) / 2;
 
-   WORD retval = INVALIDKEY;
 
-   idx    = -1;
 
-   do
 
-   {
 
-     Collided = (Bottom == Middle) || (Top == Middle);
 
-     int cmp = _tcsnicmp(KeyNames[Middle].keyName, KeyString, _tcslen(KeyString));
 
-     if (cmp == 0)
 
-     {
 
-       Found = true;
 
-       retval = KeyNames[Middle].VKey;
 
-       idx    = Middle;
 
-       break;
 
-     }
 
-     else
 
-     {
 
-       if (cmp < 0)
 
-         Bottom = Middle;
 
-       else
 
-         Top = Middle;
 
-       Middle = (Bottom + Top) / 2;
 
-     }
 
-   } while (!(Found || Collided));
 
-   return retval;
 
- }
 
- // Releases all shift keys (keys that can be depressed while other keys are being pressed
 
- // If we are in a modifier group this function does nothing
 
- void CSendKeys::PopUpShiftKeys()
 
- {
 
-   if (!m_bUsingParens)
 
-   {
 
-     if (m_bShiftDown)
 
- 	{
 
-       SendKeyUp(VK_SHIFT);
 
- 	}
 
- 	if (m_bLShiftDown)
 
- 	{
 
- 		SendKeyUp(VK_LSHIFT);
 
- 	}
 
- 	if (m_bRShiftDown)
 
- 	{
 
- 		SendKeyUp(VK_RSHIFT);
 
- 	}
 
-     if (m_bControlDown)
 
- 	{
 
-       SendKeyUp(VK_CONTROL);
 
- 	}
 
- 	if (m_bLControlDown)
 
- 	{
 
- 		SendKeyUp(VK_LCONTROL);
 
- 	}
 
- 	if (m_bRControlDown)
 
- 	{
 
- 		SendKeyUp(VK_RCONTROL);
 
- 	}
 
-     if (m_bAltDown)
 
- 	{
 
-       SendKeyUp(VK_MENU);
 
- 	}
 
-     if (m_bWinDown)
 
- 	{
 
-       SendKeyUp(VK_LWIN);
 
- 	}
 
-     m_bWinDown = m_bShiftDown = m_bLShiftDown = m_bRShiftDown = m_bControlDown = m_bLControlDown = m_bRControlDown = m_bAltDown = false;
 
-   }
 
- }
 
- // Sends a key string
 
- bool CSendKeys::SendKeys(LPCTSTR KeysString, bool Wait)
 
- {
 
-   WORD MKey;
 
-   WORD NumTimes = 1;
 
-   TCHAR KeyString[300] = {0};
 
-   bool retval  = false;
 
-   int  keyIdx;
 
-   LPTSTR pKey = (LPTSTR) KeysString;
 
-   TCHAR  ch;
 
-   m_bWait = Wait;
 
-   m_bWinDown = m_bShiftDown = m_bLShiftDown = m_bRShiftDown = m_bControlDown = m_bLControlDown = m_bRControlDown = m_bAltDown = m_bUsingParens = false;
 
-   while (ch = *pKey)
 
-   {
 
-     switch (ch)
 
-     {
 
-     // begin modifier group
 
-     case _TXCHAR('('):
 
-       m_bUsingParens = true;
 
-       break;
 
-     // end modifier group
 
-     case _TXCHAR(')'):
 
-       m_bUsingParens = false;
 
-       PopUpShiftKeys(); // pop all shift keys when we finish a modifier group close
 
-       break;
 
-     // ALT key
 
-     case _TXCHAR('%'):
 
-       m_bAltDown = true;
 
-       SendKeyDown(VK_MENU, 1, false);
 
-       break;
 
-     // SHIFT key
 
-     case _TXCHAR('+'):
 
-       m_bShiftDown = true;
 
-       SendKeyDown(VK_SHIFT, 1, false);
 
-       break;
 
-     // CTRL key
 
-     case _TXCHAR('^'):
 
-       m_bControlDown = true;
 
-       SendKeyDown(VK_CONTROL, 1, false);
 
-       break;
 
-     // WINKEY (Left-WinKey)
 
-     case '@':
 
-       m_bWinDown = true;
 
-       SendKeyDown(VK_LWIN, 1, false);
 
-       break;
 
-     // enter
 
-     case _TXCHAR('~'):
 
-       SendKeyDown(VK_RETURN, 1, true);
 
-       PopUpShiftKeys();
 
-       break;
 
-     // begin special keys
 
-     case _TXCHAR('{'):
 
-       {
 
-         LPTSTR p = pKey+1; // skip past the beginning '{'
 
-         size_t t;
 
-         // find end of close
 
-         while (*p && *p != _TXCHAR('}'))
 
-           p++;
 
-         t = p - pKey;
 
-         // special key definition too big?
 
-         if (t > sizeof(KeyString))
 
-           return false;
 
-         // Take this KeyString into local buffer
 
-         _tcsncpy(KeyString, pKey+1, t);
 
-         KeyString[t-1] = _TXCHAR('\0');
 
-         keyIdx = -1;
 
-         pKey += t; // skip to next keystring
 
-         // Invalidate key
 
-         MKey = INVALIDKEY;
 
-         // sending arbitrary vkeys?
 
-         if (_tcsnicmp(KeyString, _T("VKEY"), 4) == 0)
 
-         {
 
-           p = KeyString + 4;
 
-           MKey = _ttoi(p);
 
-         }
 
-         else if (_tcsnicmp(KeyString, _T("BEEP"), 4) == 0)
 
-         {
 
-           p = KeyString + 4 + 1;
 
-           LPTSTR p1 = p;
 
-           DWORD frequency, delay;
 
-           if ((p1 = _tcsstr(p, _T(" "))) != NULL)
 
-           {
 
-             *p1++ = _TXCHAR('\0');
 
-             frequency = _ttoi(p);
 
-             delay = _ttoi(p1);
 
-             ::Beep(frequency, delay);
 
-           }
 
-         }
 
-         // Should activate a window?
 
-         else if (_tcsnicmp(KeyString, _T("APPACTIVATE"), 11) == 0)
 
-         {
 
-           p = KeyString + 11 + 1;
 
-           AppActivate(p);
 
-         }
 
-         // want to send/set delay?
 
-         else if (_tcsnicmp(KeyString, _T("DELAY"), 5) == 0)
 
-         {
 
-           // Advance to parameters
 
-           p = KeyString + 5;
 
-           // set "sleep factor"
 
-           if (*p == _TXCHAR('='))
 
-             m_nDelayAlways = _ttoi(p + 1); // Take number after the '=' character
 
-           else
 
-             // set "sleep now"
 
-             m_nDelayNow = _ttoi(p);
 
-         }
 
-         // not command special keys, then process as keystring to VKey
 
-         else
 
-         {
 
-           MKey = StringToVKey(KeyString, keyIdx);
 
-           // Key found in table
 
-           if (keyIdx != -1)
 
-           {
 
-             NumTimes = 1;
 
-             // Does the key string have also count specifier?
 
-             t = _tcslen(KeyNames[keyIdx].keyName);
 
-             if (_tcslen(KeyString) > t)
 
-             {
 
-               p = KeyString + t;
 
-               // Take the specified number of times
 
-               NumTimes = _ttoi(p);
 
-             }
 
-             if (KeyNames[keyIdx].normalkey)
 
-               MKey = ::VkKeyScan(KeyNames[keyIdx].VKey);
 
-           }
 
-         }
 
-         // A valid key to send?
 
- 		if (MKey != INVALIDKEY)
 
- 		{
 
- 			if (MKey == VK_LCONTROL ||
 
- 				MKey == VK_RCONTROL)
 
- 			{
 
- 				m_bLControlDown = (MKey == VK_LCONTROL);
 
- 				m_bRControlDown = (MKey == VK_RCONTROL);
 
- 				SendKeyDown(MKey, 1, false);
 
- 			}
 
- 			else if (MKey == VK_LSHIFT ||
 
- 					 MKey == VK_RSHIFT)
 
- 			{
 
- 				m_bLShiftDown = (MKey == VK_LSHIFT);
 
- 				m_bRShiftDown = (MKey == VK_RSHIFT);
 
- 				SendKeyDown(MKey, 1, false);
 
- 			}
 
- 			else
 
- 			{		
 
- 				SendKey(MKey, NumTimes, true);	
 
- 				PopUpShiftKeys();
 
- 			}
 
-         }
 
-       }
 
-       break;
 
-       // a normal key was pressed
 
-     default:
 
-       // Get the VKey from the key
 
-       MKey = ::VkKeyScan(ch);
 
-       SendKey(MKey, 1, true);
 
-       PopUpShiftKeys();
 
-     }
 
-     pKey++;
 
-   }
 
-   m_bUsingParens = false;
 
-   PopUpShiftKeys();
 
-   return true;
 
- }
 
- bool CSendKeys::AppActivate(HWND wnd)
 
- {
 
-   if (wnd == NULL)
 
-     return false;
 
-   ::SendMessage(wnd, WM_SYSCOMMAND, SC_HOTKEY, (LPARAM) wnd);
 
-   ::SendMessage(wnd, WM_SYSCOMMAND, SC_RESTORE, (LPARAM) wnd);
 
-   
 
-   ::ShowWindow(wnd, SW_SHOW);
 
-   ::SetForegroundWindow(wnd);
 
-   ::SetFocus(wnd);
 
-   return true;
 
- }
 
- BOOL CALLBACK CSendKeys::enumwindowsProc(HWND hwnd, LPARAM lParam)
 
- {
 
-   enumwindow_t *t = (enumwindow_t *) lParam;
 
-   LPTSTR wtitle = 0, wclass = 0, str = t->str;
 
-   if (!*str)
 
-     str++;
 
-   else
 
-   {
 
-     wtitle = str;
 
-     str += _tcslen(str) + 1;
 
-   }
 
-   if (*str)
 
-     wclass = str;
 
-   bool bMatch(false);
 
-   if (wclass)
 
-   {
 
-     TCHAR szClass[300];
 
-     if (::GetClassName(hwnd, szClass, sizeof(szClass)))
 
-       bMatch |= (_tcsstr(szClass, wclass) != 0);
 
-   }
 
-   if (wtitle)
 
-   {
 
-     TCHAR szTitle[300];
 
-     if (::GetWindowText(hwnd, szTitle, sizeof(szTitle)))
 
-       bMatch |= (_tcsstr(szTitle, wtitle) != 0);
 
-   }
 
-   if (bMatch)
 
-   {
 
-     t->hwnd = hwnd;
 
-     return false;
 
-   }
 
-   return true;
 
- }
 
- // Searchs and activates a window given its title or class name
 
- bool CSendKeys::AppActivate(LPCTSTR WindowTitle, LPCTSTR WindowClass)
 
- {
 
-   HWND w;
 
-   w = ::FindWindow(WindowClass, WindowTitle);
 
-   if (w == NULL)
 
-   {
 
-     // Must specify at least a criteria
 
-     if (WindowTitle == NULL && WindowClass == NULL)
 
-       return false;
 
-     // << Code to serialize the windowtitle/windowclass in order to send to EnumWindowProc()
 
-     size_t l1(0), l2(0);
 
-     if (WindowTitle)
 
-       l1 = _tcslen(WindowTitle);
 
-     if (WindowClass)
 
-       l2 = _tcslen(WindowClass);
 
-     LPTSTR titleclass = new TCHAR [l1 + l2 + 5];
 
-     memset(titleclass, '\0', l1+l2+5);
 
-     if (WindowTitle)
 
-       _tcscpy(titleclass, WindowTitle);
 
-     titleclass[l1] = 0;
 
-     if (WindowClass)
 
-       _tcscpy(titleclass+l1+1, WindowClass);
 
-     // >>
 
-     enumwindow_t t;
 
-     t.hwnd = NULL;
 
-     t.str  = titleclass;
 
-     ::EnumWindows(enumwindowsProc, (LPARAM) & t);
 
-     w = t.hwnd;
 
-     delete [] titleclass;
 
-   }
 
-   if (w == NULL)
 
-     return false;
 
-   return AppActivate(w);
 
- }
 
- // Carries the required delay and clears the m_nDelaynow value
 
- void CSendKeys::CarryDelay()
 
- {
 
-   // Should we delay once?
 
-   if (!m_nDelayNow)
 
-     // should we delay always?
 
-     m_nDelayNow = m_nDelayAlways;
 
-   // No delay specified?
 
-   if (m_nDelayNow)
 
-     ::Sleep(m_nDelayNow); //::Beep(100, m_nDelayNow);
 
-   // clear SleepNow
 
-   m_nDelayNow = 0;
 
- }
 
- /*
 
- Test Binary search
 
- void CSendKeys::test()
 
- {
 
-   WORD miss(0);
 
-   for (int i=0;i<MaxSendKeysRecs;i++)
 
-   {
 
-     char *p = (char *)KeyNames[i].keyName;
 
-     WORD v = StringToVKeyB(p);
 
-     if (v == INVALIDKEY)
 
-     {
 
-       miss++;
 
-     }
 
-   }
 
- }
 
- */
 
- /*
 
- Search in a linear manner
 
- WORD CSendKeys::StringToVKey(const char *KeyString, int &idx)
 
- {
 
- for (int i=0;i<MaxSendKeysRecs;i++)
 
- {
 
- size_t len = strlen(KeyNames[i].keyName);
 
- if (strnicmp(KeyNames[i].keyName, KeyString, len) == 0)
 
- {
 
- idx = i;
 
- return KeyNames[i].VKey;
 
- }
 
- }
 
- idx = -1;
 
- return INVALIDKEY;
 
- }
 
- */
 
 
  |