C / C ++中的ClearConsole() - 清除控制台的功能

时间:2016-01-07 11:00:07

标签: c++ console clear

我在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>

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

2 个答案:

答案 0 :(得分:1)

我认为

system("cls");更好。

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

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

和控制台缓冲区信息(也可以与微软联系)

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

答案 1 :(得分:0)

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

  1. 用“清晰”字符(即空格)替换屏幕上的所有文本
  2. 用控制台属性替换所有字符属性(前景色/背景色)(认为这是绘画程序中当前选择的颜色,尽管它是为整个程序设置的,但我们仍然需要对所有内容进行绘画)< / li>
  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. 避免每次都重新获取stdout的句柄(使其成为参数)
  2. 避免在发生错误后也丢掉count(也将其作为参数)
  3. 返回(或抛出)更多有用的错误。在这一点上,还没有编程的方法来判断该功能是否成功,更不用说它如何失败了。

供参考: