Итак, у меня запущено приложение OpenGL, которое может переключаться между полноэкранным и оконным режимами. В настоящее время он делает это, изменяя размер окна и стили.

Однако, похоже, это не делает экран недействительным при переключении из полноэкранного режима в оконный, из-за чего вещи, которые я нарисовал, остаются на экране после переключения. Интересно, что такое поведение наблюдается только в режиме одного монитора. Если я работаю с несколькими мониторами, это отменяет правильность и очищает мой рисунок.

Я не думаю, что это ошибка драйвера, так как это происходит на двух разных компьютерах, использующих две отдельные видеокарты (хотя, по общему признанию, обе они nVidia.), Я думаю, что где-то что-то делаю не так.

Я пробовал несколько способов заставить Windows очистить экран от моих ранее полноэкранных рисунков, но, похоже, ничего не работает. InvalidateRect (), RedrawWindow (), ChangeDisplaySettings () ... В частности:

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);

Что ж, на самом деле, одна вещь, которая, похоже, действительно работает, - это ShowWindow (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 сохраняется до того, как m_hwnd будет присвоено значение NULL, а не после этого. Мое первоначальное создание окна работает нормально, и полноэкранный режим работает нормально. Он просто возвращается в оконный режим после полноэкранного режима, вот в чем проблема.

2
Azuvector 27 Авг 2011 в 19:19

2 ответа

Лучший ответ

Как упоминает datenwolf в другом комментарии к ответу, вы хотите использовать SetWindowPos () вместо MoveWindow () при использовании SetWindowLongPtr ().

Мои грязные проблемы с фоном были решены вызовом ChangeDisplaySettings (NULL, 0) ПОСЛЕ изменения размера моего окна. Выполнение этого раньше мало что дает, но потом, похоже, работает нормально.

2
Azuvector 29 Авг 2011 в 03:13

Если вы установите нулевую фоновую кисть в своем классе окна, окна не будут очищаться автоматически. Вы должны добавить обработчик WM_PAINT, который вызывает ваш обработчик отображения OpenGL, который, в свою очередь, очищает область просмотра ( glClearColor ) и перерисовывает.

2
datenwolf 27 Авг 2011 в 16:15