gpt4 book ai didi

delphi - 如何在 TForm 以外的控件中捕获 WM_DEVICECHANGE?

转载 作者:行者123 更新时间:2023-12-02 08:50:45 42 4
gpt4 key购买 nike

直到今天,我一直在使用以下代码来捕获应用程序主窗体中的 WM_DEVICECHANGE 消息,并且效果良好。但是,如果我尝试在自定义控件中使用它,我不会收到有关设备插入或删除的通知。发生了什么事?

  TDriveBar = class(TCustomPanel)
private
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;
end;

implementation

procedure TDriveBar.WMDeviceChange(var Msg: TMessage);
const DBT_DEVICEARRIVAL = $8000;
DBT_DEVICEREMOVECOMPLETE = $8004;
DBT_DEVTYP_VOLUME = 2;

type PDEV_BROADCAST_HDR = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = record
dbch_size: dword;
dbch_devicetype: dword;
dbch_reserved: dword;
end;

begin
case Msg.WParam of

DBT_DEVICEREMOVECOMPLETE:
if PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype = DBT_DEVTYP_VOLUME then UpdateDrives;

DBT_DEVICEARRIVAL:
if PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype = DBT_DEVTYP_VOLUME then UpdateDrives;

end;
end;

最佳答案

操作系统向所有顶级窗口发送 wm_DeviceChange 消息。应用程序的主窗体是顶级窗口,但您的控件不是,这就是窗体接收消息而您的控件不接收消息的原因。

对于任意设备类型,您有两种选择:

  1. 使用AllocateHWnd创建一个仅包含消息的顶级窗口,该窗口将通过调用与控件关联的函数来响应消息。这将为您提供与主表单收到的相同的基本信息。

    为您的控件编写一个与 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);
  2. 调用 RegisterDeviceNotification告诉操作系统您的控件的窗口也想要接收通知。 (确保处理控件的 CreateWndDestroyWnd 方法,以便在重新创建控件时,可以使用控件的新窗口句柄更新通知注册。)这将为您提供比默认 wm_DeviceChange 消息提供的更详细的信息,但仅适用于您在注册窗口句柄时指定的设备类型。

但是,您对卷的更改感兴趣。 RegisterDeviceNotification 的注释对此有话要说(已添加强调):

The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME.

这消除了通知注册作为您的一个选项,因此您的情况的唯一解决方案是使用 AllocateHWnd

关于delphi - 如何在 TForm 以外的控件中捕获 WM_DEVICECHANGE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30711942/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com