[方法记录]向Windows的特定窗口注入键盘事件

前言

在尝试开发一款可以远程控制电脑进行文字输入软件时候,需要找到合适方法在Windows端注入键盘事件。查询微软的相关文档之后,发现通过两个简单的函数就能实现基本的键盘事件注入功能。

事件注入

使用SendInput方法即可。参照官方给出的实例:

cpp 复制代码
//**********************************************************************
//
// Sends Win + D to toggle to the desktop
//
//**********************************************************************
void ShowDesktop()
{
    OutputString(L"Sending 'Win-D'\r\n");
    INPUT inputs[4] = {};
    ZeroMemory(inputs, sizeof(inputs));

    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = VK_LWIN;
   
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = 'D';

    inputs[2].type = INPUT_KEYBOARD;
    inputs[2].ki.wVk = 'D';
    inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;

    inputs[3].type = INPUT_KEYBOARD;
    inputs[3].ki.wVk = VK_LWIN;
    inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;

    UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
    if (uSent != ARRAYSIZE(inputs))
    {
        OutputString(L"SendInput failed: 0x%x\n", HRESULT_FROM_WIN32(GetLastError()));
    } 
}

写成如下函数进行测试:

cpp 复制代码
UINT sendInput(WORD virtualKeyCode) {
    cout<<"sendInput"<<virtualKeyCode<<endl;
    INPUT inputs[2] = {};
    ZeroMemory(inputs, sizeof(inputs));

    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = virtualKeyCode;

    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = virtualKeyCode;
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;

    UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
    if (uSent != ARRAYSIZE(inputs))
    {
        printf("SendInput failed: 0x%x\n", HRESULT_FROM_WIN32(GetLastError()));
    }

    return uSent;
}

int main()
{
    sendInput('W');
    sendInput('E');
    sendInput('B');
}

根据函数返回值,事件在这个时候已经注入成功了。

使用SetForegroundWindow 聚焦窗口

然而,事件被成功注入不代表被注入到我们想要的地方。sendInput方法只会将事件注入到已经聚焦的窗口,如果窗口没有聚焦的话是收不到注入的消息的。通过SetForegroundWindow方法,可以将特定的窗口聚焦。为了找到我们想聚焦的窗口,可以使用FindWindow方法。FindWindow需要两个参数,依次是类名、窗口名。 用法如下:

cpp 复制代码
HWND targetWindow = FindWindow("YodaoMainWndClass",NULL);
if (targetWindow != NULL)
{
    std::cout << "Window found!" << std::endl;
    SetForegroundWindow(targetWindow);
    
    
}

如何获取窗口的类名与方法名?

一般的窗口使用Visual Studio的工具Spy++即可。以网易有道词典为例:

如图可以看到,类名为YodaoMainWindClass,窗口名为网易有道词典。

相关推荐
william_djj16 分钟前
python3.8 提取xlsx表格内容填入单个文件
windows·python·xlsx
点云SLAM9 小时前
C++内存泄漏检测之Windows 专用工具(CRT Debug、Dr.Memory)和Linux 专业工具(ASan 、heaptrack)
linux·c++·windows·asan·dr.memory·c++内存泄漏检测·c++内存管理
LuiChun9 小时前
Docker Compose 容器服务查询与文件查看操作指南(Windows Docker Desktop 版)【一】
linux·运维·windows·docker·容器
无限进步_11 小时前
【C++】大数相加算法详解:从字符串加法到内存布局的思考
开发语言·c++·windows·git·算法·github·visual studio
love530love11 小时前
彻底解决 ComfyUI Mixlab 插件 Whisper.available False 的报错
人工智能·windows·python·whisper·win_comfyui
习惯就好zz11 小时前
[实战笔记] 从 Qt 5.12.9 跨越到 Qt 6.x 完美迁移指南 (Windows + VS)
windows·qt·msvc·qt5·qt6·迁移
石像鬼₧魂石12 小时前
Windows Server 2003 域控制器靶机搭建与渗透环境配置手册
linux·windows·学习
抠头专注python环境配置13 小时前
解决“No module named ‘tensorflow‘”报错:从导入失败到环境配置成功
人工智能·windows·python·tensorflow·neo4j
qh0526wy13 小时前
WINDOWS BAT 开机登录后自动启动
windows·python
十五年专注C++开发13 小时前
CMake基础: 在release模式下生成调试信息的方法
linux·c++·windows·cmake·跨平台构建