MapVirtualKey

MapVirtualKey

  函数功能:该函数将一虚拟键码翻译(映射)成一扫描码或一字符值,或者将一扫描码翻译成一虚拟键码。   函数原型:UINT MapVirtualKey(UINT uCode,UINT uMapType);   参数:   uCode:定义一个键的扫描码或虚拟键码。该值如何解释依赖于uMapType参数的值。   uMapType:定义将要执行的翻译。该参数的值依赖于uCode参数的值。取值如下:   0:代表uCodee是一虚拟键码且被翻译为一扫描码。若一虚拟键码不区分左右,则返回左键的扫描码。若未进行翻译,则函数返回O。   1:代表uCode是一扫描码且被翻译为一虚拟键码,且此虚拟键码不区分左右。若未进行翻译,则函数返回0。   2:代表uCode为一虚拟键码且被翻译为一未被移位的字符值存放于返回值的低序字中。死键(发音符号)则通过设置返回值的最高位来表示。若未进行翻译,则函数返回0。   3:代表uCode为一扫描码且被翻译为区分左右键的一虚拟键码。若未进行翻译,则函数返回0。   返回值:返回值可以是一扫描码,或一虚拟键码,或一字符值,这完全依赖于不同的uCode和uMapType的值。若未进行翻译,则函数返回O。   备注:应用程序可以使用MapVirtualKey将扫描码翻译为虚拟键码常数VK_SHIFT,VK_CONTROL和VK_MENU。反之亦然。这些翻译不区分左右shift,ctrl,alt键。应用程序可以通过调用MapVirtualKey函数时将uCode参数   设置为如下的虚拟键码常数来获得分别相应于上述键的左右键的扫描码:   VK_LSHIFT,VK_RSHIFT;VK_LCONTROL;VK_RCONTROL;VK_LMENU,VK_RMENU   仅当应用程序调用GetKeyboardState,SetKeyboardStaste,GetAsyncKeystate, GetKeyState和MapVirtUalKey函数时,才可用这些区分左右键的常数。
#include <windows.h> #include <iostream> #include <fstream> #include <string> #include <conio.h> using namespace std; const string CONFIG_FILE = "key_config.txt"; const string DEFAULT_KEY = "F8"; // 虚拟键码映射表 const unordered_map<string, SHORT> vkMap = { {"A", 0x41}, {"B", 0x42}, {"C", 0x43}, {"D", 0x44}, {"E", 0x45}, {"F", 0x46}, {"G", 0x47}, {"H", 0x48}, {"I", 0x49}, {"J", 0x4A}, {"K", 0x4B}, {"L", 0x4C}, {"M", 0x4D}, {"N", 0x4E}, {"O", 0x4F}, {"P", 0x50}, {"Q", 0x51}, {"R", 0x52}, {"S", 0x53}, {"T", 0x54}, {"U", 0x55}, {"V", 0x56}, {"W", 0x57}, {"X", 0x58}, {"Y", 0x59}, {"Z", 0x5A}, {"0", 0x30}, {"1", 0x31}, {"2", 0x32}, {"3", 0x33}, {"4", 0x34}, {"5", 0x35}, {"6", 0x36}, {"7", 0x37}, {"8", 0x38}, {"9", 0x39}, {"F1", VK_F1}, {"F2", VK_F2}, {"F3", VK_F3}, {"F4", VK_F4}, {"F5", VK_F5}, {"F6", VK_F6}, {"F7", VK_F7}, {"F8", VK_F8}, {"F9", VK_F9}, {"F10", VK_F10}, {"F11", VK_F11}, {"F12", VK_F12}, {"SPACE", VK_SPACE}, {"ENTER", VK_RETURN}, {"ESC", VK_ESCAPE}, {"LEFT", VK_LEFT}, {"RIGHT", VK_RIGHT}, {"UP", VK_UP}, {"DOWN", VK_DOWN}, {"CTRL", VK_CONTROL}, {"ALT", VK_MENU}, {"SHIFT", VK_SHIFT}, {"TAB", VK_TAB}, {"CAPSLOCK", VK_CAPITAL}, {"BACKSPACE", VK_BACK} }; // 获取键名对应的虚拟键码 SHORT GetKeyCode(const string& keyName) { auto it = vkMap.find(keyName); if (it != vkMap.end()) { return it->second; } return 0; } // 获取虚拟键码对应的键名 string GetKeyName(SHORT vkCode) { for (const auto& pair : vkMap) { if (pair.second == vkCode) { return pair.first; } } return ""; } // 初始化配置文件 void InitConfigFile() { ofstream file(CONFIG_FILE); if (file.is_open()) { file << DEFAULT_KEY; file.close(); } } // 读取配置的键名 string ReadConfigKey() { ifstream file(CONFIG_FILE); string keyName; if (file.is_open()) { file >> keyName; file.close(); } return keyName.empty() ? DEFAULT_KEY : keyName; } // 保存键名到配置文件 void SaveConfigKey(const string& keyName) { ofstream file(CONFIG_FILE); if (file.is_open()) { file << keyName; file.close(); } } // 等待用户按键并返回键名 string WaitForUserKeyPress() { cout << "请按下要设置的键 (按ESC取消)...\n"; string lastKey; while (true) { if (_kbhit()) { int ch = _getch(); // 处理功能键 if (ch == 0 || ch == 0xE0) { int ext = _getch(); SHORT vkCode = MapVirtualKey(ext, MAPVK_VSC_TO_VK); lastKey = GetKeyName(vkCode); if (!lastKey.empty()) { cout << "检测到按键: " << lastKey << endl; } } // 处理普通键 else { SHORT vkCode = MapVirtualKey(ch, MAPVK_VSC_TO_VK); lastKey = GetKeyName(vkCode); if (!lastKey.empty()) { cout << "检测到按键: " << lastKey << endl; } // ESC键取消 if (vkCode == VK_ESCAPE) { return ""; } } // 等待按键释放 while (_kbhit()) { _getch(); } // 返回最后一个有效按键 if (!lastKey.empty()) { return lastKey; } } Sleep(10); } } // 模拟按键按下 void SimulateKeyPress(SHORT vkCode) { INPUT input[2] = { {0}, {0} }; // 按下键 input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = vkCode; // 释放键 input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = vkCode; input[1].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(2, input, sizeof(INPUT)); } // 串口监听函数 void MonitorSerialPort(SHORT vkCode) { HANDLE hSerial = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { cout << "无法打开串口COM3\n"; return; } // 配置串口 DCB dcb = { 0 }; dcb.DCBlength = sizeof(DCB); if (!GetCommState(hSerial, &dcb)) { cout << "获取串口状态失败\n"; CloseHandle(hSerial); return; } dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.StopBits = ONESTOPBIT; dcb.Parity = NOPARITY; if (!SetCommState(hSerial, &dcb)) { cout << "设置串口状态失败\n"; CloseHandle(hSerial); return; } cout << "开始监听串口 (按ESC退出)...\n"; cout << "当串口开关按下时将模拟按下: " << GetKeyName(vkCode) << endl; char buffer; DWORD bytesRead; bool running = true; while (running) { if (ReadFile(hSerial, &buffer, 1, &bytesRead, NULL) && bytesRead > 0) { if (buffer == '1') { // 假设串口发送'1'表示开关按下 SimulateKeyPress(vkCode); } } // 检查是否按下ESC键 if (_kbhit() && _getch() == 27) { running = false; } Sleep(10); } CloseHandle(hSerial); } // 主菜单 void ShowMainMenu(const string& currentKey) { system("cls"); cout << "===== 串口按键模拟器 =====\n"; cout << "当前配置按键: " << currentKey << "\n\n"; cout << "1. 更改按键配置\n"; cout << "2. 开始监听串口\n"; cout << "3. 退出程序\n"; cout << "请选择: "; } int main() { // 初始化配置文件 ifstream testFile(CONFIG_FILE); if (!testFile.good()) { InitConfigFile(); } testFile.close(); string currentKey = ReadConfigKey(); bool running = true; while (running) { ShowMainMenu(currentKey); int choice; cin >> choice; switch (choice) { case 1: { // 更改按键配置 string newKey = WaitForUserKeyPress(); if (!newKey.empty()) { cout << "要将按键配置更改为 " << newKey << " 吗? (Y/N): "; char confirm; cin >> confirm; if (toupper(confirm) == 'Y') { SaveConfigKey(newKey); currentKey = newKey; cout << "按键配置已更新\n"; } } else { cout << "取消更改\n"; } break; } case 2: // 开始监听串口 MonitorSerialPort(GetKeyCode(currentKey)); break; case 3: // 退出程序 running = false; break; default: cout << "无效选择\n"; break; } cout << "按任意键继续..."; _getch(); } return 0; }
最新发布
07-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值