There is my code, a simple console program that consists of menu() function for now.
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();
}
Unfortunately, there is one problem that ruins everything. I'm using <windows.h> to read keyboard buttons from console, but ReadConsoleInput() function catches all states of button (pressed and released), so I'm getting double printed vars[] every every time I press a key (up and down arrows in this case). How can "key-ups" be ignored, and only "key-downs" can be catched?
CodePudding user response:
Every time ReadConsoleInput
returns, you go through the if
and then go back to the beginning of the loop and print the "menu" (vars
). ReadConsoleInput
returns whenever a button is pressed or released. You can even see that pressing a button that isn't VK_UP
or VK_DOWN
will print "Use UP or DOWN arrows\n"
, but then releasing that button will not print this line.
A simple solution is to wrap ReadConsoleInput
in a loop to filter out the events you don't want.
do {
ReadConsoleInput(s_in, &rec, 1, &dr);
FlushConsoleInputBuffer(s_in);
} while (rec.EventType == KEY_EVENT && !rec.Event.KeyEvent.bKeyDown);
Probably a better solution is to move the menu printing outside of the loop and repeat it at the end of the keydown processing:
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]);
}
}
}
}
The menu printing should really be a function at this point, so you don't have to repeat these lines of code. Note that this also eliminates the need for FlushConsoleInputBuffer
.