繁体   English   中英

控制台模拟器之间的 Win32 控制台行为不一致 API

[英]Inconsistent behavior with Win32 Console API between console emulator

有人可以告诉我以下代码片段中我做错了什么吗?

问题是这个片段,它应该打印“Hello, World!” with colors 在cmder中以 cmd.exe 作为 shell 运行时完全符合预期,但在本机 cmd.exe 终端模拟器或本机 PowerShell 模拟器中使用时完全损坏。 具体来说就是背景颜色变了,reset也不管用。

#include <windows.h>
#include <io.h>
#include <conio.h>
#include <fileapi.h>

#include <assert.h>
#include <stdio.h>

typedef struct {
  HANDLE h;
  HANDLE hin;
  WORD savedAttr;
} Terminal;

#define FOREGROUND_RGB (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN)
#define BACKGROUND_RGB (BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN)
#define TRY_OS(expr) if ((expr) == 0) { osError(); }
#define TRY_OR(expr) if ((expr) == 0)

static WORD get_text_attributes(Terminal term)
{
  CONSOLE_SCREEN_BUFFER_INFO c;

  TRY_OR(GetConsoleScreenBufferInfo(term.h, &c)) {
    return 0x70;
  }

  return c.wAttributes;
}

Terminal getHandle(FILE* in, FILE* out)
{
  Terminal term;

  if ((in == stdin) && (out == stdout)) {
    // grab the current console even if stdin/stdout have been redirected
    term.h =
        CreateFile("CON", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                   0, 0);
    term.hin =
        CreateFile("CON", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
                   0);
    // term.h = GetStdHandle(STD_OUTPUT_HANDLE);
    // term.hin = GetStdHandle(STD_INPUT_HANDLE);
  } else {
    term.h = (HANDLE) _get_osfhandle(_fileno(out));
    term.hin = (HANDLE) _get_osfhandle(_fileno(in));
  }

  term.savedAttr = get_text_attributes(term);
  return term;
}

void setFG(Terminal term, int color)
{
  WORD attr = get_text_attributes(term);
  attr &= ~FOREGROUND_RGB;  // clear FG color
  attr &= ~FOREGROUND_INTENSITY;  // clear FG intensity
  attr |= color;

  SetConsoleTextAttribute(term.h, attr);
}

void setBG(Terminal term, int color)
{
  WORD attr = get_text_attributes(term);
  attr &= ~BACKGROUND_RGB;  // clear BG color
  attr &= ~BACKGROUND_INTENSITY;  // clear BG intensity
  attr |= color;

  SetConsoleTextAttribute(term.h, attr);
}

int main()
{
  Terminal term = getHandle(stdin, stdout);

  setFG(term, FOREGROUND_RED);
  WriteConsole(term.h, "Hello, ", 7, NULL, NULL);

  setFG(term, FOREGROUND_BLUE);
  WriteConsole(term.h, "World !\r\n", 9, NULL, NULL);

  // reset style
  SetConsoleTextAttribute(term.h, term.savedAttr);

  return 0;
}

我想我在使用 API 时做错了什么,cmder 对此比较宽松,但我是通过阅读 Microsoft 官方文档来编写整个代码的,所以我有点困惑。

我建议您可以尝试使用Multi-Byte Character Set而不是Unicode Character Set

在此处输入图像描述

或者您可以尝试使用宽字符文字,例如:

    term.h =
        CreateFile(L"CON", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
            0, 0);
    term.hin =
        CreateFile(L"CON", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,

.

WriteConsole(term.h, L"Hello, ", 8, NULL, NULL);

.

WriteConsole(term.h, L"World !\n\r", 9, NULL, NULL);

编辑:

用 cmd 运行的结果: 在此处输入图像描述

用visual studio运行结果: 在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM