如何通过Win32实现类似WinCompose向应用发送Unicode字符串的功能?
在Win32中用SendInput模拟Unicode字符输入(含表情符号)
核心原理
Win32的SendInput函数支持直接发送Unicode字符级的键盘输入,无需模拟复杂的按键组合。当KEYBDINPUT的dwFlags设置为KEYEVENTF_UNICODE时,wScan字段直接传入Unicode字符的编码值,系统会将该字符直接注入当前焦点窗口的输入队列,完美支持包括表情符号在内的所有Unicode字符,和WinCompose的核心实现逻辑一致。
实现步骤
1. 构建输入事件数组
每个Unicode字符需要两个INPUT结构:
- 一个标记为按下的事件(仅设置
KEYEVENTF_UNICODE) - 一个标记为释放的事件(同时设置
KEYEVENTF_UNICODE和KEYEVENTF_KEYUP)
2. 填充INPUT结构细节
针对每个字符:
INPUT.type=INPUT_KEYBOARDKEYBDINPUT.wScan= 目标Unicode字符(比如U+1F600对应😀)KEYBDINPUT.dwFlags=KEYEVENTF_UNICODE(按下事件)或KEYEVENTF_UNICODE | KEYEVENTF_KEYUP(释放事件)- 其余字段(
wVk,time,dwExtraInfo)设为0即可
3. 调用SendInput发送事件
通过SendInput一次性发送所有构建好的输入事件数组,保证输入的连续性。
代码示例(C++)
#include <Windows.h> #include <vector> void SendUnicodeString(const wchar_t* unicodeStr) { std::vector<INPUT> inputEvents; size_t strLen = wcslen(unicodeStr); // 为每个字符生成按下和释放事件 for (size_t i = 0; i < strLen; ++i) { wchar_t ch = unicodeStr[i]; // 按下事件 INPUT pressInput = {0}; pressInput.type = INPUT_KEYBOARD; pressInput.ki.wScan = ch; pressInput.ki.dwFlags = KEYEVENTF_UNICODE; inputEvents.push_back(pressInput); // 释放事件 INPUT releaseInput = {0}; releaseInput.type = INPUT_KEYBOARD; releaseInput.ki.wScan = ch; releaseInput.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; inputEvents.push_back(releaseInput); } // 发送所有输入事件 SendInput(static_cast<UINT>(inputEvents.size()), inputEvents.data(), sizeof(INPUT)); } // 使用示例 int main() { // 确保目标窗口获得焦点(可替换为指定窗口句柄) SetForegroundWindow(GetForegroundWindow()); // 发送包含表情的Unicode字符串 SendUnicodeString(L"Hello 😀 你好 🎉"); return 0; }
注意事项
- 窗口焦点:发送输入前需确保目标窗口处于前台(可通过
SetForegroundWindow指定),否则输入会发送到当前焦点窗口。 - 编码问题:必须使用宽字符(
wchar_t)存储Unicode字符串,避免多字节编码转换错误。 - 权限限制:部分高权限窗口(如UAC弹窗)无法接收模拟输入,需程序以管理员权限运行。
- 事件顺序:严格遵循“按下→释放”的顺序,否则可能导致输入异常。
内容的提问来源于stack exchange,提问作者John Allsup
相关产品推荐
相关产品推荐

