简易按键精灵制作
参考链接:https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendinput?redirectedfrom=MSDN、https://www.fluentcpp.com/2018/12/28/timer-cpp/、https://github.com/99x/timercpp
具体实现见代码,同时可以设置定时器进行定时操作按键。
按键代码实现(注意必须通过管理员身份运行生成的可执行文件才有效):
#include <iostream> #include <Windows.h> #include <tchar.h> #include "timer.h" // The reference between key and code connection can be found below: // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes /***************************************************************/ /* 全局定义 */ /***************************************************************/ constexpr size_t ARRAY_MAX_SIZE = 4; /***************************************************************** 功能描述: 发送按键消息 其他说明: *******************************************************************/ void GenerateKeyMsg(HWND hwnd, DWORD keyVal) { std::cout << "Post message start. -->"; LPARAM lparam = (MapVirtualKey(keyVal, 0) << 16) + 1; PostMessage(hwnd, WM_KEYDOWN, keyVal, lparam); std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(50))); PostMessage(hwnd, WM_KEYUP, keyVal, lparam); std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(10))); std::cout << " Post message finish." << std::endl; } int main() { std::cout << "Input time interval:" << std::endl; int delay; std::cin >> delay; // 获取MapleStory句柄 auto ms = FindWindow(NULL, _T("MapleStory")); if (ms == NULL) { std::cout << "No game is found." << std::endl; return 0; } // 界面最前显示 if (!SetForegroundWindow(ms)) return 0; Timer timer; timer.setInterval(std::bind(GenerateKeyMsg, ms, 0x43), delay); timer.loop(); return 0; }
定时器实现:
#include <iostream> #include <thread> #include <chrono> #include <functional> class Timer { bool clear = false; public: void setTimeout(std::function<void(void)> func, float delay); void setInterval(std::function<void(void)> func, float delay); void stop(); void loop(); }; void Timer::setTimeout(std::function<void(void)> func, float delay) { this->clear = false; std::thread t([=]() { if (this->clear) return; std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(delay * 1000))); if (this->clear) return; func(); }); t.detach(); } void Timer::setInterval(std::function<void(void)> func, float delay) { this->clear = false; std::thread t([=]() { while (true) { if (this->clear) return; std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(delay * 1000))); if (this->clear) return; func(); } }); t.detach(); } void Timer::stop() { this->clear = true; } void Timer::loop() { while (!this->clear) { } }
完善后包含有按键处理的代码,可以使用notepad测试
#include <iostream> #include <Windows.h> #include <tchar.h> #include "timer.h" #include "input.h" // The reference between key and code connection can be found below: // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes /***************************************************************/ /* 全局定义 */ /***************************************************************/ /***************************************************************** 功能描述: 发送按键消息 其他说明: 发送给全部窗口 *******************************************************************/ void GenerateKeyMsgForActiveWindow(WORD virKey = 0x41, WORD flag = 0) { INPUT ip; // Set up a generic keyboard event. ip.type = INPUT_KEYBOARD; ip.ki.wScan = 0; // hardware scan code for key ip.ki.time = 0; ip.ki.dwExtraInfo = 0; // Press the "A" key ip.ki.wVk = virKey; // virtual-key code for the "a" key ip.ki.dwFlags = flag; // 0 for key press auto uSent = SendInput(1, &ip, sizeof(INPUT)); // Release the "A" key //ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release //SendInput(1, &ip, sizeof(INPUT)); if (uSent != 1) { std::cout << "[ERROR] Send Key Message failed: " << HRESULT_FROM_WIN32(GetLastError()) << std::endl; } } /***************************************************************** 功能描述: 发送按键消息 其他说明: 发送给单个窗口 *******************************************************************/ void GenerateKeyMsgForInactiveWindow(HWND hwnd, DWORD keyVal) { LPARAM lparam = (MapVirtualKey(keyVal, 0) << 16) + 1; PostMessage(hwnd, WM_KEYDOWN, keyVal, lparam); std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(50))); PostMessage(hwnd, WM_KEYUP, keyVal, lparam); std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<size_t>(10))); // PostMessage(hwnd, WM_CLOSE, NULL, NULL); // std::cout << GetLastError() << std::endl; } /***************************************************************** 功能描述: 主程序入口 其他说明: *******************************************************************/ int main() { Input input; Timer timer; bool loop = false; while (!input.exit()) { if(!loop) input.parser(); const auto keyMap = input.getKeyBoard(); auto hwnd = FindWindow(NULL, _T("new 1 - Notepad++ [Administrator]")); if (hwnd == NULL) { std::cout << "[WARN] No Application is Found." << std::endl; return 0; } // 界面最前显示 if (!SetForegroundWindow(hwnd)) return 0; for (auto& key : keyMap) { if (key.first == VK_ESCAPE) continue; std::cout << "[INFO] Key Value: " << key.first << " / Time Interval: " << key.second << std::endl; timer.setInterval(std::bind(GenerateKeyMsgForInactiveWindow, hwnd, key.first), key.second); } input.parser(); timer.stop(); loop = true; } return 0; }
#pragma once #include <iostream> #include <string> #include <map> #include <WinUser.h> class Input { public: Input() { std::cout << "Please enter the time interval of each key you want " << std::endl << "and set 'start' value as 1 to start application." << std::endl << std::endl; } void parser() { std::string line; while (std::getline(std::cin, line)) { if (line == "start") { break; } std::string key, time; for (size_t pos = 0; pos < line.length(); ++pos) { if (pos > 0 && key.empty() && line[pos - 1] != ' ' && line[pos] == ' ') { key = line.substr(0, pos); } if (pos + 1 < line.length() && time.empty() && line[pos] == ' ' && line[pos + 1] != ' ' && key != "quit") { time = line.substr(pos + 1, line.length() - 1 - pos); keyBoardRec[ConvertIntoKeyValue(key)] = atof(time.c_str()); } } } } const std::map<int, float>& getKeyBoard() const { return keyBoardRec; } bool exit() { return keyBoardRec.find(VK_ESCAPE) != keyBoardRec.end(); } private: std::map<int, float> keyBoardRec; int ConvertIntoKeyValue(const std::string& key) { if (key.length() == 1) { int off = key[0] - 'a'; if (off >= 0 && off <= 26) { return 0x41 + off; /* a */ } off = key[0] - '0'; if (off >= 0 && off <= 9) { return 0x30 + off; /* 0 */ } } if (key == "shift") { return VK_SHIFT; } if (key == "ctrl") { return VK_CONTROL; } if (key == "alt") { return VK_MENU; } if (key == "space") { return VK_SPACE; } if (key == "delete") { return VK_DELETE; } if (key == "end") { return VK_END; } if (key == "pagedown") { return VK_NEXT; } if (key == "pageup") { return VK_PRIOR; } if (key == "esc") { return VK_ESCAPE; } return 0x0; } };
标签:std,&&,ip,void,C++,简易,按键精灵,key,include From: https://www.cnblogs.com/lidabo/p/16922243.html