MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как реализовать нажатие клавиш Ctrl и Shift на языке С/C++"
Answer 802885
Система отправляет события клавиатуры для консольных приложений не в процесс консольного приложения, а в системный процесс, владеющий окном консоли (csrss или conhost в зависимости от ОС), создавать цикл обработки сообщений бесполезно. Чтобы обрабатывать такие события, нужно использовать специальные функции работы с консольным вводом:
#include <stdlib.h> #include <locale.h> #include <stdio.h> #include <windows.h> #include <tchar.h> VOID ErrorExit(LPSTR); VOID KeyEventProc(KEY_EVENT_RECORD); VOID MouseEventProc(MOUSE_EVENT_RECORD); #define STR_SIZE 256 #define BUFSIZE 65535 #define SHIFTED 0x8000 HANDLE hStdin; HANDLE hOut; DWORD fdwSaveOldMode; DWORD scan=0; //скан-код последней клавиши wchar_t code=0; //код символа последней клавиши bool alt,ctrl,shift; //состояние управляющих клавиш void PrintData(){ DWORD size = STR_SIZE; TCHAR result[STR_SIZE]; POINT p; // структура для координат COORD cord; // структура COORD, которая указывает позицию курсора cord.X = 0; // координата X структуры COORD cord.Y = 0; // координата Y структуры COORD SetConsoleCursorPosition(hOut, cord); wsprintf(result, L"Позиция курсора: "); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); GetCursorPos(&p); wsprintf(result, L"x = %4ld, y = %4ld\r\n", p.x, p.y); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); if(scan!=0){ wsprintf(result, L"Последняя нажатая клавиша\nScan code: %4u, Character code: %4u\r\n", (UINT)scan,(UINT)code); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); if(ctrl) wsprintf(result,L"CTRL:(+) "); else wsprintf(result,L"CTRL:(-) "); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); if(shift) wsprintf(result,L"SHIFT:(+) "); else wsprintf(result,L"SHIFT:(-) "); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); if(alt) wsprintf(result,L"ALT:(+) "); else wsprintf(result,L"ALT:(-) "); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr); } } int main() { setlocale(LC_ALL, "Russian"); DWORD cNumRead, fdwMode, i; INPUT_RECORD irInBuf[128]; // Get the standard input handle. hStdin = GetStdHandle(STD_INPUT_HANDLE); hOut = GetStdHandle(STD_OUTPUT_HANDLE); // Save the current input mode, to be restored on exit. if (! GetConsoleMode(hStdin, &fdwSaveOldMode) ) ErrorExit("GetConsoleMode"); // Enable the window and mouse input events. fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT; if (! SetConsoleMode(hStdin, fdwMode) ) ErrorExit("SetConsoleMode"); // Loop to read and handle input events. while (1) { // Wait for the events. if (! ReadConsoleInput( hStdin, // input buffer handle irInBuf, // buffer to read into 128, // size of read buffer &cNumRead) ) // number of records read ErrorExit("ReadConsoleInput"); // Dispatch the events to the appropriate handler. for (i = 0; i < cNumRead; i++) { switch(irInBuf[i].EventType) { case KEY_EVENT: // keyboard input KeyEventProc(irInBuf[i].Event.KeyEvent); break; case MOUSE_EVENT: // mouse input MouseEventProc(irInBuf[i].Event.MouseEvent); break; case WINDOW_BUFFER_SIZE_EVENT: case FOCUS_EVENT: case MENU_EVENT: break; } } } // Restore input mode on exit. SetConsoleMode(hStdin, fdwSaveOldMode); return 0; } VOID KeyEventProc(KEY_EVENT_RECORD ker) { if(ker.bKeyDown){ scan=ker.wVirtualScanCode; code=ker.uChar.UnicodeChar; if((ker.dwControlKeyState & SHIFT_PRESSED) > 0) shift=true; else shift=false; if((ker.dwControlKeyState & LEFT_ALT_PRESSED) > 0 || (ker.dwControlKeyState & RIGHT_ALT_PRESSED) > 0) alt=true; else alt=false; if((ker.dwControlKeyState & LEFT_CTRL_PRESSED) > 0 || (ker.dwControlKeyState & RIGHT_CTRL_PRESSED) > 0) ctrl=true; else ctrl=false; PrintData(); } } VOID MouseEventProc(MOUSE_EVENT_RECORD mer) { if(mer.dwEventFlags == MOUSE_MOVED){ PrintData(); } } VOID ErrorExit (LPSTR lpszMessage) { fprintf(stderr, "%s\n", lpszMessage); // Restore input mode on exit. SetConsoleMode(hStdin, fdwSaveOldMode); ExitProcess(0); }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.