【问题标题】:How to use WM_KEYDOWN properly ?如何正确使用 WM_KEYDOWN ?
【发布时间】:2013-12-18 05:41:41
【问题描述】:

我定义了一些函数来使用 WM_KEYDOWN / WM_KEYUP 处理输入,但似乎只有 WM_KEYUP 可以正常工作。当使用利用 WM_KEYDOWN 的函数时,没有任何反应。 (不显示调试信息)

在我的框架对象中初始化我的输入类的实例时,我将一个指针传递给我的框架使用的 MSG 对象。 (另外我的函数中的 ESCAPE 参数与 VK_ESCAPE 相同)

这是我的代码:
//输入.cpp

bool Input::KeyPressed( Keys key )  
{
    if( InputMsg->message == WM_KEYDOWN )
    {
        if( InputMsg->wParam == key )
            return true;
    }

    return false;
}

bool Input::KeyReleased( Keys key )
{
    if( InputMsg->message == WM_KEYUP )
    {
        if( InputMsg->wParam == key )
        return true;
    }

    return false;
}

//Framework.cpp

bool Framework::Frame()
{
    ProcessInput();
    return true;
}

void Framework::ProcessInput()
{
    if( m_Input->KeyPressed( ESCAPE ) )
    {
        OutputDebugString("Escape was pressed!\n");
    }
}

有人知道为什么只有 KeyReleased() 函数有效,而 KeyPressed() 无效吗?
提前致谢

【问题讨论】:

  • Frame() 什么时候被调用? InputMsg 何时/何地被定义?
  • @JonathanPotter Frame() 在我的 Run() 函数中被调用,这是一个 while 循环:while( msg.message != WM_QUIT && m_result) { if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { m_result = Frame(); } }。当我初始化我的输入对象时,我将一个指针传递给我在我的框架类中创建的一个 MSG 对象,这样它就变成了InputMsg(这个初始化也在框架对象内完成)。我的 while() 循环与来自 Framwework 的 MSG 对象一起使用
  • 我认为我们需要查看更多代码。你的窗口程序在做什么?
  • @JonathanPotter 我在第一个答案中添加了指向源代码的链接

标签: c++ winapi message-queue


【解决方案1】:

好的,看看您的代码,问题似乎在于您的 Run() 函数中的消息循环:

void Framework::Run()
{
    while( msg.message != WM_QUIT && m_result)
    {
        if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
            m_result = Frame();
        }
    }
}

看看这是在做什么。每次循环迭代,过程为:

  • 如果消息在队列中,则处理它
  • 否则调用Frame()函数

当消息被处理时,它被分派到窗口并由您的WndProc 处理,这实际上做的很少。您的大部分消息处理是在Frame()Frame() 调用的函数中完成的,但只有在队列中没有消息时才会调用该函数。

这解释了为什么您看到的是WM_KEYUP 而不是WM_KEYDOWN。这两条消息通常会同时出现,至少如果您以正常速度按下并释放键。

第一次通过循环时,PeekMessage 将检索WM_KEYDOWN 并将其分派到您的窗口过程,这与它无关。

然后循环重复,并检索WM_KEYUP。这再次被发送到窗口过程(它不做任何事情),但在下次调用 Frame() 函数时队列中没有更多消息 - 然后处理 最近检索到的消息 但没有出现在它之前的其他消息。

要修复您的代码,您需要重构您的消息处理,以便处理每条消息,而不仅仅是任何特定批次中的最后一条。

【讨论】:

  • 非常感谢。我又学到了很多。现在我通过在 if 语句的两个分支中执行我的 Frame() 函数来解决它。随着我的技能和知识的增长,我会考虑实施更多“专业”的方法。
【解决方案2】:

WM_KEYDOWN 穿过 TranslateMessage 块,并将作为 WM_CHAR 到达您的块。

所以我认为你必须改用 WM_CHAR。

【讨论】:

猜你喜欢
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 2012-07-12
相关资源
最近更新 更多