使用以下代码无法使我的控制台 window 居中

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

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

我正在尝试使用上面的代码将我的控制台 window 居中,但似乎 window 只是在我每次执行程序时移动到屏幕上的随机位置,任何知道如何解决吗?

您需要 (GetSystemMetrics(SM_CXSCREEN) - (rConsole.right - rConsole.left))/2 才能居中。


旁注:您可以使用一个 SetWindowPos 而不是两个(并且不需要获取 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);

不要为此使用 GetSystemMetrics(),因为它仅 returns 主要 监视器的指标。如今,多显示器设置非常普遍,因此如果您忽略它,用户会很不高兴。

此外,window通常不应与物理监视器表面对齐,而应与工作区对齐其中不包括任务栏。是的,可以有多个任务栏(称为“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.

为了涵盖这两个方面,我们可以使用 MonitorFromWindow() and GetMonitorInfo()

首先我们从 window 句柄中获取 "nearest" 监视器。这是完全显示 window 或 window 面积最大的显示器:

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

然后我们得到那个显示器的工作区矩形,并使 window 相对于它居中:

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

就是这样。在实际应用程序中,您当然不应该对 window 大小进行硬编码,因为这是用户偏好。对于首次启动,默认大小可能是合理的,但即使这样也不应该硬编码,而是根据 Windows DPI 设置进行缩放。