C++ 从全屏模式切换后是否清除屏幕?

C++ 从全屏模式切换后是否清除屏幕?,c++,c,winapi,opengl,fullscreen,C++,C,Winapi,Opengl,Fullscreen,所以我有一个OpenGL应用程序运行,可以在全屏模式和窗口模式之间切换。它目前通过调整窗口大小和更改样式来实现这一点 然而,当从全屏模式切换到窗口模式时,它似乎不会使屏幕失效,这会使我绘制的东西在切换后留在屏幕上。 有趣的是,它仅在单监视器模式下显示这种行为。如果我使用多个监视器运行,它将使OK无效,并清除我的图形 我不认为这是一个驱动程序错误,因为它发生在使用两个独立视频卡的两台独立计算机上(尽管承认它们都是nVidia),我想我在某处做错了什么 我尝试了很多方法让Windows清除以前全屏绘

所以我有一个OpenGL应用程序运行,可以在全屏模式和窗口模式之间切换。它目前通过调整窗口大小和更改样式来实现这一点

然而,当从全屏模式切换到窗口模式时,它似乎不会使屏幕失效,这会使我绘制的东西在切换后留在屏幕上。 有趣的是,它仅在单监视器模式下显示这种行为。如果我使用多个监视器运行,它将使OK无效,并清除我的图形

我不认为这是一个驱动程序错误,因为它发生在使用两个独立视频卡的两台独立计算机上(尽管承认它们都是nVidia),我想我在某处做错了什么

我尝试了很多方法让Windows清除以前全屏绘图的屏幕,但似乎没有任何效果。无效安装()、重画窗口()、更改显示设置()。。。 具体而言:

InvalidateRect(m_hwnd, &rectx, true); // rect being the dimensions of either the screen or my window.
InvalidateRect(HWND_DESKTOP, NULL, TRUE); // Doesn't seem to do anything.
RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
ChangeDisplaySettings(NULL, 0);
事实上,有一件事似乎确实有效,那就是在调整大小之前显示窗口(hwnd,SW_HIDE)。然而,这会暂时失去焦点,允许其他应用程序获取我的应用程序的输入,这似乎是一种不好的方式。 我应该注意,当我看到这种行为时,我并没有做任何实际的显示模式改变;只需保持当前全屏分辨率即可

我有点不知道我哪里出了问题。简化代码:

if(m_isFullscreen)
{
    ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
}
else
{
    ChangeDisplaySettings(&m_dmSavedScreenSettings, 0);
}
if(m_isFullscreen)
{
    dwExStyle = WS_EX_APPWINDOW;
    dwStyle = WS_POPUP;
    ShowCursor(false);
}
else
{
    dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    dwStyle = WS_OVERLAPPEDWINDOW;
    if(m_isRunning) // Because ShowCursor uses a counter to indicate, and windowed mode defaults to cursor on, we don't need to increment the counter and double it being on.
    {
        ShowCursor(true);
    }
}

RECT rect;
rect.left = 0;
rect.top = 0;
if(m_isFullscreen) { rect.right = 1280; } else { rect.right = 640; }
if(m_isFullscreen) { rect.bottom = 1024; } else { rect.bottom = 480; }
AdjustWindowRectEx(&rect, dwStyle, false, dwExStyle);

SetWindowLongPtr(m_hwnd, GWL_STYLE, dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, dwExStyle);
if(m_isFullscreen)
{
    MoveWindow(m_hwnd, 0, 0, 1280, 1024, true);
}
else
{
    MoveWindow(m_hwnd, 0, 0, 640, 480, true); // windowed
}

差不多就是这样。其他一些支持代码和错误检查,但这就是我正在做的。。。dmSavedSettings在从NULL分配m_hwnd之前保存,而不是之后保存。我的初始窗口创建工作正常,全屏工作正常。问题在于,在全屏显示后,它只是返回到Windowed状态。

如果在window类中设置空背景笔刷,windows将不会自动清除。您必须添加一个调用OpenGL显示处理程序的WM_PAINT处理程序,该处理程序依次清除视口(glClearColor)并重新绘制。

正如DatenWalf在另一个答案的注释中提到的,在使用SetWindowLongPtr()时,您希望使用SetWindowPos()而不是MoveWindow()


调整窗口大小后,通过调用ChangeDisplaySettings(NULL,0)解决了我的脏背景问题。以前做这件事没什么作用,但事后看来效果不错。

我不确定我是否理解你的意思。我的视口很好,我正在渲染的内容显示在我的窗口中,周围的桌面空间被以前的全屏显示和清晰的颜色所覆盖。。。我使用的是hbrBackground=NULL,但你在这里是正确的。你能给我举个例子说明我应该如何处理这个问题吗?我可以想象,自从我开始渲染东西后,WM_PAINT不断地被调用…?@Azuvector:啊,我明白了。我误解了你,以为你自己的节目有问题。如果根窗口(这就是它的名称)没有被正确地重新绘制,这肯定不是程序的错误,而是窗口合成器中的错误。但我想知道:如果你不切换分辨率,为什么要调用ChangeDisplaySettings?因为一旦事情正常运行,我可能会更改屏幕分辨率。在我的测试用例中,您实际上可以完全删除changedDisplaySettings()调用,它的功能仍然相同,在窗口缩小很多之后,屏幕上的大部分仍然覆盖着我在全屏上绘制的像素。注意,我可以通过拖动框架或最小化/最大化来调整窗口本身的大小。正是全屏->窗口化的更改让我着迷。我一定是做错了什么…:/@Azuvector:只有一个建议:使用SetWindowPos代替MoveWindow,SetWindowLongPtr需要这样做。