如何检查按键序列是否按下?

时间:2017-05-14 10:43:54

标签: c++

我想检查按键序列是否按下。像密码一样,我希望看到消息框,你必须在正确的顺序中键入“bcqwl”。我试过了

#include <iostream>

#include <windows.h>

using namespace std;

int main()
{
    while(true)
    {
        if(GetKeyState('B') & 0x8000)
        {
            cout<<"b has been press"<<endl;
               if(GetKeyState('C') & 0x8000)
               {
                   cout<<"c has been press"<<endl;
                   if(GetKeyState('Q') & 0x8000)
                   {
                       cout<<"Q has been press"<<endl;
                       if(GetKeyState('W') & 0x8000)
                       {
                           cout<<"W has been press"<<endl;
                           if(GetKeyState('L') & 0x8000)
                           {
                               MessageBox(NULL,"YES","YES",MB_OK);
                           }
                           else
                           {
                               continue;
                           }
                       }
                       else
                       {
                           continue;
                       }
                   }
                   else
                   {
                       continue;
                   }
               }
               else
               {
                    continue;
               }
        }
        else
        {
            continue;
        }
    }
}

但它不起作用。如果按下b,他会打印“B已经按下”,很多次但不是无限次。如果按b后我按c没有任何反应。 所以我很累:

step:
        if(GetKeyState('B') & 0x8000)
        {
            cout<<"B has been press"<<endl;
            goto step1;
        }
        else
        {
            goto step;
        }
        step1:
        if(GetKeyState('C') & 0x8000)
        {
               MessageBox(NULL,"WORK","yes",MB_OK);
        }
        else
        {
            goto step;
        }

但是不起作用。 我也累了:

#include <iostream>

#include <windows.h>

int main()
{
int progress = 0;
    while(progress<=4)
    {
        if(GetKeyState('B') & 0x8000)
        {
            std::cout<<"b has been press"<<std::endl;
            progress=1;
        }
        else
        {
            progress=0;
        }
        if(progress==1)
        {
            if(GetKeyState('C') & 0x8000)
            {
               std::cout<<"c has been press"<<std::endl;
                progress=2;
            }
            else
            {
                progress=0;
            }
        }
        if(progress==2)
        {
            if(GetKeyState('Q') & 0x8000)
            {
                std::cout<<"q has been press"<<std::endl;
                progress=3;
            }
            else
            {
                progress=0;
            }
        }
        if(progress==3)
        {
            if(GetKeyState('W') & 0x8000)
            {
                std::cout<<"w has been press"<<std::endl;
                progress=4;
            }
            else
            {
                progress=0;
            }
        }
        if(progress==4)
        {
            if(GetKeyState('L') & 0x8000)
            {
                std::cout<<"l has been press"<<std::endl;
                progress=5;
            }
            else
            {
                progress=0;
            }
        }

}
return 0;
}

但是输出“b已按下”很多次但不是无限的,如果我按b,之后如果我按c没有发生任何事情,按下b之后的praticaly并且程序进入if(process==1)但是如果我按c没什么事情发生

P.S。抱歉我的英语不好。

1 个答案:

答案 0 :(得分:2)

您仍然遇到的问题来自于您无法在按键顺序中存储进度。

假设您的密码存储在char数组中(以便以后更方便地访问单个字符):

#define PWD_LEN 6 // bcqwl has a length of 5 characters but you need +1 for the '\0' (terminating character) at the end of your string
// ...
char password[PWD_LEN] = "bcqwl";

此外,您还需要一个柜台:

#define PWD_LEN 5
// ...
char password[PWD_LEN] = "bcqwl";
int progress = 0;

while(true) { ... }

两者都需要存储在while循环之前和之外,因为两者都存储了您不希望在循环的每个迭代步骤中重置的数据。

计数器将用于跟踪用户完成密码所代表的密钥序列的进度。

每当用户按下某个键时,您需要进行以下检查:

  • 是否允许钥匙? - 如果您有密码abc,但用户按下y!或其他内容,则按abc是不允许的。
  • 如果允许该密钥,请使用其代表的字符并检查它是否与password中索引progress处的字符相同:

    if ( key allowed )
    {
      if (password[progress] == '<your key character here>')
      {
        ++progress;
      }
      else
      {
        // Handle incorrect key stroke relative to key sequence
      }
    }
    

现在为了防止反香蕉,我建议对键释放进行所有检查,这与按键不同,是一次性事件。按下的键也可以是键保持的一部分,在这种情况下,您将多次登陆else(来自上面的代码段),这可能不是一个好主意

如果密钥正常并且在顺序方面它适合您的密码,那么您可以增加进度,以便在下一个迭代步骤中您可以使用新发布的密钥事件和用于访问密码的新索引值进行相同的检查阵列。

当您的progress达到所需的值,表明密钥序列已完成且密码所包含的所有字符都已“插入”时,您可以打破循环。

这是非常基本的,所以我希望说明书足够清晰,你可以实施。

以前的答案(由于问题发生变化,现已过时)

除非有其他开箱即用的方法(我没有使用GetKeyState()windows.h中的任何其他内容),否则一般的做法是简单地存储{{1每个按钮的状态(在数组中,pressed等。)。

在你的循环中,你可以使用一个简单的struct语句链(但不像你那样嵌套!)来检查当前迭代步骤中按下了哪个按钮。每当按下一个已知密钥(您应用程序想要处理的密钥)时,您只需切换阵列中该按钮的相应状态,if或用于存储此信息的任何其他容器:

struct

while(true) { // Check state of supported buttons if(GetKeyState('A') & 0x8000) { // store change of state of key A } if(GetKeyState('B') & 0x8000) { // store change of state of key B } if (...) { // ... } } 的正文结束或开头,您可以询问每个按钮的状态并进行综合查询:

while

例如,假设您使用以下结构来存储密钥的状态:

while(true)
{
  // Check state of supported buttons
  if(GetKeyState('A') & 0x8000)
  {
    // store change of state of key A
  }
  if(GetKeyState('B') & 0x8000)
  {
    // store change of state of key B
  }
  if (...)
  {
    // ...
  }


  // Do something


  // Check for states of buttons
  // ...
}

你可以简单地做

typedef struct Key
{
  char keyCode;
  bool pressed;
} Key;

Key keyA;
keyA.pressed = false;

检查当前是否按下了您的特定按钮并分别触发某些操作。

对于组合键,事情并没有太大的不同。您只需使用简单的布尔逻辑来处理它:

if (keyA.pressed)
{
  // Trigger some change that key 'A' controls
}

您可以通过在阵列中存储所有支持的按钮来提高代码的可读性,甚至可以添加一个漂亮的if (keyA.pressed && keyB.pressed) { // Both key 'A' and 'B' are pressed - we have a key combo! } 以便轻松访问每个按钮:

enum

如果您无法找到enum KeyCode { A, B, ... }; Key keys[n]; //with n being the number of keys you want to support and also the number of elements your enum has // Access with an improved readability if (keys[A].pressed && keys[B].pressed) { // ... } 的任何代码(极不可能),您可以查看GetKeyState()