4

Win32 应用程序如何仅响应第一个 WM_KEYDOWN 通知?MSDN 文档声称第 30 位“指定先前的密钥状态。如果在发送消息之前密钥已关闭,则值为 1,如果密钥已启动,则值为 0。” 但在我的 WndProc 中,位 30 始终为 0。

case WM_KEYDOWN:
    // ToDo - stop multiple notifications for repeating keys
    printf("WM_KEYDOWN %i %i", wParam, lParam & 30);
    return 0;

lParam & 30是错误的方法吗?我做错了什么吗?

4

4 回答 4

11

要测试第 30 位,不要与 30 与,而是与 1 << 30 与。

const bool isBitSet = lParam & (1 << 30);
于 2009-09-01T14:33:11.323 回答
4

要获得第 30 位,您需要:

(lParam & 0x40000000)

另一种方法是使用位 0-15 来获取重复计数:

int repeatCount = (lParam & 0xffff)

并且仅在重复计数为 0(或可能为 1;我不确定第一条消息的重复计数为 0 还是 1,并且从文档中不清楚)时才执行任何操作。

于 2009-09-01T14:33:07.110 回答
4

按位 AND(lParam & 0x4000000)将起作用,但您可以使用 Windows.h 中包含的定义轻松使其更具可读性(您已经在使用 for WM_KEYDOWN):

case WM_KEYDOWN:
    if((HIWORD(lParam) & KF_REPEAT) == 0) //process wParam
    return 0;

HIWORD采用最高有效 16 位。

KF_REPEATWM_KEYDOWN(= 0x4000) 标记表示重复消息的位的位置。

当重复标志关闭(初始按键)时,这些值的按位与等于 0,并且每次后续时间(自动重复功能)都等于 1,直到释放键。

这是一件小事,但它对提高代码的可读性大有帮助。0x40000000对读者没有任何意义,但可以从中推断出很多东西 KF_REPEAT

于 2014-11-10T11:28:48.260 回答
1

做 lParam & 30 的问题是,这里的 '30' 被认为是十进制的,当转换为二进制时会是 '11110'。因此,您不是在测试第 30 位,而只是获得 lparam 和 11110 的结果。

希望这有助于澄清问题。

于 2009-09-02T18:35:02.013 回答