如何创建 SendMessage WM_KEYDOWN 的 lParam

Posted

技术标签:

【中文标题】如何创建 SendMessage WM_KEYDOWN 的 lParam【英文标题】:How To Create lParam Of SendMessage WM_KEYDOWN 【发布时间】:2012-04-23 11:51:56 【问题描述】:

我正在尝试使用SendMessage 发送击键,但并不真正了解 lParam。我理解不同的位代表每个参数,需要按顺序排列。

我读过this question 和this,所以我知道这些位需要按哪个顺序排列,我只是不知道该怎么做...

我将如何创建以下 lParam?

repeat cound = 0,
scan code = Don't know what this is?,
extended key = 1,
reserved = 0,
context code = 0,
previous key state = 1,
transition state = 0

【问题讨论】:

正如链接的帖子所述,不要使用 SendMessage 发送击键,而是使用 SendInput。 blogs.msdn.com/b/oldnewthing/archive/2005/05/30/423202.aspx @RussC:谢谢,但需要使用 SendMessage 来完成,因为我想将密钥发送到活动窗口以外的窗口。真的,我只需要知道如何构建这个 lParam。 我在下面更新了我的答案。您能否澄清一下您将向 SendMessage 发送 WM_KEYDOWN 消息? 【参考方案1】:

我意识到AutoIT 有我需要的功能,所以查看了source 文件sendKeys.cpp 并找到了该功能的以下C++代码sn-p,它很容易翻译成C# :

scan = MapVirtualKey(vk, 0);

// Build the generic lparam to be used for WM_KEYDOWN/WM_KEYUP/WM_CHAR
lparam = 0x00000001 | (LPARAM)(scan << 16);         // Scan code, repeat=1
if (bForceExtended == true || IsVKExtended(vk) == true)
    lparam = lparam | 0x01000000;       // Extended code if required

if ( (m_nKeyMod & ALTMOD) && !(m_nKeyMod & CTRLMOD) )   // Alt without Ctrl
    PostMessage(m_hWnd, WM_SYSKEYDOWN, vk, lparam | 0x20000000);    // Key down, AltDown=1
else
    PostMessage(m_hWnd, WM_KEYDOWN, vk, lparam);    // Key down

扫描码可以用MapVirtualKey生成

C# 翻译:

public static void sendKey(IntPtr hwnd, VKeys keyCode, bool extended)

    uint scanCode = MapVirtualKey((uint)keyCode, 0);
    uint lParam;

    //KEY DOWN
    lParam = (0x00000001 | (scanCode << 16));
    if (extended)
    
        lParam |= 0x01000000;
    
    PostMessage(hwnd, (UInt32)WMessages.WM_KEYDOWN, (IntPtr)keyCode, (IntPtr)lParam);

    //KEY UP
    lParam |= 0xC0000000;  // set previous key and transition states (bits 30 and 31)
    PostMessage(hwnd, WMessages.WM_KEYUP, (uint)keyCode, lParam);


[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);

【讨论】:

什么是 VKey?和WMessages?您如何将 keyCode 转换为(uint)?因为尝试将 Keys.O 转换为 (uint) 会引发错误。我尝试将您的 (uint) 更改为 (IntPtr),但它引发了溢出异常。 对于那些想知道 VKey 是什么的人:gist.github.com/pushrbx/5ca65124d7aff5b5ca7ffdc5cf6a1254【参考方案2】:

如果您绝对必须使用 SendMessage,那么您需要在正确的位置切换 int 的位。

此站点记录了如何在 C# 中执行此操作:

http://codeidol.com/csharp/csharpckbk2/Classes-and-Structures/Turning-Bits-On-or-Off/

关于您的问题,ScanCode 是您尝试发送的密钥的值,也代表某些状态。比如按A的扫码和放A的扫码是不一样的。

***有一篇关于它们的文章:

http://en.wikipedia.org/wiki/Scancode

【讨论】:

以上是关于如何创建 SendMessage WM_KEYDOWN 的 lParam的主要内容,如果未能解决你的问题,请参考以下文章

sendmessage这个发送消息的函数如何发送字符串

BCB 如何让Application收到SendMessage发送来的消息

如何在 ATL DLL 中获取 HWND(用于 SendMessage 或 PostMessage)

如何模拟后台鼠标点击功能? SendMessage 和PostMessage 都无效。

如何在 Angular 4 中从 chrome.runtime.sendMessage 获取回调?

delphi 用sendmessage向窗体发送关闭信息!但是窗体有关闭提示信息的对话框! 怎么才能把他关闭呢!