【问题标题】:How to bring std::cout output back to the top after a new line如何在换行后将 std::cout 输出带回顶部
【发布时间】:2021-12-07 13:11:48
【问题描述】:

我有以下菜单,它应该根据用户是否键入键 F1 或 F2 来更新:

int main()
{
    bool f1 = false;
    bool f2 = false;
 
    while (true)    
    {
        std::cout << "[F1]:  " << (f1 ? "ON" : "OFF") << std::endl;
        std::cout << "[F2]:  " << (f2 ? "ON" : "OFF") << std::endl;
        std::cout << "[INS] to quit" << std::endl;

        if (GetAsyncKeyState(VK_INSERT) & 0x1)
            break;

        if (GetAsyncKeyState(VK_F1) & 0x1)
            f1 = !f1;
        
        if (GetAsyncKeyState(VK_F2) & 0x1)
            f2 = !f2;
        
        Sleep(100);
        cleanWindow();
    }

    return 0;
}

现在,我之前使用system("cls"),它工作“正常”,但我被告知我应该使用 Win32 API 来清理控制台,所以我创建了cleanWindow(),如this MSVC article.

DWORD cleanWindow()
{
    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();
    }

    // Write the sequence for clearing the display.
    // \x1b[2J is the code for clearing the screen and set cursor to home
    DWORD written = 0;
    PCWSTR sequence = L"\x1b[2J";
    if (!WriteConsoleW(hStdOut, sequence, (DWORD)wcslen(sequence), &written, NULL))
    {
        // If we fail, try to restore the mode on the way out.
        SetConsoleMode(hStdOut, originalMode);
        return ::GetLastError();
    }

    // To also clear the scroll back, emit L"\x1b[3J" as well.
    // 2J only clears the visible window and 3J only clears the scroll back.

    // Restore the mode on the way out to be nice to other command-line applications.
    SetConsoleMode(hStdOut, originalMode);
}

现在,问题在于“菜单”位于命令提示符的末尾而不是开头,就像 system("cls") 一样:

我的问题是,我该如何解决这个问题?如何将输出带回 shell 的顶部?

编辑:

我还编辑了 cleanWindow() 函数来编写序列:\033[2J 和 L"\033[H" 与 WriteConsoleW(),这有效,但我仍然得到与 system("cls") 一样的“闪烁”效果,这是什么我试图避免。

【问题讨论】:

    标签: c++ winapi


    【解决方案1】:

    您可以在清除后使用SetConsoleCursorPosition将光标位置设置回左上角。

    还有ANSI escape codes(类似于你用来清屏的那个)可以让你重新定位光标。

    "\033[r;cH"
    

    将r 替换为要移动到的行和c 列。它们从 1 开始,默认位于左上角,因此您可以使用 "\033[1;1H" 或仅使用 "\033[H"

    【讨论】:

      猜你喜欢
      • 2011-07-08
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多