在Windows OpenGL应用程序中是否有一种优雅的方式来处理在全屏和窗口模式之间切换
Is there a graceful way to handle toggling between fullscreen and windowed mode in a Windows OpenGL application?
我想知道是否有可能在OpenGL窗口(我使用c++和win32为Windows编写)的全屏模式和窗口模式之间来回切换,而不破坏OpenGL上下文,因此必须在此过程中重新加载资产(纹理,VBOs等)?
这是不可取的,因为它引入了在全屏和窗口模式之间切换的延迟,可能是一个很长的延迟,以及使忘记重新初始化的东西更容易把事情搞砸。
接下来,这样做是否会破坏某些视觉效果?
在过去的几天里,我做了相当多的搜索和阅读,尽管有很多燃烧的SDL和其他框架有同样的问题(我不管怎样都不使用它们,但是…),我设法找到的最好的是在后台打开一个1x1窗口以保留上下文,而次要窗口被摧毁或随意创建的可能的线索。从我找到的关于它的评论来看,这似乎是不可靠的,而且看起来非常笨拙。
是否有一个正确的方法来做到这一点,或者是正确的方式,经常给出的一个例子的方法销毁你的窗口,并重新创建它,包括销毁你的OpenGL上下文和重新创建它?
基本上就是调整窗口的大小并指定边框不可见的标志。
SetWindowLongPtr(hWnd, GWL_STYLE,
WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
MoveWindow(hWnd, 0, 0, width, height, TRUE);
设置:
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
或对于不可调整大小的窗口:
SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
然后调整你的OpenGL视口设置。
如果你也想设置显示模式,使用:
// change display mode if destination mode is fullscreen
if (fullscreen) {
DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmBitsPerPel = bitsPerPixel;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
success = ChangeDisplaySettings(&dm, 0) == DISP_CHANGE_SUCCESSFUL;
}
// reset display mode if destination mode is windowed
if (!fullscreen)
success = ChangeDisplaySettings(0, 0) == DISP_CHANGE_SUCCESSFUL;
这是我使用的代码,它使用SetWindowPos()
而不是MoveWindow()
,正如在另一个答案的评论中讨论的那样。
void enter_fullscreen(application* App)
{
POINT Point = {0};
HMONITOR Monitor = MonitorFromPoint(Point, MONITOR_DEFAULTTONEAREST);
MONITORINFO MonitorInfo = { sizeof(MonitorInfo) };
if (GetMonitorInfo(Monitor, &MonitorInfo)) {
DWORD Style = WS_POPUP | WS_VISIBLE;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0, MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.top,
MonitorInfo.rcMonitor.right - MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.bottom - MonitorInfo.rcMonitor.top,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
App->IsFullscreen = true;
}
void exit_fullscreen(application* App)
{
bool WasMaximized = App->IsMaximized;
DWORD Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
if (WasMaximized) {
Style = Style | WS_MAXIMIZE;
}
ivec2 WindowPosition = WasMaximized ? App->WindowPosition : App->NormalWindowPosition;
ivec2 WindowSize = WasMaximized ? App->WindowSize : App->NormalWindowSize;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0,
WindowPosition.X, WindowPosition.Y, WindowSize.X, WindowSize.Y,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
App->IsFullscreen = false;
}
我在F11上调用它,但在WM_ACTIVATE
上也调用它。否则,即使其他应用程序接收到所有消息(包括鼠标和键盘),该窗口有时也会在Windows 7上保持顶部呈现。
相关文章:
- 我可以使用哪种数据结构来处理这种方式
- 如何编写具有相同名称的相同函数,该函数在C++中几乎以相似的方式处理不同的类参数?
- clang++ 是否以更轻松的方式处理系统标头?
- 如何以这种方式处理字符串数组
- 处理无法按预期方式创建的对象,c++
- 跨平台套接字发送,Linux 上的缓冲区常量无效* Windows上的常量字符*,最佳处理方式
- 识别指针处理方式中的错误
- 为什么在指针和数组的情况下,字符数组的处理方式不同
- 为什么这些函数签名的处理方式不同?
- G++ 和 boost 中 regex_replace() 替换字符串中''的不同处理方式
- 常量标识符在C++中有不同的处理方式吗
- 在 C++ 中,get() 和 getline() 对换行符的处理方式不同
- 为什么Visual Studio在调试时对ANSI Escape代码有不同的处理方式
- 在处理回调函数时,通常的异常处理方式是什么?
- 为什么未初始化的const成员在C和c++中的处理方式不同?
- 定义和处理方式不同
- 你能把一个异常继承层次结构包装到另一个吗?——或者,另一种干净的处理方式
- GCC 3.42和VC2008对std::transform的处理方式不同,接受函子的引用或副本
- NaN在不同g++版本中的处理方式不同
- OMP 目标中全局数组(malloc 与静态)的不同处理方式