Can't center my console window by using the following code

杀马特。学长 韩版系。学妹 提交于 2021-02-08 12:01:50

问题


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?


回答1:


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);



回答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.



来源:https://stackoverflow.com/questions/42905649/cant-center-my-console-window-by-using-the-following-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!