gpt4 book ai didi

c++ - 如何调整 Windows 10 窗口大小并忽略透明边框?

转载 作者:行者123 更新时间:2023-11-30 05:07:00 24 4
gpt4 key购买 nike

我们的 3d 应用程序窗口需要覆盖用户的整个桌面,包括任务栏(不能调整大小,不能最大化,不能像视频游戏中那样全屏 , 只是一个右上角带有 [X] 的窗口、标题栏和状态栏)。

为此,我们使用了以下代码:

void
CTheApp::SetFullScreenMode()
{
HWND hwnd = getHandle();

long style = ::GetWindowLong(hwnd, GWL_STYLE);
style &= ~(WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_THICKFRAME);
::SetWindowLong(hwnd, GWL_STYLE, style);

// get screen dimensions
int width = ::GetSystemMetrics(SM_CXSCREEN);
int height = ::GetSystemMetrics(SM_CYSCREEN);

::MoveWindow(hwnd, 0, 0, width, height, TRUE);
}

它可以满足我们的需求……直到 Windows 10 到来。

在 Windows 10 中,窗口不会覆盖左侧、右侧和底部的小间隙。 (更准确地说:左边 9 个像素,右边 9 个像素,底部 9 个像素。)

Windows 10 似乎在非最大化窗口的边框上增加了这种透明样式。

如何才能使窗口在 Windows 10 的整个屏幕上在视觉上正确拉伸(stretch)(不留明显间隙),同时保持该功能对以前版本的 Windows(Windows 7 - Windows 8.1)有效?有没有一种干净的方法可以将此“透明度”设置为零?


我考虑过破解它并在每一侧将尺寸扩大 9 个像素,但是当用户设置了另一个主题(例如高对比度)时,或者当应用程序将在多个显示器上使用多个窗口时,这可能会导致问题.

最佳答案

我找到了两种方法来实现这一目标。

通过使用 DwmGetWindowAttribute功能

通过这种方法,我们 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 );
}

这种方法似乎比另一种方法更有效。

通过处理 WM_NCCALCSIZE留言

使用此方法的想法是 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://learn.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% 时,我无法重现此问题。如果典型用法是不移动窗口(我们就是这种情况),这应该不是问题。
  • 我想我不太确定这一切是如何运作的,但似乎有些窗口元素有点不合适。

如果我找不到第一种方法,第二种方法就可以很好地满足我们的需求,即使它有几个问题。


我使用了这些答案(以及其他资源):

关于c++ - 如何调整 Windows 10 窗口大小并忽略透明边框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47679911/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com