如何关闭或忽略curses应用程序的密钥重复

How do I turn off or ignore key repeat for my curses application?

本文关键字:密钥 应用程序 curses 何关闭      更新时间:2023-10-16

所以我最近发现了curses(特别是PDcurses),我刚刚开始使用它。现在我正在尝试用它编写一个小型空间射击游戏,到目前为止,它在渲染和获取菜单类型输入方面都很好,但现在当我进入游戏时,我注意到按键重复对动作游戏来说非常糟糕。我需要能够按住关键点,并在关键点按下的每一帧移动我的化身。我知道如何使用普通的Win32应用程序来执行此操作,但我没有窗口,因此我没有wndpoc,并且我无法控制控制台接收到的消息:/

我不认为这是诅咒可以处理的事情,尽管如果可以的话,那就太棒了,我真的只是在寻找一个能很好地处理诅咒的解决方案。

我尝试过cbreak()、nodelay()和raw(),但都没有成功。

附加信息:

  • Microsoft Visual Studio 2010旗舰版
  • PDcurses 3.4,来自预构建的二进制文件
  • Windows 7 x64旗舰版

这远不是一个完整的解决方案,我不知道它将如何与PDCurses交互,但这是一种尝试:

总之,使用GetStdHandle()获取控制台的句柄,使用SetConsoleMode()将其配置为原始读取,然后使用ReadConsoleInput()一次读取一个密钥。我使用std::set来跟踪当前按下的键,因此忽略重复。

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    BOOL success;
    success=GetConsoleMode(h, &mode);
    assert(success);
    mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
    mode |= ENABLE_WINDOW_INPUT;
    success=SetConsoleMode(h, mode);
    assert(success);
    INPUT_RECORD buffer[10];
    std::set<WORD> keys_down;
    while (true)
    {
        DWORD count=0;
        success=ReadConsoleInput(h, buffer, 10, &count);
        if (!success)
        {
            continue;
        }
        for (size_t i=0;i<count;++i)
        {
            switch (buffer[i].EventType)
            {
            case KEY_EVENT:
            {
                WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
                if (buffer[i].Event.KeyEvent.bKeyDown)
                {
                    if (keys_down.find(keycode)==keys_down.end())
                    {
                        std::cout<<"Key down: "<<keycode<<std::endl;
                        keys_down.insert(keycode);
                    }
                }
                else
                {
                    if (keys_down.find(keycode)!=keys_down.end())
                    {
                        std::cout<<"Key up:"<<keycode<<std::endl;
                        keys_down.erase(keycode);
                    }
                }
                break;
            }
            default: 
                break;
            }
        }
    }
}