Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:GetKeyState()必须运行一次_C++_Winapi_Keyboard_Keypress - Fatal编程技术网

C++ C++;:GetKeyState()必须运行一次

C++ C++;:GetKeyState()必须运行一次,c++,winapi,keyboard,keypress,C++,Winapi,Keyboard,Keypress,我需要监听我的微型应用程序的键盘键状态 #include <windows.h> #include <fstream> #include <iostream> using namespace std; int main() { while(1) { if(GetKeyState(VK_SPACE) & 0x80) { cout << "Space pressed.\

我需要监听我的微型应用程序的键盘键状态

#include <windows.h>
#include <fstream>
#include <iostream>

using namespace std;

int main()
{
    while(1)
    {
        if(GetKeyState(VK_SPACE) & 0x80)
        {
            cout << "Space pressed.\r\n";
            DoSpaceKeyTask();
        }

        if(GetKeyState(OTHER_KEY) & 0x80)
        {
            cout << "Other key pressed.\r\n";
            DoOtherKeyTask();
        }
    }
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
而(1)
{
if(GetKeyState(VK_空间)&0x80)
{
请尝试以下方法:

#include <windows.h>
#include <fstream>
#include <iostream>

using namespace std;

int main()
{
    char lastSpaceState = 0, lastOtherKeyState = 0, spaceState, otherKeyState;
    while(1)
    {
        spaceState = (GetKeyState(VK_SPACE & 0x80) != 0);
        lastSpaceState = (spaceState && !lastSpaceState);
        if(lastSpaceState)
        {
                cout << "Space pressed.\r\n";
                DoSpaceKeyTask();
        }

        otherKeyState = (GetKeyState(OTHER_KEY) & 0x80 != 0);
        lastOtherKeyState = (otherKeyState && !lastOtherKeyState);
        if(lastOtherKeyState)
        {
                cout << "Other key pressed.\r\n";
                DoOtherKeyTask();
        }

    }

    return 0;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
char lastSpaceState=0,lastOtherKeyState=0,spaceState,otherKeyState;
而(1)
{
spaceState=(GetKeyState(VK_SPACE&0x80)!=0);
lastSpaceState=(spaceState&&!lastSpaceState);
if(lastSpaceState)
{

你想要一个windows钩子来钩住游戏,并对游戏得到的键盘输入做出反应。现在我还没有真正做过这种特定类型的钩子,但我可以给你一个关于流程的好主意。我会让你通过一个你需要的键的映射来减少空间,而不是一个巨大的重复开关,并找出任何sm我放进去的所有扭结

int main()
{
    //I imagine the last argument here is the thread 
    //containing the game's message loop
    HHOOK hook = SetWindowsHookEx (WH_CALLWNDPROC, hookProc, NULL, NULL);

    //main loop

    UnhookWindowsHookEx (hook);
}

LRESULT CALLBACK hookProc (int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HC_ACTION)
    {
         CWPSTRUCT details = *((LPCWPSTRUCT)lParam);

         if (details.message == WM_KEYDOWN)
         {   
              switch (details.wParam)
              { 
                  case KEY_ONE:
                      if (last [KEY_ONE] == UP)
                      {
                          DoKeyOneStuff();
                          last [KEY_ONE] = DOWN;
                      }
                      break;
              }
          }

          else if (details.message == WM_KEYUP)
          {
              switch (details.wParam)
              {
                   case KEY_ONE:
                       last [KEY_ONE] = UP;
                   break;
              }
          }
    }

    return CallNextHookEx (NULL, code, wParam, lParam);
}

注意我如何使用
last[KEY\u ONE]
。我建议使用
std::map
来存储vk代码所需的键。然后,您可以在地图中循环,并减少开关占用的大量空间。

由于按钮保持按下的持续时间,您的函数会被多次调用。系统非常敏感。因此,这是一种解决方法。

您可以这样做(设置一个标志,该标志将在按键按下时指定一个值,然后在按键按下时重新签名)

int k=0;//标志
而(1){
//检查按键是否按下(按键向下)

如果((GetAsyncKeyState('0')&0x8000)和(&(k==0)){k=1;cout我认为您更愿意只在释放键时执行函数“一次”,而不是在按下键时

为了实现这个目标,您不需要任何额外的标志和帮助变量来定义、分配、分配到0,并将每个标志和帮助变量设置为1和重置为0等等。您所需要的只是:首先,您必须在while(1)的范围内使用GetKeyState函数当您按下某个键时进行检查。当表达式返回true时,执行器指针(执行一个代码行的箭头,当您跨入或跨过时,该箭头将前进到下一个代码行)将进入if语句的作用域。然后立即将其困在循环中,并在按下的键仍处于按下状态时将其困在循环中,并在执行函数之前停止它,在向上释放该键时释放它,然后让它执行函数

例如,要在按下并释放空格键时仅“一次”执行DoSpaceKeyTask功能,请执行以下代码:

while (1)
{
    if (GetKeyState(VK_SPACE) & 0x80)
    {
        //The code here executes ONCE at the moment the space bar was pressed
        cout << "Space pressed.\r\n";
        while (GetKeyState(VK_SPACE) & 0x80) //You can write there ';' instead '{' and '}' below
        {
            //The executor pointer is trapped here while space bar is depressed and it will be free once space bar is released
        }
        //The code here executes ONCE at the moment the space bar was released
        cout << "Space released.\r\n";
        DoSpaceKeyTask();
    }
}
while(1)
{
if(GetKeyState(VK_空间)&0x80)
{
//这里的代码在按下空格键时执行一次

cout我也遇到了同样的问题。我有几个键,就像切换按钮一样,每次按下只想注册一次键事件。我的解决方案是制作一个简单的对象来处理逻辑。这可以保持主代码干净:

class KeyToggle {
public:
    KeyToggle(int key):mKey(key),mActive(false){}
    operator bool() {
        if(GetAsyncKeyState(mKey)){
            if (!mActive){
                mActive = true;
                return true;
            }  
        }
        else
            mActive = false;
        return false;
    }
private:
    int mKey;
    bool mActive;
};
下面是用法:

#include <windows.h>

KeyToggle toggleT(0x54);  // T key toggle
KeyToggle toggleF(0x46);  // F key toggle

void main(void)
{
    while(true){
        if(toggleT) {;} // do something
        if(toggleF) {;} // do something
    }
}
#包括
KeyToggle toggleT(0x54);//T键切换
按键切换切换F(0x46);//F按键切换
真空总管(真空)
{
while(true){
如果(toggleT){;}//做某事
如果(toggleF){;}//做某事
}
}

我知道这是一个非常老的线程,但我仍然想分享我的解决方案。我认为创建某种“标志”或“开关”是真的不需要的。下面是我循环所有关键代码的代码:

    while (true) 
    {
        for (int i = 0x01; i < 0xFE; i++) 
        {
            if (GetKeyState(i) & 0x8000)
            {
                std::cout << (char)i << "\n";
                while (GetKeyState(i) & 0x8000) {}
            }
        }
    }
while(true)
{
对于(int i=0x01;i<0xFE;i++)
{
if(GetKeyState(i)&0x8000)
{
试一下这样的东西

    while (!GetKeyState(VK_SPACE) && !GetKeyState('A') == 1) {
    //std::cout << "Key not pressed... \n";
    Sleep(40);
}
if (GetKeyState('A')) {
    std::cout << "\"A \" key pressed... \n";
}
else if (GetKeyState(VK_SPACE)) {
    std::cout << "Space key pressed... \n";
}
while(!GetKeyState(VK_空间)和&!GetKeyState('A')==1){

//std::cout 1.您希望该循环使用
GetAsyncKeyState
。2.您必须使用
0x8000
来屏蔽它。此外,您还可以使用
while(GetAsyncKeyState(…)&0x8000)
等待它上升。这里有一个关于第1点的很好的宣传:嗨,克里斯,GetAsyncKeyState和0x8000仍然是一样的。有什么想法吗?你应该使用一个状态机制,如下图所示,或者使用一些通知你按键/按下的东西,比如窗口或钩子。哦,这会让事情变得更清楚一些。你正在寻找的函数或者是
SetWindowsHookEx
。各种钩子有很多很好的例子,但是你想要的是钩子游戏窗口的消息过程。钩子它以检查关键事件,并适当地处理它们。这不是一个真正的旧的或现代的情况。
GetKeyState
用于当你需要状态时的消息消息已发送。
GetAsyncKeyState
表示当前状态。另外,0x80是10000000。文档中说,如果它是向下的,则会设置高位,并且它返回的是短的,因此是10000000000000或0x8000。我感谢您的回复,但是如果有5个或更多的键,它将是一个完全混乱的状态。@AnılÜnal,您可以使用调用钩子。类似(非真实语法):
if(WM_KEYDOWN){switch(code){case SPACE:if(last==UP)DoSomething();…}}
并使用
WM_KEYDOWN
WM_KEYDOWN
消息设置状态。在键盘操作发生之前不应调用钩子;否则它应该是空闲的。
    while (true) 
    {
        for (int i = 0x01; i < 0xFE; i++) 
        {
            if (GetKeyState(i) & 0x8000)
            {
                std::cout << (char)i << "\n";
                while (GetKeyState(i) & 0x8000) {}
            }
        }
    }
    while (!GetKeyState(VK_SPACE) && !GetKeyState('A') == 1) {
    //std::cout << "Key not pressed... \n";
    Sleep(40);
}
if (GetKeyState('A')) {
    std::cout << "\"A \" key pressed... \n";
}
else if (GetKeyState(VK_SPACE)) {
    std::cout << "Space key pressed... \n";
}