简体   繁体   English

如何正确使用WM_KEYDOWN?

[英]How to use WM_KEYDOWN properly ?

I defined a few functions to process Input using WM_KEYDOWN / WM_KEYUP, but only WM_KEYUP seems to work properly. 我定义了一些函数来使用WM_KEYDOWN / WM_KEYUP处理输入,但是似乎只有WM_KEYUP可以正常工作。 When using the function that utilizes WM_KEYDOWN nothing happens. 使用使用WM_KEYDOWN的函数时,不会发生任何事情。 (Debug message isnt displayed) (未显示调试消息)

When initializing an instance of my Input-class inside my Framework-object, I pass it a pointer to the MSG object that my Framwork uses. 当在我的Framework对象中初始化我的Input类的实例时,我将其指针传递给Framwork使用的MSG对象。 (Also the ESCAPE argument inside my function is same as VK_ESCAPE) (我的函数中的ESCAPE参数也与VK_ESCAPE相同)

Here is my code: 这是我的代码:
//Input.cpp //Input.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 //Framework.cpp

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

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

Anyone got an idea why only the KeyReleased() function works but the KeyPressed() doesn't ? 任何人都知道为什么只有KeyReleased()函数起作用而KeyPressed()没有起作用?
Thanks in advance 提前致谢

Ok, looking at your code it seems like the problem is the message loop in your Run() function: 好的,查看您的代码,看来问题出在您的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();
        }
    }
}

Look at what this is doing. 看看这是在做什么。 Every loop iteration, the process is: 每次循环迭代,过程为:

  • If a message is in the queue, process it 如果消息在队列中,请对其进行处理
  • Otherwise, call the Frame() function 否则,调用Frame()函数

When a message is processed it's dispatched to the window and handled by your WndProc , which actually does very little. 处理完一条消息后,该消息将被分发到窗口并由您的WndProc处理,实际上它WndProc很少的事情。 Most of your message processing is done in Frame() or the functions called by Frame() , but that function is only called if there isn't a message in the queue. 你的大多数消息处理的是在完成Frame()或调用的函数Frame()如果没有在队列中的消息功能仅调用。

This explains why you are seeing WM_KEYUP but not WM_KEYDOWN . 这解释了为什么您看到的是WM_KEYUP而不是WM_KEYDOWN The two messages generally come together, at least if you press and release the key at normal speed. 通常,至少在您以正常速度按下和释放键时,这两个消息会同时出现。

The first time through the loop, PeekMessage will retrieve WM_KEYDOWN and dispatch it to your window procedure, which does nothing with it. 第一次通过循环, PeekMessage将检索WM_KEYDOWN并将其分派到您的窗口过程,该过程不会执行任何操作。

The loop then repeats, and retrieves WM_KEYUP . 然后重复循环,并检索WM_KEYUP Again this is sent to the window procedure (which does nothing with it), but with no further messages in the queue the next time around your Frame() function is called - which then processes the most recently retrieved message but none of the other messages that came before it. 再次将其发送到窗口过程(不执行任何操作),但是下次调用Frame()函数时队列中没有其他消息-然后,该函数将处理最近检索到的消息,但不处理其他任何消息在那之前。

To fix your code you need to refactor your message handling so that every message is processed, not just the last in any particular batch. 要修复代码,您需要重构消息处理,以便处理每条消息,而不仅仅是处理任何特定批处理中的最后一条。

WM_KEYDOWN goes through the TranslateMessage block and would reach your block as WM_CHAR. WM_KEYDOWN经过TranslateMessage块,并作为WM_CHAR到达您的块。

So I think you must try WM_CHAR instead. 因此,我认为您必须尝试使用​​WM_CHAR。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM