【问题标题】:ClearConsole() in C/C++ - function which clears consoleC/C++ 中的 ClearConsole() - 清除控制台的函数
【发布时间】:2016-01-07 11:00:06
【问题描述】:

我在 C++ 中发现了一个删除控制台内容的函数。我测试了它并且它有效,但我不明白它。这是函数:

void ClearScreen()
 {
  HANDLE                     hStdOut;
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  DWORD                      count;
  DWORD                      cellCount;
  COORD                      homeCoords = { 0, 0 };
  hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
  if (hStdOut == INVALID_HANDLE_VALUE) return;
  if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
  cellCount = csbi.dwSize.X *csbi.dwSize.Y;
  if (!FillConsoleOutputCharacter(
     hStdOut,
     (TCHAR) ' ',
     cellCount,
     homeCoords,
     &count
     )) return;
  if (!FillConsoleOutputAttribute(
     hStdOut,
     csbi.wAttributes,
     cellCount,
     homeCoords,
     &count
     )) return;
  SetConsoleCursorPosition( hStdOut, homeCoords );
 }

这个函数使用

#include <windows.h>

如果有人可以向我解释它,它是如何工作的,它是否有效并且随时向我建议其他方法来做同样的事情。谢谢!

【问题讨论】:

  • 如果您只想清除命令窗口,那么您可以使用system 方法传递正确的清除命令。在 Windows 上,清除命令是 cls。查看 this 以获取带有 cmets 的代码示例。
  • 如果您有工作代码,请在 SE Code Review 上寻求评论。

标签: c++ console


【解决方案1】:

system("cls"); 我想更好。

您的函数从控制台获取标准输出句柄(与 Microsoft 交谈)

hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); // info stays in hStdOut (HANDLE)

还有控制台缓冲区信息(另外,请咨询 Microsoft)

GetConsoleScreenBufferInfo( hStdOut, &csbi ) // info stays in csbi (CON._SCREEN_BUFFER_INFO)

然后,用' ' 字符(空格)填充当前控制台内容

FillConsoleOutputCharacter(hStdOut, (TCHAR) ' ', cellCount, homeCoords, &count) 
                                                           //count is amount of ' ' filled

重置控制台属性:

FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, cellCount, homeCoords, &count)
// takes info from hStdOut and csbi (cellCount based on csbi), homeCoords is simply {0,0}

并将光标倒回到控制台缓冲区的开头。

SetConsoleCursorPosition(hStdOut, homeCoords );  // sets cursor to {0,0} coords

【讨论】:

  • 谢谢!我将尝试 system("cls") 看看它是如何工作的。祝你有美好的一天!
【解决方案2】:

使用 windows API 清除控制台涉及 3 个主要步骤:

  1. 用“清除”字符(即空格)替换屏幕上的所有文本
  2. 用控制台属性替换所有字符属性(前景色/背景色)(认为这是当前在绘制程序中选择的颜色,虽然它是为整个程序设置的,但我们仍然需要绘制所有内容)
  3. 将光标移回左上角

分别实现:

  • FillConsoleOutputCharacter()
  • FillConsoleOutputAttribute()
  • SetConsoleCursorPosition()

当然,我们仍然需要处理错误和函数签名,但这是高级摘要。

逐行(经过一些轻微的重新格式化):

void clearScreen() {
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); // Get an indentifier (handle) for stdout / the console it's bound to
    if (hStdOut == INVALID_HANDLE_VALUE) return; // Return early if there are any errors (indicated by a specific invalid handle value)
    
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return; // Get some information such as the size (`csbi.dwSize`) and attributes (color) (`csbi.wAttributes`) of the console. Also, return early if there is an error (indicated by a return value of 0)
    
    DWORD cellCount = csbi.dwSize.X * csbi.dwSize.Y; // Total number of cells in the console is width*height
    COORD topLeftCorner = {0, 0};
    DWORD count;
    
    if (!FillConsoleOutputCharacter( // Step 1: Fill all the character cells with spaces
        hStdOut,
        (TCHAR) ' ', // Fill the console with `cellCount` spaces
        cellCount,
        topLeftCorner, // Starting in the top left corner
        &count // `count` will store the number of characters that were filled. If there is an error, this can be used to determine how many weren't, but the way this function is structured means we have to throw it away.
    )) return; // Return early if there is an error
    
    if (!FillConsoleOutputAttribute( // Step 2: Set the cell colors to the console colors
        hStdOut,
        csbi.wAttributes, // Again, think of this as the currently selected color in a paint program. We still need to paint over everything.
        cellCount,
        topLeftCorner,
        &count // Same thing as with `FillConsoleOutputCharacter`
    )) return; // Return early if there is an error
    
    SetConsoleCursorPosition(hStdOut, topLeftCorner); // Step 3: Move the cursor back to the top left corner. No need to return early if there is an error since this is the last function call.
}

顺便说一句,这可能会被重构一下

  1. 避免每次都重新检索标准输出的句柄(使其成为参数)
  2. 避免在出错后丢弃count(也将其设为参数)
  3. 返回(或抛出)更多有用的错误。在这一点上,没有编程方式来判断函数是否成功,更不用说它是如何失败的了。

供参考:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2012-04-22
    • 2013-04-26
    • 2013-01-18
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多