Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

Как реализовать нажатие клавиш Ctrl и Shift на языке С/C++

Задание звучит так:
Написать программу, которая выводит в заданную позицию консоли информацию про координаты мыши, состояние управляющих клавиш (ALT, CTRL, SHIFT), скан-код и ASCII-код нажатой клавиши. Для вывода результатов использовать функции SetConsoleCursorPosition,(), wsprintf(), WriteConsole()
Перечитал документацию, посмотрел примеры (последний слишком сумбурный). Так как клавиши символьные, то для их написания придется использовать ещё функцию TranslateMessage.
Вопрос по реализации нажатия клавиш, каким образом лучше поступить. (Выделил блок кода, по которому вопрос).
На данный момент имею такой код:
#include "stdafx.h" #include #include #include #include #include #include
#define STR_SIZE 256 #define BUFSIZE 65535 #define SHIFTED 0x8000
int main() {
setlocale(LC_ALL, "rus"); HANDLE hIn, hOut; DWORD size = STR_SIZE; char result[STR_SIZE];
FreeConsole(); AllocConsole(); SetConsoleOutputCP(1251);
hIn = GetStdHandle(STD_INPUT_HANDLE); hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetDC(NULL); // дескриптор стола POINT p; // структура для координат COORD cord; // структура COORD, которая указывает позицию курсора
cord.X = 0; // координата X структуры COORD cord.Y = 0; // координата Y структуры COORD
//------------------------------------------------------------------
HWND hwndMain; HACCEL haccl; UINT uMsg; UINT wParam; LONG lParam; HWND hwnd; MSG msg;
switch (wParam) { case 0x10:
/*SHIFT key.*/ printf("SHIFT pressed", wParam);
break;
case 0x11:
/*CTRL key.*/ printf("CTRL pressed", wParam);
break; case 0x12:
/*ALT key. */ printf("ALT pressed", wParam);
break; default:
printf("OTHER pressed", wParam); /* Обработка воспроизводимых символов. */
break; }
while (GetMessage(&msg, (HWND)NULL, 0, 0)) { if (TranslateAccelerator(hwndMain, haccl, &msg) == 0) { TranslateMessage(&msg); DispatchMessage(&msg); } } //-----------------------------------------------------------------------------
while (1) { wsprintf(result, "Позиция курсора: "); WriteConsole(hOut, result, strlen(result), nullptr, nullptr); GetCursorPos(&p); wsprintf(result, "x = %4ld, y = %4ld
", p.x, p.y); WriteConsole(hOut, result, strlen(result), nullptr, nullptr); SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cord); } return 0; }
UPD:
#include "stdafx.h" #include #include #include #include #include
VOID ErrorExit(LPCSTR); 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; char result[STR_SIZE];
//GetDC(NULL); // дескриптор стола POINT p; // структура для координат COORD cord; // структура COORD, которая указывает позицию курсора
cord.X = 0; // координата X структуры COORD cord.Y = 0; // координата Y структуры COORD
SetConsoleCursorPosition(hOut, cord); wsprintf(result, "Позиция курсора: "); WriteConsole(hOut, result, strlen(result), nullptr, nullptr); GetCursorPos(&p); wsprintf(result, "x = %4ld, y = %4ld
", p.x, p.y); WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
if (scan != 0) { wsprintf(result, "Последняя нажатая клавиша
Scan code: %4u
", (UINT)scan); WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
wsprintf(result, "Character code: %4u
", (UINT)code); WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
if (ctrl) wsprintf(result, "CTRL:(+) "); else wsprintf(result, "CTRL:(-) "); WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
if (shift) wsprintf(result, "SHIFT:(+) "); else wsprintf(result, "SHIFT:(-) "); WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
if (alt) wsprintf(result, "ALT:(+) "); else wsprintf(result, "ALT:(-) "); WriteConsole(hOut, result, strlen(result), nullptr, nullptr); } }
int main() { //setlocale(LC_ALL, "Russian"); SetConsoleCP(1251); SetConsoleOutputCP(1251); 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(LPCSTR lpszMessage) { fprintf(stderr, "%s
", lpszMessage);
// Restore input mode on exit. SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0); }


Ответ

Система отправляет события клавиатуры для консольных приложений не в процесс консольного приложения, а в системный процесс, владеющий окном консоли (csrss или conhost в зависимости от ОС), создавать цикл обработки сообщений бесполезно. Чтобы обрабатывать такие события, нужно использовать специальные функции работы с консольным вводом:
#include #include #include #include #include
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
", p.x, p.y); WriteConsole(hOut, result, wcslen(result), nullptr, nullptr);
if(scan!=0){ wsprintf(result, L"Последняя нажатая клавиша
Scan code: %4u, Character code: %4u
", (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
", lpszMessage);
// Restore input mode on exit. SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0); }
Reading Input Buffer Events - Microsoft Docs

Комментариев нет:

Отправить комментарий