有我的代碼,一個簡單的控制臺程式,現在由 menu() 函陣列成。
void menu() {
int k = 0;
HANDLE s_in = GetStdHandle(STD_INPUT_HANDLE);
DWORD dr;
INPUT_RECORD rec;
printf("Choose a num\n");
char vars[] = { '1. A', '2. B', '3. C' };
while (true)
{
for (int i = 0; i < sizeof(vars) / sizeof(vars[0]); i ) {
if (k == i) printf("%c [*]\n", vars[i]);
else printf("%c\n", vars[i]);
}
ReadConsoleInput(s_in, &rec, sizeof(INPUT_RECORD), &dr);
FlushConsoleInputBuffer(s_in);
if (rec.EventType == KEY_EVENT) {
if (rec.Event.KeyEvent.bKeyDown) {
switch (rec.Event.KeyEvent.wVirtualKeyCode) {
case VK_UP:
if (k > 0) k--;
break;
case VK_DOWN:
if (k < ((sizeof(vars) / sizeof(vars[0])) - 1)) k ;
break;
default:
printf("Use UP or DOWN arrows\n");
break;
}
}
}
}
}
int main()
{
menu();
}
不幸的是,有一個問題毀了一切。我正在使用 <windows.h> 從控制臺讀取鍵盤按鈕,但是 ReadConsoleInput() 函式會捕獲按鈕的所有狀態(按下和釋放),所以每次按下一個鍵時我都會得到雙重列印的 vars[] (在這種情況下向上和向下箭頭)。怎么能忽略“key-ups”,而只能抓住“key-downs”呢?
uj5u.com熱心網友回復:
每次ReadConsoleInput回傳時,您都會經過if,然后回傳到回圈的開頭并列印“選單”(vars)。ReadConsoleInput每當按下或釋放按鈕時回傳。您甚至可以看到按下一個不是VK_UP或VK_DOWN將列印的按鈕"Use UP or DOWN arrows\n",但隨后釋放該按鈕將不會列印此行。
一個簡單的解決方案是包裹ReadConsoleInput在一個回圈中以過濾掉您不想要的事件。
do {
ReadConsoleInput(s_in, &rec, 1, &dr);
FlushConsoleInputBuffer(s_in);
} while (rec.EventType == KEY_EVENT && !rec.Event.KeyEvent.bKeyDown);
可能更好的解決方案是將選單列印移出回圈并在 keydown 處理結束時重復它:
for (int i = 0; i < sizeof(vars) / sizeof(vars[0]); i ) {
if (k == i) printf("%c [*]\n", vars[i]);
else printf("%c\n", vars[i]);
}
while (true)
{
ReadConsoleInput(s_in, &rec, 1, &dr);
if (rec.EventType == KEY_EVENT) {
if (rec.Event.KeyEvent.bKeyDown) {
switch (rec.Event.KeyEvent.wVirtualKeyCode) {
case VK_UP:
if (k > 0) k--;
break;
case VK_DOWN:
if (k < ((sizeof(vars) / sizeof(vars[0])) - 1)) k ;
break;
default:
printf("Use UP or DOWN arrows\n");
break;
}
for (int i = 0; i < sizeof(vars) / sizeof(vars[0]); i ) {
if (k == i) printf("%c [*]\n", vars[i]);
else printf("%c\n", vars[i]);
}
}
}
}
此時選單列印應該真的是一個函式,所以你不必重復這些代碼行。請注意,這也消除了對FlushConsoleInputBuffer.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/530408.html
標籤:C温纳皮菜单
