我找到了两种方法来实现这一点。
通过这种方法,我们MoveWindow 两次。我们第一次移动它将定位窗口并计算其所有大小信息。这将使我们能够获得其维度的两个方面。第二次,我们将考虑“投影”边框。为此,我们需要ShowWindow( SW_SHOW );之前我们MoveWindow。
void MyCFrameWndMain::applyWindowSizeAndShow()
{
ShowWindow( SW_SHOW );
int targetWidth = ::GetSystemMetrics( SM_CXSCREEN );
int targetHeight = ::GetSystemMetrics( SM_CYSCREEN );
MoveWindow( 0, 0, targetWidth, targetHeight, TRUE );
RECT decoratedRect;
// This gets the rectangle "with the decoration":
GetWindowRect( &decoratedRect );
RECT leanRECT;
// This gets the rectangle "without the decoration":
::DwmGetWindowAttribute( m_hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &leanRECT, sizeof( leanRECT ) );
int leftDecoration = leanRECT.left - decoratedRect.left;
int rightDecoration = decoratedRect.right - leanRECT.right;
int topDecoration = leanRECT.top - decoratedRect.top;
int bottomDecoration = decoratedRect.bottom - leanRECT.bottom;
// Apparently, the "rectangle without the decoration" still has a 1 pixel border on the sides and
// at the bottom, so we use the GetSystemMetrics to figure out the size of that border, and
// correct the size.
int xBorder = ::GetSystemMetrics( SM_CXBORDER );
int yBorder = ::GetSystemMetrics( SM_CYBORDER );
MoveWindow(
0 - leftDecoration - xBorder
, 0 - topDecoration - yBorder
, targetWidth + leftDecoration + rightDecoration + 2*xBorder
, targetHeight + topDecoration + bottomDecoration + 2*yBorder
, TRUE );
}
这种方法似乎比其他方法效果更好。
使用这种方法,思路是在MoveWindow之前显示出来。
void MyCFrameWndMain::applyWindowSizeAndShow()
{
int targetWidth = ::GetSystemMetrics( SM_CXSCREEN );
int targetHeight = ::GetSystemMetrics( SM_CYSCREEN );
MoveWindow( 0, 0, targetWidth, targetHeight, TRUE );
ShowWindow( SW_SHOW );
}
然后处理WM_NCCALCSIZE消息:
LRESULT MyCFrameWndMain::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// ...
case WM_NCCALCSIZE:
{ // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize?redirectedfrom=MSDN
int titleBarHeight = ::GetSystemMetrics( SM_CYCAPTION );
if ( wParam == TRUE )
{
NCCALCSIZE_PARAMS* params = reinterpret_cast<NCCALCSIZE_PARAMS*>( lParam );
params->rgrc[0].top = titleBarHeight;
return WVR_REDRAW;
}
else //if ( wParam == FALSE )
{
RECT* rect = reinterpret_cast<RECT*>( lParam );
rect->top = titleBarHeight;
return 0;
}
}
break;
// ...
}
}
我发现使用这种方法的缺点:
- 在窗口的上边缘和屏幕的上边缘之间有一像素线
- 当我有两台未使用相同缩放比例的显示器(例如,主显示器为 150%,第二台为 100%)时,当我使用标题栏将窗口从一台显示器拖动到另一台显示器时,标题栏会消失,一切都会一团糟。当两者都为 100% 时,我无法重现此问题。当典型用法是不移动窗口(我们的例子)时,这应该不是问题。
- 我想我不太确定这一切是如何工作的,但似乎某些窗口元素有点不合适。
如果我没有找到第一种方法,那么第二种方法可以很好地满足我们的需求,即使它有几个问题。
我已经使用了这些答案(以及其他资源):