为什么当我使用“message”指令时,我的控件中收不到消息?

Mar*_*unu 4 delphi message delphi-2009

创建控件后,我必须使用它DeviceWnd:=AllocateHWnd(DeviceWindowProc);来接收WM_DEVICECHANGE消息。进而...

procedure TFileList.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
           OnDeviceChange;
      end;
    end;
  end; 
  Message.Result:=DefWindowProc(DeviceWnd, Message.Msg, Message.WParam, Message.LParam);
end;
Run Code Online (Sandbox Code Playgroud)

这很好用,但是为什么当我这样做时我没有收到该消息?:

TFileList = class(TCustomControl)
private
  procedure DeviceChage(var AMessage:TMessage); message WM_DEVICECHANGE;
end;

procedure TFileList.DeviceWindowProc(var Message: TMessage);
begin
  Message.Result:=DefWindowProc(DeviceWnd, Message.Msg, Message.WParam, Message.LParam);
end;

procedure TFileList.DeviceChage(var AMessage:TMessage);
begin
 case AMessage.WParam of
   DBT_DEVICEREMOVECOMPLETE, DBT_DEVICEARRIVAL:
     if PDEV_BROADCAST_HDR(AMessage.LParam).dbch_devicetype = DBT_DEVTYP_VOLUME then
       OnDeviceChange;
 end;
end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

来自以下文档RegisterDeviceNotification

应用程序使用 BroadcastSystemMessage 函数发送事件通知。任何具有顶级窗口的应用程序都可以通过处理 WM_DEVICECHANGE 消息来接收基本通知。应用程序可以使用 RegisterDeviceNotification 函数来注册接收设备通知。

您创建的窗口AllocateHWnd是顶级窗口。因此它接收广播消息。

您的自定义控件不是顶级窗口。如果您希望它接收消息,您必须调用RegisterDeviceNotification传递其窗口句柄。如果您这样做,请务必通过在 中注册CreateWnd和取消注册来处理 VCL 窗口重新创建DestroyWnd

作为一般经验法则,AllocateHwnd这是侦听通知的首选方式。这是因为它不受 VCL 窗口重新创建的影响,因此不会错过通知。当重新创建 VCL 窗口时,有一个发送通知的机会窗口,但您的应用程序没有准备好接收的窗口。

这肯定会成为您的情况的一个问题,因此您应该使用AllocateHwnd. 您可以安排您创建的窗口归AllocateHwnd您的自定义控件所有,然后您可以将通知路由到该控件的代码。