0

キーボードのキーの押下を 1 回だけ検出できるキーボード クラスを設計していますが、その方法はまだわかりません。私の目標は、同じキーを押し続けるか押し続けるとアクションを1回だけチェックして実行し、2つのアクションキーを同時に押してもアクションが実行されないことです。たとえば、キー A を押し続けると、アクション 1 が 1 回だけ実行されます。次に、別のキー B を押し続けると、アクション 2 も 1 回実行されます。AキーとBキーを同時に押すと何もできません。

KeyboardClass ヘッダーと cpp ファイル内には、KeyboardClientClass と KeyboardServerClass の 2 つのクラスがあります。

////////////////////////////////////////////////////////////////////////////////
// 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;
}

まず、Windows プロシージャからのキーボード メッセージを追跡するために、KeyboardServer オブジェクトを作成します。

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 オブジェクトを作成して、キーが押されたかどうかを確認し、押されたキーに基づいてアクションを実行します。

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

1 に答える 1

2

lParamメッセージの値のビット 30 はWM_KEYDOWN、メッセージが生成されたときにキーがダウンしていたかどうかを示します。これを使用して、実際のキー押下とその後のキーの繰り返しを区別できます。

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

しかし、どのキーがダウンしているかをリアルタイムで確認しようとしているように見える場合は、GetAsyncKeyState()メッセージ ループを介してキー状態を追跡することに頼るのではなく、関数を使用してこれを行うことができます。

于 2013-09-29T09:29:44.130 に答える