Повторный запуск приложения, повышенные runas, не фиксирует сообщение TaskbarButtonCreated перед использованием ITaskbarList?

Использование Borland C++ Builder.

Прежде чем использовать ITaskbarList3, я делаю так, как требует Windows:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd391692.aspx

Ваше приложение должно вызывать RegisterWindowMessage(L"TaskbarButtonCreated") и обрабатывать это сообщение в своем файле wndproc. Это сообщение должно быть получено вашим приложением до того, как оно вызовет какой-либо метод ITaskbarList3.

Однако это не всегда работает для меня, сообщение, которое я жду, никогда не приходит, даже если RegisterWindowMessage() был успешным.

После некоторого копания я обнаружил, что проблема связана с тем, что мое приложение перезапускается с помощью «runas», сразу после запуска, когда на основе пользовательских настроек приложение должно запускаться с повышенными правами.

Второй (теперь повышенный) запуск, сообщение, которого я жду, так и не приходит.

Я предполагаю, это связано с тем, что Windows уже отправила это сообщение и не делает этого снова, несмотря на то, что создается новый экземпляр ??

Насколько безопасно предполагать, что сообщение должно быть отправлено уже при втором (с повышенными правами) запуске, и все равно продолжать использовать ITaskbarList3?


person Peter    schedule 16.12.2015    source источник


Ответы (1)


Код вашего приложения должен вызывать ChangeWindowMessageFilterEx< /a> после создания верхнего окна и регистрации сообщения «TaskbarButtonCreated». Это позволит второму экземпляру (с повышенными правами) получать сообщение TaskbarButtonCreated.

UINT nTaskbarButtonCreatedMessage = RegisterWindowMessage(TEXT("TaskbarButtonCreated"));
HWND hWnd = {create the top main window and get handle to it}.
ChangeWindowMessageFilterEx(hWnd, nTaskbarButtonCreated, MSGFLT_ALLOW, nullptr);

(это код для VC++, но я думаю, что он будет работать и для Borland C++ Builder)

person Ruslan Garipov    schedule 16.12.2015
comment
Спасибо @Руслан. Я получаю ошибку неопределенной функции, даже когда я включаю windows.h . Я также беспокоюсь, что это создаст ошибку на XP, поскольку в документах указано, что это Windows 7 и выше. - person Peter; 16.12.2015
comment
Из любопытства, бывают ли ситуации, когда значок на панели задач никогда не создается? Если нет, и в качестве резервного сценария я мог бы предположить, что значок был создан, когда отображается основная форма и запускается первое событие OnIdle. - person Peter; 16.12.2015
comment
ChangeWindowMessageFilterEx() определено в winuser.h, которое включено в windows.h. Убедитесь, что WINVER определение равно >= 0x0601, чтобы использовать его. В любом случае вам придется использовать ChangeWindowMessageFilter() в XP и Vista, поэтому используйте GetProcAddress() для загрузки ChangeWindowMessageFilterEx() во время выполнения и отката, если он недоступен. - person Remy Lebeau; 16.12.2015
comment
Что касается сообщения TaskbarButtonCreated, оно доставляется при создании кнопки панели задач окна (отсюда и его название), и этого не происходит до тех пор, пока окно не будет показано. Пока вы регистрируете фильтр сообщений после создания окна и до его отображения, все должно быть в порядке. Лучше всего это сделать в методе CreateWnd() вашей формы (который также позволит вам перерегистрировать фильтр сообщений, если HWND формы когда-либо будет воссоздан). - person Remy Lebeau; 16.12.2015
comment
Или вы можете просто использовать ChangeWindowMessageFilter() при запуске программы перед созданием каких-либо окон. Идентификатор для TaskbarButtonCreated не изменится в течение срока службы приложения, поэтому вы можете просто зарегистрировать фильтр сообщений один раз для всего процесса, а не пытаться зарегистрировать его для отдельных окон. - person Remy Lebeau; 16.12.2015
comment
@RuslanGaripov: Я знаю об этом, но пока этого не произошло. - person Remy Lebeau; 16.12.2015
comment
@Remy, я регистрирую сообщение в конструкторе форм. Форма создается только один раз, поэтому при повторном запуске с повышенными правами форма создается не в первом экземпляре, а во втором (повышенном) экземпляре. Однако второй экземпляр (с повышенными правами) никогда не получает сообщение, хотя регистрация сработала. - person Peter; 16.12.2015
comment
PS. как грязный обходной путь, после того, как я задал вопрос, я попытался проверить в OnIdle, отображается ли форма, и если это так, я разрешаю использование ITaskbarList с этого момента, как если бы сообщение было получено. Однако я делаю try{} catch(...){} любые действия с ITaskbarList, чтобы убедиться. Проверено и работает. - person Peter; 16.12.2015
comment
@Peter: конструктор опоздал. HWND уже создан, и DFM формы уже загружен. Если это ваша основная форма, она отображается автоматически по умолчанию, поэтому кнопка на панели задач, вероятно, также уже создана. Как я уже говорил ранее, вы должны переопределить виртуальный метод CreateWnd() формы и вместо этого выполнить регистрацию фильтра оттуда. Таким образом, вы можете зарегистрировать фильтр сразу после создания HWND, прежде чем с ним будут слишком часто манипулировать. Конечно, это предполагает, что Application.MainFormOnTaskbar истинно (что по умолчанию). - person Remy Lebeau; 16.12.2015