How to get the "output" (console screen buffer) Handle for GetConsoleMode() in Windows?

huangapple go评论52阅读模式
英文:

How to get the "output" (console screen buffer) Handle for GetConsoleMode() in Windows?

问题

我想在输入和输出上都使用 GetConsoleMode(),因为我想要更改一些标志。

输入部分相对来说比较简单:

HANDLE hStdin;
DWORD fdwSaveOldMode;

hStdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hStdin, &fdwSaveOldMode);

然而,输出部分似乎不那么简单。人们可能会认为只需使用 STD_OUTPUT_HANDLE 就足够了,但"帮助"页面提到需要创建和设置自己的缓冲区。

此外,有一篇关于句柄的页面提到:

在调用 CreateFile 时,使用 CONOUT$ 值来打开控制台的活动屏幕缓冲区的句柄。

这听起来像一个线索,但坦白地说,我不确定这是什么意思。有人能向我展示如何正确操作吗?为什么输出与输入如此不同?

谢谢!

英文:

I want to do GetConsoleMode() on both input and output because I want to change some flags.

Input is pretty straightforward:

HANDLE hStdin;
DWORD fdwSaveOldMode;

hStdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hStdin, &fdwSaveOldMode)

The output, on the other hand, doesn't seem as easy. One would think that just putting STD_OUTPUT_HANDLE would be enough, but the "help" pages talk about having to make and set your own buffer.

This, and a page about handles mention:
> Specify the CONOUT$ value in a call to CreateFile to open a handle to a console's active screen buffer.

Sounds like a clue, but frankly, I'm unsure what this even means. Can someone show me how to do it properly? Why is output so different than input?

Thank you!

答案1

得分: 1

一个人可能会认为只需使用STD_OUTPUT_HANDLE就足够了。

确实如此。"清屏示例" (https://learn.microsoft.com/en-us/windows/console/clearing-the-screen) 中有一个代码片段演示了如何设置控制台输出模式,它使用了GetStdHandle()

HANDLE hStdOut;

hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

// 获取现有的控制台模式,以便正确添加一个标志而不关闭其他标志
DWORD mode = 0;
if (!GetConsoleMode(hStdOut, &mode))
{
    return ::GetLastError();
}

// 保留原始模式,以便在退出时还原,以便与其他命令行应用程序协作
const DWORD originalMode = mode;
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;

// 尝试设置模式
if (!SetConsoleMode(hStdOut, mode))
{
    return ::GetLastError();
}

在某些情况下,GetStdHandle 与特定于控制台的函数一起使用可能不起作用,这些情况包括应用程序不是控制台模式(您可以通过调用AllocConsole在 GUI 模式应用程序中获取控制台),或者 stdout 被重定向。

在这些情况下,您需要通过CreateFile打开一个控制台句柄,使用特殊的文件名"CONOUT$"。这将始终访问一个控制台,如果与您的进程关联了一个控制台,即使stdout未映射到该控制台。

英文:

> One would think that just putting STD_OUTPUT_HANDLE would be enough

It is. The "Clearing the Screen" example has a snippet demonstrating setting console output modes, and it uses GetStdHandle():

> HANDLE hStdOut;
>
> hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
>
> // Fetch existing console mode so we correctly add a flag and not turn off others
> DWORD mode = 0;
> if (!GetConsoleMode(hStdOut, &mode))
> {
> return ::GetLastError();
> }
>
> // Hold original mode to restore on exit to be cooperative with other command-line apps.
> const DWORD originalMode = mode;
> mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
>
> // Try to set the mode.
> if (!SetConsoleMode(hStdOut, mode))
> {
> return ::GetLastError();
> }

Some cases where GetStdHandle wouldn't work together with console-specific functions would be if the application isn't console-mode (you can get a console in a GUI-mode application by calling AllocConsole) or if stdout was redirected.

In those cases, you'd need to open a console handle via CreateFile and the special filename "CONOUT$". That will always access a console, if one is associated with your process, even in case stdout is not mapped to that console.

huangapple
  • 本文由 发表于 2023年2月9日 00:28:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定