При работе с сообщением WM_DEVICECHANGE в собственном контроле, вы можете столкнуться с ситуацией, когда сообщение не поступает в ваш контроль, хотя оно работает нормально в основном окне формы. Это происходит потому, что операционная система отправляет сообщения WM_DEVICECHANGE только топ-уровневым окнам, а ваш контроль не является таковым.
Для получения сообщений WM_DEVICECHANGE для вашего контроля у вас есть два варианта:
Использование AllocateHWnd
Вы можете использовать функцию AllocateHWnd для создания сообщения-only топ-уровневого окна, которое будет отвечать на сообщения, вызывая функцию, связанную с вашим контролем. Это даст вам ту же базовую информацию, что и основная форма.
Напишите метод для вашего контроля, который соответствует сигнатуре TWndMethod, которую требует AllocateHWnd. Он может выглядеть так:
procedure TDriveBar.DeviceWindowProc(var Message: TMessage);
begin
case Message.Msg of
wm_DeviceChange: begin
case Message.WParam of
DBT_DEVICEREMOVECOMPLETE, DBT_DEVICEARRIVAL:
if PDEV_BROADCAST_HDR(Message.LParam).dbch_devicetype = DBT_DEVTYP_VOLUME then
UpdateDrives;
end;
end;
end;
Message.Result := DefWindowProc(FDeviceWnd, Message.Msg, Message.WParam, Message.LParam);
end;
Затем используйте этот метод при создании сообщения окна:
FDeviceWnd := AllocateHWnd(DeviceWindowProc);
Использование RegisterDeviceNotification
Вы можете вызвать функцию RegisterDeviceNotification, чтобы сообщить операционной системе, что окно вашего контроля хочет получать уведомления. Обратите внимание, что вам нужно обработать методы CreateWnd и DestroyWnd вашего контроля, чтобы при пересоздании контроля ernew регистрацию уведомления с новым окном. Это даст вам более подробную информацию, чем стандартное сообщение WM_DEVICECHANGE, но только для типов устройств, которые вы указали при регистрации своего окна.
Однако, вас интересуют изменения в томах. Заметки к RegisterDeviceNotification что-то говорят об этом (выделено жирным шрифтом):
Уведомления о приходе и уходе устройств автоматически рассылаются всем топ-уровневым окнам для портов. Поэтому не нужно вызывать RegisterDeviceNotification для портов, и функция терпит неудачу, если член dbch_devicetype равен DBT_DEVTYP_PORT. __Уведомления о томах также рассылаются всем топ-уровневым окнам, поэтому функция терпит неудачу, если dbch_devicetype равен DBT_DEVTYP_VOLUME.__
Это исключает регистрацию уведомлений как вариант для вас, поэтому единственным решением в вашем случае является использование AllocateHWnd.
Не забудьте закрыть свои уведомления, когда вы закончите. Когда ваш компонент будет уничтожен, не забудьте вызвать UnregisterDeviceNotification.
В любом случае, какой бы метод ни был правильным для вас, этот ответ не является заменой документации. Освободите любые ресурсы, которые вы приобрели, и тем способом, который указан в документации.
При работе с сообщением `WM_DEVICECHANGE` в собственном контроле, вам может не поступать это сообщение, если вы не являетесь топ-уровневым окном, и есть два способа решить эту проблему: использование `AllocateHWnd` или `RegisterDeviceNotification`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.