如何在使用 Windows 控制台 API 的程序中处理来自 ReadConsoleInput 的错误 233?

问题描述 投票:0回答:0

我正在使用 Windows 控制台 API 在 C 中编写文本编辑器。

在我将计算机更新到 Windows 11 之前,一切都运行良好。我收到错误 233 (

ERROR_PIPE_NOT_CONNECTED
)。首先,我在
CreateConsoleScreenBuffer()
函数中遇到了错误,由于我不明白,所以我删除了它,以为我可以在没有它的情况下创建一个缓冲区。但现在我得到了同样的错误
ReadConsoleInput()
.

我真的不明白,网上关于这个错误的所有信息都是关于SQL或.NET的,我没有在我的项目中使用。我问了“phind”(一个 AI 网络浏览器),但没有得到更多信息。

这是我的代码,不要犹豫批评它并给我建议。如果您需要缓冲区的部分,我可以将其添加到答案中。

/*** INCLUDES : ***/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <strsafe.h>
#include <unistd.h>

/*** DEFINES : ***/

#define CTRL_KEY(k) ((k) & 0x1f)

#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
#endif

#define WHITE_FONT FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE

// Sequences de terminal virtuel :
#define ESC "\x1b"
#define CSI "\x1b["

/*** DATA : ***/

/* Structure qui stocke les donnes de configuration de la console */
struct USER_CONSOLE_CONFIG
{
    HANDLE hConsoleInput;
    HANDLE hConsoleOutput;

    DWORD originalConsoleInputMode;
    DWORD originalConsoleOutputMode;

    PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo;
};

struct USER_CONSOLE_CONFIG U = {0};;

//INIT
void InitializeConsole();

//TERMINAL
void ErrorExit(LPTSTR lpszFunction);
void EnableRawMode();
void DisableRawMode();
void HandleKeyEvent();

//INPUT
char ReadInput();

//OUTPUT
void UpdateConsoleScreen();
void ClearConsoleScreen();
void CursorToOrigin();

//BUFFER


/*** INIT : ***/

void InitializeConsole()
{
    // Recupere les handles de buffer d'entree et sortie standards
    U.hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
    if(U.hConsoleInput == INVALID_HANDLE_VALUE || GetLastError() != NO_ERROR)
    {
        ErrorExit(TEXT("GetStdHandle"));
    }

    U.hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    if(U.hConsoleOutput == INVALID_HANDLE_VALUE || GetLastError() != NO_ERROR)
    {
        ErrorExit(TEXT("GetStdHandle"));
    }

    // Recupere le pointeur vers le buffer d'affichage de la console
    if(!GetConsoleScreenBufferInfo(U.hConsoleOutput, &U.lpConsoleScreenBufferInfo))
    {
        ErrorExit(TEXT("GetConsoleScreenBufferInfo"));
    }

    // Recupere le mode actuelle de la console
    if(!GetConsoleMode(U.hConsoleInput, &U.originalConsoleInputMode))
    {
        ErrorExit(TEXT("GetConsoleMode"));
    }

    // Passe la console en mode "Raw"
    EnableRawMode();

    //Lorsque le programme s'arrete on remet la console dans son mode d'origine
    atexit(DisableRawMode);
}

int main()
{
    InitializeConsole();

    while(1)
    {
        UpdateConsoleScreen();
        HandleKeyEvent();
    }

    return(0);
}

/*** TERMINAL : ***/

void EnableRawMode()
{
    DWORD currentInputMode = U.originalConsoleInputMode;

    currentInputMode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS);
    currentInputMode |= ENABLE_VIRTUAL_TERMINAL_INPUT ;
    if (!SetConsoleMode(U.hConsoleInput, currentInputMode))
    {
        ErrorExit(TEXT("SetConsoleMode"));
    }
}

void DisableRawMode()
{
    if (!SetConsoleMode(U.hConsoleInput, U.originalConsoleInputMode))
    {
        ErrorExit(TEXT("SetConsoleMode"));
    }
    if (!SetConsoleMode(U.hConsoleOutput, U.originalConsoleOutputMode))
    {
        ErrorExit(TEXT("SetConsoleMode"));
    }
}

void ErrorExit(LPTSTR lpszFunction)
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
                                      (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    StringCchPrintf((LPTSTR)lpDisplayBuf,
                    LocalSize(lpDisplayBuf) / sizeof(TCHAR),
                    TEXT("%s failed with error %d: %s"),
                    lpszFunction, dw, lpMsgBuf);
    MessageBoxA(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw);
}

void HandleKeyEvent()
{
    char c = ReadInput();

    if (iscntrl(c))
    {
        printf("%d\n", c);
    }
    else
    {
        printf("%d ('%c')\n", c, c);
    }

//    switch (c)
//    {
//    case CTRL_KEY('q'):
//    {
//        ClearConsoleScreen();
//        CursorToOrigin();
//        exit(0);
//        break;
//    }
//    }
}


/*** INPUT : ***/

char ReadInput()
{
    INPUT_RECORD inputRecord;
    DWORD nRead;

    while (1)
    {
        if (!ReadConsoleInput(U.hConsoleInput, &inputRecord, 1, &nRead))
        {
            ErrorExit(TEXT("ReadConsoleInput"));
        }
        if (inputRecord.EventType == KEY_EVENT && inputRecord.Event.KeyEvent.bKeyDown)
        {
            return inputRecord.Event.KeyEvent.uChar.AsciiChar;
        }
    }
}

/*** OUTPUT : ***/

void UpdateConsoleScreen()
{
    ClearConsoleScreen();
    CursorToOrigin();


    CursorToOrigin();
}

void ClearConsoleScreen()
{
    printf(CSI "2J");
}

void CursorToOrigin()
{
    printf(ESC "[0;0H");
}

void DrawRows()
{

}

正如我所说,我将我的代码交给了一个 AI 来查看我是否犯了错误(我不是 Windows API 专家,实际上我是 EE 的学生)并且没有得到任何信息。我还尝试使我的错误处理在

ReadInput()
函数上更加健壮,但它什么也没做所以我删除了它,因为它是一大段冗余的“调试”代码。

c windows winapi console console-application
© www.soinside.com 2019 - 2024. All rights reserved.