windows - C ++ Console - korrekt størrelse forbliver stadig tom plads til rullefelter

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er (lige så mange for mig, jeg har gjort en masse searcing) forsøger at få min konsol til at vise bufferen uden rullefelter. Jeg har ændret vinduet baseret på systemets skrifttypestørrelse og den ønskede bufferstørrelse, men selv efter at du ændret (og opdaterer) konsolens stilflagger, er jeg stadig tilbage med tomme mellemrum, hvor de vandrette og lodrette rullefelter var.


Kan nogen hjælpe mig med dette problem?


#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
";
      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
";
      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
";
      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
";
      return false;
   }

   /// Get handle to console
   HANDLE l\_console\_handle( GetStdHandle( STD\_OUTPUT\_HANDLE ) );
   if( l\_console\_handle == nullptr )
   {
      std::cout << "GetStdHandle() failed
";
      return false;
   }

   /// Get font information
   CONSOLE\_FONT\_INFO l\_font\_info;
   if( !GetCurrentConsoleFont( l\_console\_handle, false, &l\_font\_info ) )
   {
      std::cout << "GetCurrentConsoleFont() failed
";
      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
";
      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
";
      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
";
      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;
}


Billede af konsol med tomme mellemrum hvor rullestænger var [11]

Bedste reference


Da jeg forstod dit spørgsmål, vil du oprette et konsolvindue, der ikke har rullefelter, og det synlige område er nøjagtigt størrelsen på outputskærmbufferen? Sådan kan du gøre dette:


#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;
} 


Dette kræver nogle forklaringer. CONSOLE\_SCREEN\_BUFFER\_INFOEX struktur synes at indeholde alle de parametre, der er nødvendige for at få dette til at ske. Hvis du kontrollerer egenskaber i dit konsolvindue og sammenligner dem med strukturmedlemmer


Indtast billedbeskrivelse her [12]


du finder, at dwSize svarer til Screen Buffer Size, srWindow.Right - srWindow.Left og srWindow.Bottom - srWindow.Top svarer til Window Size.


Hvis dwMaximumWindowSize ikke er indstillet, er den standard til skrivebordets grænser og tilføjer rullestenger, hvis vinduet er større. Det fastsætter også det.


Endelig skal ENABLE\_WRAP\_AT\_EOL\_OUTPUT fjernes fra konsolindstillinger for at stoppe markøren ved at springe til den næste linje i slutningen af ​​linjen og dermed rulle bufferen med det sidste trykte tegn. Jeg har justeret printsløjfen for at tage højde for det.