如何只检测一次相同的键盘按键 [英] how to detect same keyboard key press only once

查看:101
本文介绍了如何只检测一次相同的键盘按键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个键盘类,该类只能检测一次键盘按键,但是我仍然不知道这样做的方法.我的目标是仅在按住同一键或保持不动时检查并仅执行一次操作,而同时按下两个操作键则不执行任何操作.例如,当我持续按住键A时,动作1仅执行一次.然后,我按住或按住另一个键B,动作2也执行一次.如果同时按下A键和B键,我将无法执行任何操作.

I am designing a keyboard class that can detect the keyboard key press only one time but I still cannot figure out the way to do it. My goal is just check and perform the action only once when the same key is keep pressing or keep holding and no action performed when 2 action keys are pressed at the same time. For example, when I keep pressing or holding key A, action 1 is only perform once. Then I keep pressing or holding another key B, action 2 is also perform once. I cannot peform any action if I press key A and B at the same time.

KeyboardClass标头和cpp文件中有两个类,即KeyboardClientClass和KeyboardServerClass.

There is two class inside KeyboardClass header and cpp file i.e. KeyboardClientClass and KeyboardServerClass.

////////////////////////////////////////////////////////////////////////////////
// Filename: KeyboardClass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _KEYBOARDCLASS_H_
#define _KEYBOARDCLASS_H_

////////////////////////////////////////////////////////////////////////////////
// Class prototype
////////////////////////////////////////////////////////////////////////////////
class KeyboardServerClass;


////////////////////////////////////////////////////////////////////////////////
// Class name: KeyboardClientClass
////////////////////////////////////////////////////////////////////////////////
class KeyboardClientClass
{
public:
    KeyboardClientClass( const KeyboardServerClass& KeyboardServer );
    ~KeyboardClientClass();
    bool KeyIsPressed( unsigned char keycode ) const;
    bool KeyIsPressedOnce( unsigned char keycode );

private:
    unsigned char tempKeyCode;
    const KeyboardServerClass& server;
};

class KeyboardServerClass
{
    friend KeyboardClientClass;

public:
    KeyboardServerClass();
    ~KeyboardServerClass();
    void OnKeyPressed( unsigned char keycode );
    void OnKeyReleased( unsigned char keycode );

   private:
        static const int nKeys = 256;
        bool keystates[ nKeys ];
        bool isKeyDown;
    };

    #endif


////////////////////////////////////////////////////////////////////////////////
// Filename: KeyboardClass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "KeyboardClass.h"

KeyboardClientClass::KeyboardClientClass( const KeyboardServerClass& KeyboardServer ) 
: server ( KeyboardServer )
{
    tempKeyCode = 257;
}


KeyboardClientClass::~KeyboardClientClass()
{}


bool KeyboardClientClass::KeyIsPressed( unsigned char keycode ) const
{
    return server.keystates[ keycode ];
}



bool KeyboardClientClass::KeyIsPressedOnce( unsigned char keycode )
{
    if ( tempKeyCode != keycode )
    {
        tempKeyCode = keycode;
        return server.keystates[ keycode ];
    }
    else
    {
        return false;
    }
}


KeyboardServerClass::KeyboardServerClass()
{
    for ( int x = 0; x < nKeys; x++ )
    {
        keystates[ x ] = false;
    }
}


KeyboardServerClass::~KeyboardServerClass()
{
    isKeyDown = true;
}


void KeyboardServerClass::OnKeyPressed( unsigned char keycode )
{
    keystates [ keycode ] = true;
    isKeyDown = false;
}


void KeyboardServerClass::OnKeyReleased( unsigned char keycode )
{
    keystates [ keycode ] = false;
    isKeyDown = true;
}

首先,我创建一个KeyboardServer对象,以跟踪Windows Procedure中的键盘消息.

Firstly, I create the a KeyboardServer object to keep track of the keyboard messgae from Windows Procedure.

LRESULT CALLBACK SystemClass::MessageHandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch ( msg )
    {
        //************ KEYBOARD MESSAGES ************ //

        // Check if a key has been pressed on the keyboard
        case WM_KEYDOWN:
        {
            if ( wParam == VK_ESCAPE )
                PostQuitMessage( 0 );

            // If a key is pressed send it to the KeyboardServer object so it can record the state
            m_KeyboardServer.OnKeyPressed( wParam );
            break;
        }

        // Check if a key has been released on the keyboard
        case WM_KEYUP:
        {
            // If a key is released then send it to the KeyboardServer object so it can unset the state for that key
            m_KeyboardServer.OnKeyReleased( wParam );
            break;
        }

        // ************ END KEYBOARD MESSAGES ************ //
}

然后,我在Game类中创建一个KeyboardClient对象,以检查是否已按下某个键,并根据所按下的键执行操作.

Then, I create a KeyboardClient object at Game class to check whether a key has been pressed or not and perform the action based on key pressed.

if ( m_Keyboard.KeyIsPressed( KEY_B ) )
    // Do action A
else if ( m_Keyboard.KeyIsPressed( KEY_N ) )
    // Do action B

推荐答案

Bit 30 of the lParam value for the WM_KEYDOWN message indicates whether or not the key was previously down when the message was generated. You can use this to distinguish between the actual keypress and any subsequent key repeats.

case WM_KEYDOWN:
    if (lParam & (1 << 30))
    {
        // this is a repeat
    }
    else
    {
        // first press
    }
    break;

但是,如果您似乎试图实时检查哪些键已关闭,则可以使用

But if, as it seems, you're trying to check in realtime which keys are down, you can do this using the GetAsyncKeyState() function rather than relying on tracking keystate via your message loop.

这篇关于如何只检测一次相同的键盘按键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆