【问题标题】:How to send keystrokes to a window?如何将击键发送到窗口?
【发布时间】:2011-01-08 00:12:33
【问题描述】:

我正在使用 keybd_event();我想使用 SendMessage();将击键发送到记事本,可以这样做吗?

【问题讨论】:

    标签: c++ windows


    【解决方案1】:

    使用SendMessage 将文本插入编辑缓冲区(听起来像你想要的那样):

    HWND notepad = FindWindow(_T("Notepad"), NULL);
    HWND edit = FindWindowEx(notepad, NULL, _T("Edit"), NULL);
    SendMessage(edit, WM_SETTEXT, NULL, (LPARAM)_T("hello"));
    

    如果您需要键码和任意键击,您可以使用SendInput()(在 2k/xp 和首选版本中可用)或keybd_event()`(最终将在较新的操作系统中调用 SendInput)这里的一些示例:

    http://www.codeguru.com/forum/showthread.php?t=377393

    还有您可能感兴趣的 SendMessage 的 WM_SYSCOMMAND/WM_KEYDOWN/WM_KEYUP/WM_CHAR 事件。

    【讨论】:

    • 如何将其发送到窗口?
    • 它没有。您需要在hWnd 参数中传递一个窗口句柄。此外,窗口句柄是 first 参数,而不是第三个。
    • 您不能使用 SendMessage() 发送击键。您无法控制键盘状态。特别是 Shift、Control 和 Alt 键。
    • WM_SETTEXT 也不发送击键。在任何情况下,您都不能像 nobugz 提到的那样使用 SendMessage() 可靠地做到这一点。见blogs.msdn.com/oldnewthing/archive/2005/05/30/423202.aspx
    • 您无需发送击键即可输入文本。 OP 已经知道keybd_event。问题是关于使用SendMessage
    【解决方案2】:

    keybd_event() 已被 SendInput() 取代,因此最好使用它。这是一些示例代码来执行您所要求的操作。您可以使用 SendMessage() 直接编辑记事本窗口的编辑控件,也可以使用 SendInput() 合成要发送到窗口的击键。

    使用SendInput()

    int SendKeystrokesToNotepad( const TCHAR *const text )
    {
        INPUT *keystroke;
        UINT i, character_count, keystrokes_to_send, keystrokes_sent;
        HWND notepad;
    
        assert( text != NULL );
    
        //Get the handle of the Notepad window.
        notepad = FindWindow( _T( "Notepad" ), NULL );
        if( notepad == NULL )
            return 0;
    
        //Bring the Notepad window to the front.
        if( !SetForegroundWindow( notepad ) )
            return 0;
    
        //Fill in the array of keystrokes to send.
        character_count = _tcslen( text );
        keystrokes_to_send = character_count * 2;
        keystroke = new INPUT[ keystrokes_to_send ];
        for( i = 0; i < character_count; ++i )
        {
            keystroke[ i * 2 ].type = INPUT_KEYBOARD;
            keystroke[ i * 2 ].ki.wVk = 0;
            keystroke[ i * 2 ].ki.wScan = text[ i ];
            keystroke[ i * 2 ].ki.dwFlags = KEYEVENTF_UNICODE;
            keystroke[ i * 2 ].ki.time = 0;
            keystroke[ i * 2 ].ki.dwExtraInfo = GetMessageExtraInfo();
    
            keystroke[ i * 2 + 1 ].type = INPUT_KEYBOARD;
            keystroke[ i * 2 + 1 ].ki.wVk = 0;
            keystroke[ i * 2 + 1 ].ki.wScan = text[ i ];
            keystroke[ i * 2 + 1 ].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
            keystroke[ i * 2 + 1 ].ki.time = 0;
            keystroke[ i * 2 + 1 ].ki.dwExtraInfo = GetMessageExtraInfo();
        }
    
        //Send the keystrokes.
        keystrokes_sent = SendInput( ( UINT )keystrokes_to_send, keystroke, sizeof( *keystroke ) );
        delete [] keystroke;
    
        return keystrokes_sent == keystrokes_to_send;
    }
    

    使用SendMessage()

    int SendKeystrokesToNotepad( const TCHAR *const text )
    {
        HWND notepad, edit;
    
        assert( text != NULL );
    
        //Get the handle of the Notepad window.
        notepad = FindWindow( _T( "Notepad" ), NULL );
        if( notepad == NULL )
            return 0;
    
        //Get the handle of the Notepad window's edit control.
        edit = FindWindowEx( notepad, NULL, _T( "Edit" ), NULL );
        if( edit == NULL )
            return 0;
    
        SendMessage( edit, EM_REPLACESEL, ( WPARAM )TRUE, ( LPARAM )text );
        return 1;
    }
    

    希望对你有帮助。

    【讨论】:

    • 在 SendInput() 示例中,KEYEVENTF_UNICODE 是否关心文本类型,也可能是字符?我看不到 KEYEVENTF_SCANCODE 但你把你的角色放在 wScan 中。 GetMessageExtraInfo() 有必要吗?
    • @DevNoob:不,这应该适用于 Unicode 和非 Unicode 版本。 (我刚刚对其进行了测试。)是的,GetMessageExtraInfo() 似乎 是必需的,因为文档指定它是必需的。顺便说一句,您的问题的答案也可以通过使用我的答案中的链接阅读相应功能和类型的 MSDN 文档来找到。
    • @DevNoob,我不完全确定您对KEYEVENTF_KEYUP 被排除在外是什么意思。我也不确定您引用的文档部分是什么意思。如果您想知道为什么需要 key-down 和 key-up 键盘事件,那是因为这些事件被用于为目标窗口生成相应的 WM_KEYDOWN 和 WM_KEYUP 窗口消息。我们在低级别工作,我不认为 Windows API 提供 WM_KEYPRESS 消息来表示单个键 press
    • @DevNoob,使用WM_KEYDOWNWM_KEYUP 实际上是一个非常好的解决方案,因为它非常兼容。这是因为这些 Window 消息是几乎所有 Windows 应用程序的标准。将它们分开也给了我们更多的控制权。我能想到的唯一不支持这种方法的 Windows 应用程序类型是那些使用 DirectInput 的应用程序。这样做的一个缺点是 SendInput 仅将消息发送到当前聚焦的窗口,这可能类似于菜单而不是文本字段。
    • 抱歉复制粘贴错误。我做到了,但是 MS 应该清楚地区分发送的字符和必须用作输入的字符。这就是我一开始就误解了。我仍然不明白为什么 KEYEVENTF_SCANCODE 被遗漏了。根据文档“......如果指定,wScan 会识别密钥并忽略 wVk。”来自here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多