Как отключить или игнорировать повторение клавиш для моего приложения curses? - PullRequest
2 голосов
/ 02 февраля 2012

Итак, я недавно нашел проклятия (в частности, PDcurses ), и я только вхожу в это.Прямо сейчас я пытаюсь написать небольшую игру типа космического шутера с ней, и до сих пор она отлично работала для рендеринга и получения ввода типа меню, но теперь, когда я вхожу в игру, я заметил, что повторение клавиш довольно плохо дляДействие игры.Я должен быть в состоянии удерживать клавишу и перемещать свой аватар каждый кадр, когда клавиша нажата.Я знаю, как это сделать с обычным приложением Win32, но у меня нет окна, и поэтому у меня нет wndproc, и я не могу контролировать сообщения, которые получает консоль: /

Я не знаюЯ не ожидал, что это что-то для проклятий, но если это возможно, это было бы здорово, я просто искал обходной путь, который прекрасно сочетается с проклятиями.

Я пробовал cbreak (), nodelay() и raw () безрезультатно.

Дополнительная информация:

  • Microsoft Visual Studio 2010 Ultimate
  • PDcurses 3.4, из готовых двоичных файлов
  • Windows 7 x64 Ultimate

1 Ответ

2 голосов
/ 02 февраля 2012

Это далеко не полное решение, и я не знаю, как оно будет взаимодействовать с 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;
            }
        }
    }
}
...