Как предоставить HWND для DirectSound SetCooperativeLevel в консольной программе?

Я пишу консольную программу, которая использует DirectSound API для рендеринга некоторых аудиоданных. Я наткнулся на любопытную проблему, следуя DirectSound Programming Руководство (от Microsoft). Согласно документации:

После создания объекта устройства необходимо установить уровень взаимодействия для устройства с помощью IDirectSound8::SetCooperativeLevel. Если вы этого не сделаете, никаких звуков не будет слышно.

Проблема в том, что я пишу консольную программу, и SetCooperativeLevel требует HWND в качестве первого аргумента. У меня нет HWND для работы в консольной программе. Я попытался предоставить нулевой указатель, но это не удалось с кодом ошибки DSERR_INVALIDPARAM.

Какое значение HWND следует указать для IDirectSound8::SetCooperativeLevel в консольной программе? Аудиочасть программы планируется построить как разделяемую библиотеку, поэтому она практически не знает о «внешней» программе.

Спасибо за любой совет!

Примечание. Я знаю, что есть несколько лучшее решение для простого рендеринга звука, например, с использованием SDL, OpenAL, SFML (на основе OpenAL), но для моего текущего проекта DirectSound принудительно применяется.


Изменить: я нашел сообщение от инженера Microsoft, которое устраняет сомнения относительно использования окна рабочего стола или окна консоли в качестве HWND для SetCooperativeLevel при создании буферов GLOBAL_FOCUS.


person overcoder    schedule 15.07.2011    source источник


Ответы (2)


Хотя я сам не проверял это, вы можете успешно создать скрытое окно и передать его HWND методу SetCooperativeLevel. SetCooperativeLevel использует этот hwnd, чтобы определить, когда ваше приложение имеет фокус ввода; поэтому, если вы выберете кооперативный уровень, на котором фокус ввода не имеет значения (например, DSSCL_NORMAL), скрытое окно (которое никогда не получит фокус ввода) должно подойти.

person bdonlan    schedule 15.07.2011
comment
Как вы сказали, фокус ввода не должен мешать при рендеринге звука. Я невинно проверил предоставление HWND, возвращенного GetDesktopWindow() в SetCooperativeLevel, и, похоже, это работает. Однако я не знаю, есть ли у него недостатки по сравнению с использованием скрытого дескриптора окна... - person overcoder; 16.07.2011
comment
Передача HWND, которую вы не контролируете, кажется очень плохой идеей. Это одна из тех вещей, которые, вероятно, будут работать просто отлично — до того дня, когда ваш код окажется в разборе на dailywtf или на старой новой штуке. - person snemarch; 16.07.2011
comment
@overcoder, я бы беспокоился о том, что произойдет, если другая программа решит сделать то же самое... - person bdonlan; 16.07.2011
comment
@snemarch, @bdonlan: Ты прав. Я предпочитаю писать правильно, как описано bdonlan. На ум приходит закон Мерфи: «Все, что может пойти не так, идет не так». - person overcoder; 16.07.2011
comment
Совершенно нормально передать HWND другого приложения в DirectSound. Не лучший дизайн, но он работает. Именно так некоторые приложения голосовой связи для геймеров, такие как RogerWilco и Battlecom, делали это до того, как режим DSSCL_EXCLUSIVE устарел (и все игры использовали этот режим). Игра может оставаться на переднем плане с собственным HWND, но приложение голосовой связи может воспроизводить звук в фоновом режиме. На самом деле вам даже не нужно передавать действительный HWND, если вы используете кооперативный режим, который не заботится о фокусе приложения. Вы можете передать что-нибудь ненулевое. - person selbie; 16.07.2011
comment
@selbie: Спасибо за ответ. Ранее я обнаружил, что использование некоторого ненулевого HWND работает нормально, но сомнения все еще присутствуют без явной ссылки или документации. Я (сильно) гуглил, чтобы найти его у инженера Microsoft: groups.google.com/group/ - person overcoder; 16.07.2011

вы можете использовать это ::GetDesktopWindow().

person szhu    schedule 23.08.2012