我正在使用 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()
函数上更加健壮,但它什么也没做所以我删除了它,因为它是一大段冗余的“调试”代码。