【问题标题】:Key input lags when using Windows API and WM_KEYDOWN C++使用 Windows API 和 WM_KEYDOWN C++ 时键输入滞后
【发布时间】:2012-04-01 22:31:12
【问题描述】:

所以我正在尝试使用 Windows API(和 DirectX9,如果重要的话)制作程序,并尝试使用 WM_KEYDOWN 和 WM_KEYUP 从键盘获取输入。这是我现在代码的相关部分。这个想法是“keyTimes”数组应该存储一个键被按下的帧数。

    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);


    Game* Game::s_instance = NULL;

    LPDIRECT3D9 d3dObject;
    LPDIRECT3DDEVICE9 d3dDevice;

    Game::Game(){
        for(int i=0; i<256; i++){
            keyTimes[i]=0;
        }

    }

    //....

    Game* Game::Instance(){
        if(Game::s_instance==NULL){
            s_instance = new Game();
        }
        return s_instance;
    }

    //Checks to see if key was pressed, and adds to value
    void Game::keyCheck(int keyNum, bool pressed){
        if(pressed){
            keyTimes[keyNum]++;
        }
        else{
            keyTimes[keyNum]=0;
        }

    }

    //Returns time that key has been pressed
    int Game::keyPressed(int keyNum){
            return keyTimes[keyNum];
    }

    //Returns true if key was hit once, and doesn't return true again until the key is let go and hit again.
    bool Game::keyHit(int keyNum){
        return keyTimes[keyNum]==1;
    }

    //Returns true only if the key has been held for delay
    bool Game::keyHeld(int keyNum, int delay){
        if(delay==0)
            delay=1;

        return keyTimes[keyNum]==delay;

    }

    //Returns true everyXFrame frames.
    bool Game::keyPressedDelay(int keyNum, int everyXFrame){
        if(everyXFrame<2){
            return false;
        }
        return keyTimes[keyNum]%everyXFrame==1;
    }


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){

    switch (message)
    {
            case WM_DESTROY:
                 PostQuitMessage(0);
            break;
            case WM_KEYDOWN:
                {
                    Game::Instance()->keyCheck(wParam,true);

                    return 0;   

                }
            break;
            case WM_KEYUP:
                {

                    Game::Instance()->keyCheck(wParam,false);
                    return 0;
                }
            break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;

}


    //........
    //Inside the main function while loop....


    if(Game::Instance()->keyHit(VK_LEFT)){
        thing->move(-3,0);
    }
    if(Game::Instance()->keyHit(VK_RIGHT)){
        thing->move(3,0);
    }
    if(Game::Instance()->keyHit(VK_UP)){
        thing->move(0,-3);
    }
    if(Game::Instance()->keyHit(VK_DOWN)){
        thing->move(0,3);
    }

    //.......

因此,当我尝试使用“KeyPressed”函数作为布尔值来移动主函数中的“事物”时,它会移动三个像素,停止大约半秒,然后再次开始移动。如果我在按住第一个键的同时尝试按下另一个键,它也会再次停止。当我使用“KeyHit”移动它时,它会移动大约 9-12 个像素,然后停止(而不是只移动 3 个像素)。

我将如何更改我的代码,以使函数按照注释的方式工作,没有任何延迟?

编辑 3/26/12:我已设法修复代码。事实证明,问题只是我在我的主循环中使用了 GetMessage 函数,它在移动之前等待输入,而我应该一直使用 PeekMessage。

【问题讨论】:

  • 也许WM_MOVEUP(或类似的)消息将有助于解决问题,如果您在密钥关闭时继续发送它。非系统定义的消息有指定的消息范围。

标签: c++ winapi keyboard


【解决方案1】:

keyHit 仅在前 500 毫秒内有效,因为自动重复启动并导致命中计数超过 1。

添加一些调试跟踪以观察您收到的消息以及每次在主游戏循环中检查keyTimes 的值是多少。这可能会发现问题。

【讨论】:

  • 我在我的代码中移动了一点,我发现当我按下一个键时它实际上冻结了整个程序,而不仅仅是停止输入。也许还有其他问题......
【解决方案2】:

因此,当我尝试使用“KeyPressed”函数作为布尔值来移动主函数中的“事物”时,它会移动三个像素,停止大约半秒,然后再次开始移动。

这是标准的 Windows 行为。

例如,如果您转到 Windows 控制面板 并在 键盘 属性中将 重复延迟 设置为短,您会发现您的现在减少了延迟时间。

【讨论】:

  • 不幸的是,我正在使用的笔记本电脑似乎不允许这种事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2021-09-07
  • 2013-11-06
  • 2013-10-21
  • 2015-02-03
  • 1970-01-01
相关资源
最近更新 更多