Show / Hide Table of Contents

MSDN.WhiteKnight - Stack Overflow answers

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

Answer 802885

Link

Система отправляет события клавиатуры для консольных приложений не в процесс консольного приложения, а в системный процесс, владеющий окном консоли (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); 
}

Reading Input Buffer Events - Microsoft Docs


Content is retrieved from StackExchange API.

Auto-generated by ruso-archive tools.

Back to top Stack Overflow answers (published from sources in GitHub repository). Copyright (c) 2020, MSDN.WhiteKnight. Content licensed under BSD 3-Clause License.
Generated by DocFX