RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 801076
Accepted
invzbl3
invzbl3
Asked:2020-03-19 00:58:49 +0000 UTC2020-03-19 00:58:49 +0000 UTC 2020-03-19 00:58:49 +0000 UTC

如何在 C/C++ 中实现按 Ctrl 和 Shift 键

  • 772

任务是这样的:

编写一个程序,显示有关鼠标坐标、控制键状态(ALT、CTRL、SHIFT)、扫描码和给定控制台位置按下键的 ASCII 码的信息。要显示结果,请使用SetConsoleCursorPosition,()、wsprintf()、WriteConsole() 函数。

我重新阅读了文档,查看了示例(最后一个太混乱了)。由于键是象征性的,您将不得不使用另一个函数来编写它们TranslateMessage。

关于击键执行的问题,最好的方法是什么。(突出显示问题所在的代码块)。

目前我有这个代码:

        #include "stdafx.h"
        #include <cstring>
        #include <iostream>
        #include <stdio.h>
        #include <conio.h>
        #include <windows.h>
        #include <winuser.h>


        #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\r\n", p.x, p.y);
                WriteConsole(hOut, result, strlen(result), nullptr, nullptr);
                SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cord);
            }
            return 0;
        }

升级版:

#include "stdafx.h"
#include <stdlib.h>
#include <locale.h>  
#include <stdio.h>
#include <windows.h>
#include <tchar.h>

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\r\n", p.x, p.y);
    WriteConsole(hOut, result, strlen(result), nullptr, nullptr);

    if (scan != 0) {
        wsprintf(result, "Последняя нажатая клавиша\nScan code: %4u\r\n", (UINT)scan);
        WriteConsole(hOut, result, strlen(result), nullptr, nullptr);

        wsprintf(result, "Character code: %4u\r\n", (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\n", lpszMessage);

    // Restore input mode on exit.
    SetConsoleMode(hStdin, fdwSaveOldMode);

    ExitProcess(0);
}
c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    MSDN.WhiteKnight
    2020-03-22T13:22:24Z2020-03-22T13:22:24Z

    系统不会将控制台应用程序的键盘事件发送给控制台应用程序进程,而是发送给拥有控制台窗口的系统进程(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); 
    }
    

    读取输入缓冲区事件 - Microsoft Docs

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5