2013-09-26 4 views
2

Я пишу приложение для рабочего стола Win7 и хочу, чтобы он плавно переходил из оконного в оконный полноэкранный (и наоборот) и в основном выполнял это, позвонив SetWindowLongPtr, чтобы обновить его стиль, а затем MoveWindow, чтобы обновить его размер и положение. Проблема в том, что окно мигает для одного кадра, чтобы показать его обновленный стиль, но новый размер и позиция не отображаются. Следующий кадр выглядит корректно, но я стараюсь избегать этого однокадрового артефакта.Как я могу обновить стиль и положение HWND атомарно?

Я попытался изменить порядок, в котором я называю API, но он просто изменяет внешний вид артефакта. Я также пытался скрывать окно, вызывая API, а затем показываю окно, но это просто заставляет окно исчезать для одного кадра.

Я знаю, что один из вариантов заключается в создании нового окна с желаемыми свойствами, а затем уничтожении старого, но я хотел найти менее дорогую альтернативу.

Так можно ли назвать эти API и визуально отобразить их атомарно? В качестве бонуса было бы неплохо также иметь множественные результирующие сообщения WM_SIZE, объединенные в одно событие, но я могу управлять этим сам в обработчике сообщений.

ответ

2

Выполнение такого рода надежно затруднено в Windows, тем более что Vista, поскольку DWM может усложнить ситуацию. Часто это вопрос проб и ошибок, пока вы не найдете решение, которое работает для вас.

SetWindowPos имеет флаг SWP_NOREDRAW, который предотвращает перепроектирование окна в ответ на вызов. Таким образом, вы можете попробовать сначала изменить позицию, затем обновить стили и, наконец, третий вызов перерисовать окно в новом месте. Например,

SetWindowPos(hWnd, 0, x, y, w, h, SWP_NOREDRAW | SWP_NOZORDER); 
SetWindowLongPtr(hWnd, GWL_STYLE, dwNewStyles); 
RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_FRAME); 
+0

Самый точный ответ, хотя я не мог получить ничего, что было бы без артефактов на нескольких машинах, в том числе с использованием подхода RedrawWindow. – MooseBoys

0

Что вы подразумеваете под "windowed-fullscreen"? Это то же самое, что и максимизировано?

Если да, то ShowWindow(hwnd, SW_MAXIMIZE)?

+0

Нет, я имею в виду стиль WS_POPUP с клиентом, равным выпрямителю монитора. Также называемый [Безграничный полноэкранный режим] (http://pcgamingwiki.com/wiki/Borderless_fullscreen_windowed), это приводит к выигрышу в эффективности при использовании DirectX. Похоже, что SW_MAXIMIZE работает как альтернатива MoveWindow, но он не устраняет артефакт, поскольку мне все же нужно сначала отрегулировать стиль окна. – MooseBoys

1

MSDN говорит:

Некоторые данные окна кэшируются, поэтому любые изменения, используя SetWindowLongPtr не вступит в силу до тех пор, пока вызов функции SetWindowPos .

Таким образом, этот должен работы. Возможно, попробуйте использовать SetWindowPos вместо MoveWindow.

Вы делаете что-нибудь интересное в своем окне proc, когда получаете события, вызванные этими вызовами? В частности, вы «фиксируете» размер или что-то в этом роде?

+0

Я тоже попробовал SetWindowPos, и он дает те же результаты.Единственное, что я делаю в моем wndproc, - это обработка WM_SYSCHAR для команды Alt + Enter. Я «фиксирую» размер, но только если он меньше 128 пикселей, поэтому в этом случае он не попадает (проверен с помощью отладчика). – MooseBoys

1

Отъезд WM_SETREDRAW; используйте его, чтобы отключить перерисовку, изменить стили окна, а затем вызвать RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN), чтобы отобразить их атомарно.

+0

Окно может игнорировать это сообщение –

Смежные вопросы