【发布时间】:2022-02-08 00:34:04
【问题描述】:
所以我在win32 c++中创建了一个全屏功能:
uint8_t isFullscreen = 0;
RECT winRect; //Current Window Rect
RECT nonFullScreenRect; //Rect Not In Full Screen Position (used to restore window to not full screen position when coming out of fullscreen)
uint32_t screen_width = DEFAULT_SCREEN_WIDTH;
uint32_t screen_height = DEFAULT_SCREEN_HEIGHT;
void Fullscreen( HWND WindowHandle )
{
isFullscreen = isFullscreen ^ 1;
if( isFullscreen )
{
//saving off current window rect
nonFullScreenRect.left = winRect.left;
nonFullScreenRect.right = winRect.right;
nonFullScreenRect.bottom = winRect.bottom;
nonFullScreenRect.top = winRect.top;
SetWindowLongPtr( WindowHandle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE ); //causes a resize msg
HMONITOR hmon = MonitorFromWindow(WindowHandle, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof( mi ) };
GetMonitorInfo( hmon, &mi );
screen_width = mi.rcMonitor.right - mi.rcMonitor.left;
screen_height = mi.rcMonitor.bottom - mi.rcMonitor.top;
MoveWindow( WindowHandle, mi.rcMonitor.left, mi.rcMonitor.top, (int32_t)screen_width, (int32_t)screen_height, FALSE );
}
else
{
SetWindowLongPtr( WindowHandle, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE );
screen_width = nonFullScreenRect.right - nonFullScreenRect.left;
screen_height = nonFullScreenRect.bottom - nonFullScreenRect.top;
MoveWindow( WindowHandle, nonFullScreenRect.left, nonFullScreenRect.top, (int32_t)screen_width, (int32_t)screen_height, FALSE );
}
}
但是,当它进入全屏时,该函数会生成 2 个 WM_SIZE 消息。而当它打开窗口时,它只生成 1。
为什么会这样?我怎样才能让它只为正确的全屏尺寸生成 1 条 WM_SIZE 消息?
How can I update an HWND's style and position atomically? 询问但没有人回答
我需要这个的原因是因为我使用的是 DirectX12,并且在 WM_SIZE 上,我在调整所有交换链后台缓冲区的大小之前等待命令队列末尾的所有信号。而且我不想在切换到全屏模式时调整交换链的大小两次。
case WM_SIZE:
{
screen_width = LOWORD( LParam );
screen_height = HIWORD( LParam );
//DirectX stuff here
}break;
提前致谢!
【问题讨论】:
-
isFullscreen = isFullscreen ^ 1;- 只有游戏开发者才会编写这样的代码。 :) 除此之外,通过检测您的第二个 WM_SIZE 与前一个 WM_SIZE 的宽度/高度相同,什么问题不能解决?或者您是否收到两条不同参数的 WM_SIZE 消息? -
@selbie 但它的高度和宽度与前一个不同。它几乎就像在一种情况下 SetWindowLongPtr 导致 WM_SIZE。但这两种情况都不是。但我不知道 SetWindowLongPtr 是否真的在生成消息
-
我在 WM_SIZE 中放置了一个打印语句当窗口化时:
Old: 1280 720 New: 1264 681。 When Going fullscreenOld: 1264 681 New: 1280 720Old: 1920 1080 New: 1920 1080注意全屏函数也设置了 screen_width 和 screen_height 全局变量 -
您似乎忽略了documentation 的一部分:“某些窗口数据已被缓存,因此您使用
SetWindowLongPtr所做的更改在您调用SetWindowPos函数之前不会生效." 我相信窗口边框是“某些窗口数据” 的一部分。尝试将您的MoveWindow呼叫替换为对SetWindowPos的呼叫。我不知道这是否能解决您当前的问题,但这是您需要解决的问题。 -
@IInspectable 当我切换到 SetWindowPos 时,它不再让我 Alt-Tab 退出程序(也许我必须手动处理?)。也仍然调用它两次。我将不得不做更多的调查。也许我的程序中的其他东西正在生成 2 条消息。
标签: winapi visual-c++ fullscreen directx-12