Правильная обработка Alt-Enter / Alt-Tab полноэкранного разрешения

Страница MSDN на DXGI дает инструкции о том, как работать с полноэкранными разрешениями, отличными от разрешения рабочего стола. В нем говорится, что нужно вызвать IDXGISwapChain::ResizeTargets() перед вызовом IDXGISwapChain::SetFullscreenState(), чтобы предотвратить мерцание, среди прочего.

В нем не сказано, как обращаться с Alt-Enter, который вызывает IDXGISwapChain::SetFullscreenState() до того, как программа получит возможность сделать свой собственный вызов IDXGISwapChain::ResizeTargets(). Если последний метод вызывается для сообщения WM_SIZE, будет отправлено другое сообщение WM_SIZE, что может вызвать бесконечный цикл. Как сделать так, чтобы последний вызывался раньше первого при нажатии alt-enter или alt-tab, и чтобы переключение режимов происходило вообще безболезненно?


person NmdMystery    schedule 18.08.2014    source источник


Ответы (2)


Это будет очень сложно... правильный способ решения этой проблемы: IDXGIFactory::MakeWindowAssociation, который, насколько мне известно, еще никому не удалось успешно использовать. Вы можете попробовать это в любом случае.

"Правильный" ответ - вручную обрабатывать Alt+Enter. Итак, отключите Alt+Enter с помощью MakeWindowAssociation и запачкайте руки. Во-первых, нет необходимости захватывать WM_SIZE. Вместо этого слушайте WM_ENTERSIZEMOVE, WM_CAPTURECHANGED, WM_WINDOWPOSCHANGED и WM_EXITSIZEMOVE. Это избавит вас от необходимости иметь дело с WM_SIZE и по-прежнему получать все соответствующие события изменения размера окна. (При этом также прочитайте этот вопрос: WM_ENTERSIZEMOVE /WM_EXITSIZEMOVE - при использовании меню не всегда парное)

Итак, предположим, что все прошло нормально, для Alt+Enter вам нужно сделать следующее: Вы устанавливаете свою цепочку обмена в полноэкранный режим, используя IDXGISwapChain::SetFullscreenState, а затем измените размер цепочки подкачки (IDXGISwapChain::ResizeBuffers). По умолчанию вы получите цепочку подкачки, максимально приближенную к текущему разрешению вашего окна перед изменением размера. Чтобы сделать это правильно, сначала перечислите полноэкранные разрешения, а после перехода в полноэкранный режим установите разрешение, которое вы хотите иметь. Звучит некрасиво, но кажется самым надежным способом решения проблемы.

В общем, реальный, эксклюзивный полноэкранный режим не стоит проблем, так как вы всегда будете мерцать, когда кто-то нажимает Alt + Tab (вы не можете избежать этого, если произойдет переключение режима, так как сам экран должен будет перенастроиться). гораздо лучшим решением является использование полноэкранного окна без полей. Вы просто создаете класс окна без каких-либо украшений, делаете его полноэкранным, размещаете его так, чтобы он покрывал весь экран, и покончили с этим. Тогда вам вообще не придется беспокоиться об Alt+Enter и Alt+Tab. Это также позволяет людям продолжать работу на втором экране без мерцания. С точки зрения производительности это довольно неплохо (большинство новых игр поддерживают это как «полноэкранный режим без полей».)

Может быть серебряная пуля, которая решает все это правильно, но я ее еще не видел. Если есть более чистое/красивое решение, мне было бы очень любопытно его услышать. «Полноэкранный режим без полей», по-видимому, является текущим стандартом, хотя IIRC, Unity 5 разрешает «полноэкранный режим без полей» только для Direct3D 11.

person Anteru    schedule 18.08.2014
comment
Просто обновление - я смог добиться того, чего хотел, всего лишь с WM_SIZE. Здесь есть небольшой хак, но это только одна строка, и это не очень больно. Когда вызывается WM_SIZE, я проверяю, существует ли целевой вид рендеринга, прежде чем настраивать буферы. Таким образом, я не сталкиваюсь с ошибками нулевого указателя при создании окна. Впрочем, все остальное было сделано, как вы сказали. - person NmdMystery; 14.10.2014
comment
Как именно вы обрабатываете ALT + Enter? Вы сказали отключить ALT + ENTER в MakeWindowAssociation, но ALT + ENTER не вызывает ни одного из сообщений, упомянутых в вашем ответе. - person Raildex; 03.01.2021
comment
Для ввода с клавиатуры используйте обычный материал, то есть либо WM_*KEYDOWN, либо необработанный ввод. Это не требует специального сообщения. - person Anteru; 03.01.2021

Я просто хочу добавить обновление по этой проблеме - я написал небольшую библиотеку окон, которая, как мне кажется, довольно хорошо обрабатывает DXGI - никаких отладочных сообщений, никаких сообщений об ошибках, и все ведет себя так, как предполагалось, по крайней мере, в моей среде Windows. Полное решение этой проблемы слишком сложно, чтобы объяснить его в одном ответе, так как оно требует множества точно размещенных вызовов методов (как оказалось, DXGI действительно, очень жесткий), но мой код находится на github, если кто-то хочет на это взглянуть. В частности, этот файл и этот файл — это те файлы, которые вы хотите просмотреть — последний является совокупным объектом бывший.

Обратите внимание, что я отключил ALT+ENTER в пользу F11, но функциональность точно такая же.

Кстати, если вы хотите использовать эту библиотеку, я выпускаю ее как свободное программное обеспечение и скоро предоставлю документацию.

person NmdMystery    schedule 06.07.2015