📄 sendkeys.cpp
字号:
// 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_bControlDown)
SendKeyUp(VK_CONTROL);
if (m_bAltDown)
SendKeyUp(VK_MENU);
if (m_bWinDown)
SendKeyUp(VK_LWIN);
m_bWinDown = m_bShiftDown = m_bControlDown = m_bAltDown = false;
}
}
// Sends a key string
bool CSendKeys::SendKeys(LPCTSTR KeysString, bool Wait)
{
WORD MKey, NumTimes;
TCHAR KeyString[300] = {0};
bool retval = false;
int keyIdx;
LPTSTR pKey = (LPTSTR) KeysString;
TCHAR ch;
m_bWait = Wait;
m_bWinDown = m_bShiftDown = m_bControlDown = 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)
{
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;
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -