2012-09-30 104 views
1

我正在使用一個簡單的循環捕捉用戶按鍵;捕捉按鍵C++

while (1) 
{ 
    for(i = 8; i <= 190; i++) 
    { 
     if (GetAsyncKeyState(i) == -32767){ 
     //Do stuff 
     } 
    } 
} 

這將「做的東西」,當用戶按下某個鍵,但是很明顯,因爲它是無限循環,併爲我新的C++它佔用100%的CPU是不利於一個簡單的輸入。

我在做什麼錯?我已經嘗試了Sleep()函數(如果我把它放在'for循環'中,它會丟失按鍵,如果我把它放在'while循環'中,它根本不會降低CPU,afaik)

我可以使它按照相同的方式抓取按鍵,但使用的CPU不會太多;我錯過了一招嗎?我相信大多數程序都會捕獲按鍵,並且你沒有看到全部使用它們!

非常感謝。

+0

你不能使用線性算法做到這一點......你需要爲你的程序添加一個監聽器。谷歌那。 –

+0

使用鉤子。 「GetMessage」將一直處於空閒狀態,直到發生關鍵事件。對於比較髒的解決方案,在循環中添加一個「睡眠(10)」或其他東西。 – chris

+0

在過去,我使用了'RegisterHotkey'和'UnregisterHotkey'的組合。我只想在窗口焦點時檢測按鍵,所以我在窗口不合焦的時候調用了'UnregisterHotkey',並在窗口返回焦點時將其註冊。也許這些功能會幫助你。如果在窗口沒有對焦的情況下未註銷熱鍵,則可能會弄亂其他應用程序熱鍵。 – Marlon

回答

0

你可以使用

​​

這可能會有幫助。

+0

我的編譯器不能識別kbhit(DevC++)這個命令會使用哪個編譯器? –

+0

你有包括'conio.h'嗎? –

+0

現在感謝,雖然仍然非常高的CPU,我會嘗試像其他評論建議的鉤子或聽衆。謝謝。 –

2

請檢查以下鏈接,解釋正確使用GetAsyncKeyState()和示例代碼。 http://www.mpgh.net/forum/31-c-c-programming/120656-proper-use-getasynckeystate.html

希望這個鏈接可以幫助你解決你的問題

編輯: 的GetAsyncKeyState()函數是不理想的你正在嘗試做的。

它所做的只是檢查鍵盤上某個鍵的實際當前位置。這樣做幾乎總是不正確的。

而是使用正確的輸入功能讀取控制檯輸入。請在下面找到示例代碼。

#include <stdio.h> 
#include <windows.h> 

int main() 
{ 
    DWORD  mode;   /* Preserved console mode */ 
    INPUT_RECORD event;   /* Input event */ 
    BOOL   done = FALSE; /* Program termination flag */ 
    unsigned int counter = 0; /* The number of times 'Esc' is pressed */ 

    /* Don't use binary for text files, OK? ;-) */ 
    FILE* myfile = fopen("example.txt", "w"); 

    /* Get the console input handle */ 
    HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE); 

    /* Preserve the original console mode */ 
    GetConsoleMode(hstdin, &mode); 

    /* Set to no line-buffering, no echo, no special-key-processing */ 
    SetConsoleMode(hstdin, 0); 

    /* Give the user instructions */ 
    printf(
     "Press Escape as many times as you like.\n" 
     "Press anything else to quit.\n\n" 
     ); 

    while (!done) 
    { 
     if (WaitForSingleObject(hstdin, 0) == WAIT_OBJECT_0) /* if kbhit */ 
     { 
      DWORD count; /* ignored */ 

      /* Get the input event */ 
      ReadConsoleInput(hstdin, &event, 1, &count); 

      /* Only respond to key release events */ 
      if ((event.EventType == KEY_EVENT) 
      && !event.Event.KeyEvent.bKeyDown) 
       switch (event.Event.KeyEvent.wVirtualKeyCode) 
       { 
        case VK_ESCAPE: 
         counter++; 
         fprintf(myfile, "Escape: %d\n", counter); 
         printf("Button pressed!\n"); 
         break; 
        default: 
         done = TRUE; 
       } 
     } 
    } 

    /* All done! */ 
    printf("You pressed the Escape key %d times\n", counter); 
    fclose(myfile); 
    SetConsoleMode(hstdin, mode); 
    return 0; 
} 
2

把你的無限循環放在工作線程中,讓它在每次迭代時進入合理的時間間隔。 C++ 11使這非常容易:

#include <thread> 
#include <chrono> 

std::chrono::milliseconds THREAD_WAIT = 50; 

int keypress = -1; 

void GetKeyPress() 
{ 
    while (1) 
    { 
     for(i = 8; i <= 190; i++) 
     { 
      int k = GetAsyncKeyState(i); 
      if (/*whatever condition needs to be satisfied*/) 
       keypress = k; 
     } 
     if (keypress != -1) break; //Use this only if you have td.join() below 
     std::this_thread::sleep_for(THREAD_WAIT); 
    } 
} 

int main(void) 
{ 
    ... 

    std::thread td(GetKeyPress); 
    td.join(); //If you want to block until the user presses a key, otherwise remove. 

    //If no join(), do the rest of your program, checking in on keypress when need be 

    return 0; 
}