【问题标题】:How to do a C# Windows Console application that "respects" previous console content?如何做一个“尊重”以前控制台内容的 C# Windows 控制台应用程序?
【发布时间】:2013-02-06 11:48:41
【问题描述】:

就像 Vim:当它启动时,它会将你带到另一个“缓冲区”。当 vim 关闭时,用户会看到命令提示符之前的内容。

有人知道如何使用 C# 做到这一点吗?

谢谢

编辑:用户将不再看到应用程序的输出。希望能更好地解释它。

【问题讨论】:

  • 您描述的示例是如果从命令行调用 C# 控制台应用程序当前将如何工作;如果您执行控制台应用程序,然后将其关闭,您将返回到之前的命令行。还是我错过了什么?
  • 我认为海报的意思是应用程序的任何输出都不应再出现在控制台上,而是执行前的内容。
  • @Richard 像 dir 或 cat 这样的应用程序将在同一个控制台“缓冲区”上喷射。 vim 之类的应用程序会在控制台窗口上重绘大量文本,但在关闭它后,用户会返回查看他或她键入的命令,包括 vim。 vim 放在窗口上的所有输出都消失了。如果我没有正确解释自己,请告诉我
  • 你的解释很好,但是还没有人看懂!对不起,我没有建议给你。。
  • @robertoprs 哦,我明白你的意思了,是的,对不起,我误解了你的问题。我不知道你有什么方法可以在原生 C# 中做到这一点,你可能不得不通过 PInvoke 深入研究 Windows API,很抱歉我帮不上忙。

标签: c# .net windows console


【解决方案1】:

我相信 Vim 会记录其打开文件的历史记录,并且很可能还会缓冲它们,就像备份副本一样。在 C# 中做同样的事情的想法是实现一个文件缓冲区,一种可以记录和跟踪你想要的东西的存储 - 输入参数等。

这里的另一个问题是 Vim(如 Vi)具有命令模式,这也需要在 C# 中实现。现在这取决于你想用你的 C# 程序完成什么,那是一个编辑器,那么好吧,无论如何,你必须区分命令和其他模式。

【讨论】:

  • 这与问题关系不大。
  • 我相信 OP 的问题在黑暗中有点被击中 - 根本不容易理解。我回答了我认为是正确的。
  • 这个问题对我来说很有意义。打开命令提示符。启动vim。注意 vim 如何出现在同一个窗口中。退出 vi。注意一点 vim 是如何保持可见的。现在的问题是如何从 C# 中实现这一点。
  • 好吧,如果是这样的话,那么它与 Vim 无关,而是与终端本身有关。
【解决方案2】:

您可以通过将旧内容写入控制台缓冲区来实现,如下所述:How can I write fast colored output to Console?

【讨论】:

  • ..你打算如何获取旧内容?
  • 我对此表示赞同,因为我发现它很有用。我不知道 PInvoke,所以我不知道我可以从 C# 代码调用 Win32 API。多亏了这个,我找到了 CreateConsoleScreenBuffer。贾斯汀的回答更详细,但这足以解除对我的阻止。
【解决方案3】:

我通过查看Vim source code 发现了这一点,相关位可以在 os_win32.c 中的mch_init 函数中找到,我已在此处复制并粘贴相关位

    /* Obtain handles for the standard Console I/O devices */
    if (read_cmd_fd == 0)
    g_hConIn =  GetStdHandle(STD_INPUT_HANDLE);
    else
    create_conin();
    g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE);

#ifdef FEAT_RESTORE_ORIG_SCREEN
    /* Save the initial console buffer for later restoration */
    SaveConsoleBuffer(&g_cbOrig);
    g_attrCurrent = g_attrDefault = g_cbOrig.Info.wAttributes;
#else
    /* Get current text attributes */
    GetConsoleScreenBufferInfo(g_hConOut, &csbi);
    g_attrCurrent = g_attrDefault = csbi.wAttributes;
#endif
    if (cterm_normal_fg_color == 0)
    cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1;
    if (cterm_normal_bg_color == 0)
    cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1;

    /* set termcap codes to current text attributes */
    update_tcap(g_attrCurrent);

    GetConsoleCursorInfo(g_hConOut, &g_cci);
    GetConsoleMode(g_hConIn,  &g_cmodein);
    GetConsoleMode(g_hConOut, &g_cmodeout);

#ifdef FEAT_TITLE
    SaveConsoleTitleAndIcon();
    /*
     * Set both the small and big icons of the console window to Vim's icon.
     * Note that Vim presently only has one size of icon (32x32), but it
     * automatically gets scaled down to 16x16 when setting the small icon.
     */
    if (g_fCanChangeIcon)
    SetConsoleIcon(g_hWnd, g_hVimIcon, g_hVimIcon);
#endif

所以它只是保存控制台信息(包括标题和图标),然后在退出时再次恢复。

不幸的是,Console 类不提供对屏幕缓冲区内容的访问,因此您需要 P/Invoke 到相关的 Win32 函数中。

或者,Win32 控制台实际上支持multiple screen buffers,这可能是一种更简单的实现方式——而不是复制现有的屏幕缓冲区,只需使用CreateConsoleScreenBuffer 创建一个新的缓冲区,并将该缓冲区设置为当前显示的缓冲区。 SetConsoleActiveScreenBuffer。同样不幸的是,Console 类不支持多个屏幕缓冲区,因此您需要 P/Invoke 来执行此操作。此外,Console 类始终写入应用程序启动时处于活动状态的屏幕缓冲区,因此如果您换出活动屏幕缓冲区,Console 类仍将写入旧屏幕缓冲区(不是更长时间可见) - 要解决此问题,您需要 P/Invoke 所有控制台访问权限,请参阅Working with Console Screen Buffers in .NET

【讨论】:

  • 谢谢!你是对的,我应该看看代码。我忘记了一些项目即使在 Windows 世界中仍然是开源的。由于 jgauffin 的回答,我碰到了 CreateConsoleScreenBuffer,但是保存前一个缓冲区的状态是个好主意!
  • 原来保存原始缓冲区内容是必要的,因为当缓冲区不活动时它会被清除。
猜你喜欢
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
相关资源
最近更新 更多