草庐IT

C++ 控制台 - 适当大小仍然为滚动条留下空白空间

coder 2024-06-14 原文

我(和我之前的许多人一样,做了很多搜索)试图让我的控制台显示没有滚动条的缓冲区。我根据系统字体大小和请求的缓冲区大小调整了窗口大小,但即使在更改(和更新)控制台的样式标志之后,水平和垂直滚动条所在的位置仍然留有空白。

谁能帮我解决这个问题?

#include <windows.h>
#include <iostream>

const bool adjustWindowSize( const unsigned int p_console_buffer_width, 
const unsigned int p_console_buffer_height )
{
   /// Get the handle to the active window
   HWND l_window_handle( GetConsoleWindow() );
   if( l_window_handle == NULL )
   {
      std::cout << "GetConsoleWindow() failed\n";
      return false;
   }

   /// Get the dimensions of the active window
   RECT l_window_rect;
   if( !GetWindowRect( l_window_handle, &l_window_rect ) )
   {
      std::cout << "GetWindowRect() failed\n";
      return false;
   }

   /// Remove unwanted WindowStyle flags
   LONG l_style( GetWindowLong( l_window_handle, GWL_STYLE ) );
   l_style &= ~( WS_VSCROLL | WS_HSCROLL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | 
                 WS_SIZEBOX );
   SetWindowLong( l_window_handle, GWL_STYLE, l_style );

   /// Set new window size to update the style flags
   if( !SetWindowPos( l_window_handle, HWND_TOP, l_window_rect.left, 
                      l_window_rect.top, l_window_rect.right - 
                      l_window_rect.left, l_window_rect.bottom - 
                      l_window_rect.top, SWP_HIDEWINDOW ) )
   {
      std::cout << "SetWindowPos() failed\n";
      return false;
   }

   /// Get the dimensions of the client area within the window's borders
   RECT l_client_rect;
   if( !GetClientRect( l_window_handle, &l_client_rect ) )
   {
      std::cout << "GetClientRect() failed\n";
      return false;
   }

   /// Get handle to console
   HANDLE l_console_handle( GetStdHandle( STD_OUTPUT_HANDLE ) );
   if( l_console_handle == nullptr )
   {
      std::cout << "GetStdHandle() failed\n";
      return false;
   }

   /// Get font information
   CONSOLE_FONT_INFO l_font_info;
   if( !GetCurrentConsoleFont( l_console_handle, false, &l_font_info ) )
   {
      std::cout << "GetCurrentConsoleFont() failed\n";
      return false;
   }

   /// Prepare desired client area size
   unsigned int l_target_width(  l_font_info.dwFontSize.X * 
                                 p_console_buffer_width );
   unsigned int l_target_height( l_font_info.dwFontSize.Y * 
                                 p_console_buffer_height );

   POINT l_top_left;
   l_top_left.x = l_client_rect.left;
   l_top_left.y = l_client_rect.top;
   ClientToScreen( l_window_handle, &l_top_left );

   POINT l_bottom_right;
   l_bottom_right.x = l_client_rect.right;
   l_bottom_right.y = l_client_rect.bottom;
   ClientToScreen( l_window_handle, &l_bottom_right );

   unsigned int l_diff_x = l_window_rect.right - l_bottom_right.x + 
                           l_top_left.x - l_window_rect.left;
   unsigned int l_diff_y = l_window_rect.bottom - l_bottom_right.y + 
                           l_top_left.y - l_window_rect.top;

   /// Adjust window to fit exactly it's borders + the new client size
   l_window_rect.right = l_target_width + l_diff_x;
   l_window_rect.bottom = l_target_height + l_diff_y;

   /// Set new window size
   if( !SetWindowPos( l_window_handle, HWND_TOP, l_window_rect.left, 
                      l_window_rect.top, l_window_rect.right, 
                      l_window_rect.bottom, SWP_SHOWWINDOW ) )
   {
      std::cout << "SetWindowPos() failed\n";
      return false;
   }

   /// Set new console buffer size
   if( !SetConsoleScreenBufferSize( l_console_handle,
                                    COORD( { (SHORT)p_console_buffer_width, 
                                    (SHORT)p_console_buffer_height } ) ) )
   {
      std::cout << "SetConsoleScreenBufferSize() failed\n";
      return false;
   }

   return true;
}

int main()
{
   SetConsoleTitle( (LPCSTR)"Console Test" );

   unsigned int l_buffer_x( 100 );
   unsigned int l_buffer_y( 40 );

   if( !adjustWindowSize( l_buffer_x, l_buffer_y ) )
   {
      std::cout << "adjustWindowSize() failed\n";
      return 1;
   }

   for( unsigned int i( 0 ); i < l_buffer_x * l_buffer_y; ++i )
   {
      std::cout << i % 10;
   }

   SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ),
                             COORD( { 0, 0 } ) );

   return 0;
}

Picture of console with empty spaces where scroll bars were

最佳答案

据我了解你的问题,你想创建没有滚动条的控制台窗口,可见区域正好是输出屏幕缓冲区的大小?这是您可以执行此操作的方法:

#include <windows.h>
#include <iostream>

void SetConsoleWindow(HANDLE conout, SHORT cols, SHORT rows)
{
    CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx;
    sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    GetConsoleScreenBufferInfoEx(conout, &sbInfoEx);
    sbInfoEx.dwSize.X = cols;
    sbInfoEx.dwSize.Y = rows;
    sbInfoEx.srWindow = { 0, 0, cols, rows };
    sbInfoEx.dwMaximumWindowSize = { cols, rows };
    SetConsoleScreenBufferInfoEx(conout, &sbInfoEx);

    DWORD mode;
    GetConsoleMode(conout, &mode);
    mode &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
    SetConsoleMode(conout, mode);

    SetConsoleTitle(L"Console Test");
}

int main()
{
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    SHORT cols = 100, rows = 20;
    SetConsoleWindow(out, cols, rows);

    for (int y = 0; y < rows; ++y)
    {
        for (int x = 0; x < cols; ++x)
            std::cout << y %10;

        if (y < rows - 1)
            std::cout << std::endl;
    }

    SetConsoleCursorPosition(out, { 0,0 });

    return 0;
} 

这需要一些解释。 CONSOLE_SCREEN_BUFFER_INFOEX 结构似乎包含实现此目的所需的所有参数。如果您检查控制台窗口的属性并将它们与结构成员进行比较

您发现 dwSize 对应于 Screen Buffer SizesrWindow.Right - srWindow.LeftsrWindow.Bottom - srWindow .Top 对应Window Size.

如果未设置 dwMaximumWindowSize,则默认为桌面边界,如果窗口较大则添加滚动条。设置它也可以解决这个问题。

最后,ENABLE_WRAP_AT_EOL_OUTPUT 需要从控制台选项中删除,以停止光标跳转到行尾的下一行,从而使用最后打印的字符滚动缓冲区。我已经调整了打印循环来解决这个问题。

关于C++ 控制台 - 适当大小仍然为滚动条留下空白空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50415627/

有关C++ 控制台 - 适当大小仍然为滚动条留下空白空间的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  4. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  5. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  8. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

随机推荐