DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

 简易按键精灵制作

参考链接:https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendinput?redirectedfrom=MSDNhttps://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;
 
}
 
};
 
 

 

 
posted on   DoubleLi  阅读(585)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2017-11-24 windows服务和进程的区别和联系
2017-11-24 Daemon Process
2017-11-24 C++11中的原子操作(atomic operation)
2013-11-24 MFC消息顺序
点击右上角即可分享
微信分享提示