-1
void Initialize_Window(void)
{
    RECT rConsole;
    GetWindowRect(GetConsoleWindow(), &rConsole);
    SetWindowPos(GetConsoleWindow(), NULL, 0, 0, 800, 700, 0);
    SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX));
    SetWindowPos(GetConsoleWindow(), NULL, (GetSystemMetrics(SM_CXSCREEN) - rConsole.right - rConsole.left) / 2, (GetSystemMetrics(SM_CYSCREEN) - rConsole.bottom - rConsole.top) / 2, 0, 0, SWP_NOSIZE);
}

I'm trying to center my console window by using the code above, but seems like the window just moved to a random position on my screen every time I execute the program, any idea how to fix it?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
marticztn
  • 170
  • 1
  • 9

2 Answers2

2

You need (GetSystemMetrics(SM_CXSCREEN) - (rConsole.right - rConsole.left))/2 to get center.


Side note: you can use one SetWindowPos instead of two (and do not need to get window Rect)

const int width = 800;
const int height = 700;
//SetWindowLong()...
SetWindowPos(GetConsoleWindow(), NULL,
   GetSystemMetrics(SM_CXSCREEN)/2 - width/2,
   GetSystemMetrics(SM_CYSCREEN)/2 - height/2,
   width, height, SWP_SHOWWINDOW);
apple apple
  • 10,292
  • 2
  • 16
  • 36
  • Now it's not moving anymore but still not centered – marticztn Mar 20 '17 at 14:25
  • 1
    @BaronZhu Could you tell more about *not centered*? Where is it now? – apple apple Mar 20 '17 at 14:27
  • It's centered vertically, but not horizontally, lower position from the center – marticztn Mar 20 '17 at 14:31
  • I have no idea. Do you remember to also change the Y statement? – apple apple Mar 20 '17 at 14:36
  • const int variable worked, now it's centered, appreciate it! – marticztn Mar 20 '17 at 14:50
  • Your solution centers the window only on the *primary* monitor and does not take size and position of the taskbar(s) into account. A more generic solution would center the window on the *work area* of the *nearest* monitor (see [MonitorFromWindow()](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145064(v=vs.85).aspx) and [GetMonitorInfo()](https://msdn.microsoft.com/en-us/library/windows/desktop/dd144901(v=vs.85).aspx)) . – zett42 Mar 21 '17 at 17:45
  • @zett42 Thanks for the information, but I think my answer is enough for the OP, and I also give the main reason why OP's code not work (use `-` instead of `+`). If you downvote me, I think it's not fair. – apple apple Mar 22 '17 at 07:02
  • Your answer only fixes a single problem of OP's code. This may be enough to make the code *appear* to work on OP's machine but it's not a good general solution for centering a window. As such it is neither useful for OP in the long term nor for any people coming to SO in search for a generic answer. I think that's a fair reason for downvote. – zett42 Mar 22 '17 at 20:18
2

Don't use GetSystemMetrics() for this because it only returns the metrics of the primary monitor. Multi monitor setups are quite common these days so users will be rightly upset if you ignore that.

In addition, a window normally should not be aligned to the physical monitor surface, but to the work area which excludes the taskbar(s). Yes, there can be multiple taskbars (called "appbars" in Windows slang) on either side of the screen. An exception where you would actually use the full physical surface are full screen windows.

To cover both aspects we can use MonitorFromWindow() and GetMonitorInfo().

First we get the "nearest" monitor from the window handle. This is the monitor that either shows the window completely or that has the biggest area of the window on it:

HWND hConsoleWnd = ::GetConsoleWindow();
HMONITOR hMonitor = ::MonitorFromWindow( hConsoleWnd, MONITOR_DEFAULTTONEAREST );

Then we get the work area rectangle of that monitor and center the window relative to that:

if( hMonitor ) 
{
    MONITORINFO info{ sizeof(info) }; // set cbSize member and fill the rest with zero
    if( ::GetMonitorInfo( hMonitor, &info ) )
    {
        int width = 800;
        int height = 700;
        int x = ( info.rcWork.left + info.rcWork.right ) / 2 - width / 2;
        int y = ( info.rcWork.top + info.rcWork.bottom ) / 2 - height / 2;

        ::SetWindowPos( hConsoleWnd, nullptr, x, y, width, height,
                        SWP_NOZORDER | SWP_NOOWNERZORDER );
    }
}

That's it. In a real-world application you should of course not hardcode the window size because it is a user preference. For first launch a default size can be reasonable but even that should not be hardcoded but scaled according to the Windows DPI settings.

zett42
  • 25,437
  • 3
  • 35
  • 72