WM_KEYDOWN 重复计数?

spo*_*gGT 6 winapi

MSDN 文档说 LParam 前 15 位用于重复计数,但它说它不是累积的

现在除非我在这里遗漏了一些东西,为什么它称它为重复计数但说它不是累积的?

这是一个矛盾的说法?它说它可以,但它没有?或者我在这里遗漏了什么?

我实际上对其进行了测试并使用按位运算符对其进行屏蔽以提取前 15 位,LParam&0xFFFF无论我按住键多少,该值仍为 1

除非我做错了什么或遗漏了什么,我不知道这个不算数的计数器有什么意义?或者我是否误解了某些事情并以错误的方式执行此操作,并且需要做一些事情才能使用它

拥有这个计数器会更有效和方便,这样我就不必运行所有其他代码来计算按下和按住的键的重复计数,那么是否可以使用前 15 位来完成?也许增加前 15 位?

the*_*heB 6

让我们从文档开始:

当前消息的重复计数。该值是由于用户按住键而自动重复击键的次数。

这部分比较简单。重复计数字段是按键的“按下”次数。

如果击键时间足够长,则会发送多条消息。

可以发送多条消息,具体取决于您的消息循环。只要按键按下,Windows 就会继续向您发送消息,因此您可以继续重复处理。

但是,重复计数不是累积的。

重复计数不会在消息之间延续。换句话说,每条消息代表自上次处理WM_KEYDOWN消息以来重复的次数。

您从未看到重复计数高于 1 的原因是您处理窗口消息的速度太快。您可以通过在WM_KEYDOWN消息处理程序中设置延迟以允许更多重复队列进入下一条消息,从而看到更高的数字。(在 C# 中,因为样板代码较少,但您应该能够将其翻译成您使用的任何语言。)

private const int WM_KEYDOWN = 0x0100;
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_KEYDOWN)
    {
        System.Threading.Thread.Sleep(1000);
        this.Text = $"Keydown Count: {m.LParam.ToInt32() & 0xFF}";
    }
    base.WndProc(ref m);
}
Run Code Online (Sandbox Code Playgroud)

运行此代码,我看到重复计数接近 20-30。

如果您需要重复的总数,则需要从第一次WM_KEYDOWNWM_KEYUP. 设计使您可以在事件进入时对其进行处理。(想象一个文本框:响应性要求您在键进入时对其进行处理,而不是等到键被释放。)