delphi – 如何检测新串口的添加?

前端之家收集整理的这篇文章主要介绍了delphi – 如何检测新串口的添加?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
要与微控制器通信,我使用串行端口.我使用TCommPortDriver 2.1工作正常.但是,它缺乏检测新组合的添加删除的能力.这会在会话期间定期发生.

是否有事件告知何时添加删除了一个comport?

更新1

我尝试了RRUZ的第一个建议,并把它变成了一个独立的程序.当电缆插入或拔出时,它会对WM_DEVICECHANGE作出反应,但WParam不会显示设备的到达或移除.结果是:

  1. msg = 537,wparam = 7,lparam = 0
  2. msg = 537,lparam = 0

插入USB电缆时会发送第一条消息,插入USB电缆时会发送下一条消息.
消息部分显示WM_DEVICECHANGE消息(537),但WParam为7,不是WM_DEVICECHANGE或DBT_DEVICEARRIVAL.我稍微修改代码以便处理消息,但是当LParam为零时,这是没用的.结果与VCL和FMX相同.作为检查,请参阅下面的代码.

更新2

我现在运行WMI代码.它只在添加COM端口时触发,当一个端口被移除时没有反应.结果:

  1. TargetInstance.ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318}
  2. TargetInstance.Description : Arduino Mega ADK R3
  3. TargetInstance.Name : Arduino Mega ADK R3 (COM4)
  4. TargetInstance.PNPDeviceID : USB\VID_2341&PID_0044\64935343733351E0E1D1
  5. TargetInstance.Status : OK

这可以解释一个事实,在其他代码中,这不被视为添加COM端口?它似乎将新连接视为USB端口(实际上是什么). Arduino驱动程序将其转换为COM端口,但WMI无法识别. Windows消息传递’看到’COM端口更改但无法检测是否添加删除了它.

无论如何:设备更改工作.我只需要枚举COM端口,看看哪个实际存在,这是我已经手动完成的.现在我可以使用WM_DEVICECHANGE自动执行此操作.我只是向CPDrv组件添加一个事件.

感谢RRUZ的代码和帮助!

  1. unit dev_change;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;
  7.  
  8. type
  9. TProc = procedure (text: string) of object;
  10.  
  11. BroadcastHdr = ^DEV_BROADCAST_HDR;
  12. DEV_BROADCAST_HDR = packed record
  13. dbch_size: DWORD;
  14. dbch_devicetype: DWORD;
  15. dbch_reserved: DWORD;
  16. end;
  17. TDevBroadcastHdr = DEV_BROADCAST_HDR;
  18.  
  19. type
  20. PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
  21. DEV_BROADCAST_DEVICEINTERFACE = record
  22. dbcc_size: DWORD;
  23. dbcc_devicetype: DWORD;
  24. dbcc_reserved: DWORD;
  25. dbcc_classguid: TGUID;
  26. dbcc_name: Char;
  27. end;
  28. TDevBroadcastDeviceInterface = DEV_BROADCAST_DEVICEINTERFACE;
  29.  
  30. const
  31. DBT_DEVICESOMETHING = $0007;
  32. DBT_DEVICEARRIVAL = $8000;
  33. DBT_DEVICEREMOVECOMPLETE = $8004;
  34. DBT_DEVTYP_DEVICEINTERFACE = $00000005;
  35.  
  36. type
  37. TDeviceNotifyProc = procedure(Sender: TObject; const DeviceName: String) of Object;
  38. TDeviceNotifier = class
  39. private
  40. hRecipient: HWND;
  41. FNotificationHandle: Pointer;
  42. FDeviceArrival: TDeviceNotifyProc;
  43. FDeviceRemoval: TDeviceNotifyProc;
  44. FOnWin: TProc;
  45.  
  46. procedure WndProc(var Msg: TMessage);
  47.  
  48. public
  49. constructor Create(GUID_DEVINTERFACE : TGUID);
  50. property OnDeviceArrival: TDeviceNotifyProc read FDeviceArrival write FDeviceArrival;
  51. property OnDeviceRemoval: TDeviceNotifyProc read FDeviceRemoval write FDeviceRemoval;
  52. destructor Destroy; override;
  53.  
  54. property OnWin: TProc read FOnWin write FOnWin;
  55. end;
  56.  
  57. TForm1 = class(TForm)
  58. Memo: TMemo;
  59. procedure FormCreate(Sender: TObject);
  60. procedure FormDestroy(Sender: TObject);
  61. private
  62. { Private declarations }
  63. DeviceNotifier : TDeviceNotifier;
  64. public
  65. { Public declarations }
  66. procedure arrival(Sender: TObject; const DeviceName: String);
  67. procedure report (text: string);
  68. end;
  69.  
  70. var
  71. Form1: TForm1;
  72.  
  73. implementation
  74.  
  75. {$R *.dfm}
  76.  
  77. constructor TDeviceNotifier.Create(GUID_DEVINTERFACE : TGUID);
  78. var
  79. NotificationFilter: TDevBroadcastDeviceInterface;
  80. begin
  81. inherited Create;
  82. hRecipient := AllocateHWnd(WndProc);
  83. ZeroMemory (@NotificationFilter,SizeOf(NotificationFilter));
  84. NotificationFilter.dbcc_size := SizeOf(NotificationFilter);
  85. NotificationFilter.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
  86. NotificationFilter.dbcc_classguid := GUID_DEVINTERFACE;
  87. //register the device class to monitor
  88. FNotificationHandle := RegisterDeviceNotification(hRecipient,@NotificationFilter,DEVICE_NOTIFY_WINDOW_HANDLE);
  89. end;
  90.  
  91. procedure TDeviceNotifier.WndProc(var Msg: TMessage);
  92. var
  93. Dbi: PDevBroadcastDeviceInterface;
  94. begin
  95. OnWin (Format ('msg = %d,wparam = %d,lparam = %d',[msg.Msg,msg.WParam,msg.LParam]));
  96. with Msg do
  97. if (Msg = WM_DEVICECHANGE) and ((WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE) or
  98. (WParam = DBT_DEVICESOMETHING)) then
  99. try
  100. Dbi := PDevBroadcastDeviceInterface (LParam);
  101. if Dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE then
  102. begin
  103. if WParam = DBT_DEVICEARRIVAL then
  104. begin
  105. if Assigned(FDeviceArrival) then
  106. FDeviceArrival(Self,PChar(@Dbi.dbcc_name));
  107. end
  108. else
  109. if WParam = DBT_DEVICEREMOVECOMPLETE then
  110. begin
  111. if Assigned(FDeviceRemoval) then
  112. FDeviceRemoval(Self,PChar(@Dbi.dbcc_name));
  113. end;
  114. end;
  115. except
  116. Result := DefWindowProc(hRecipient,Msg,WParam,LParam);
  117. end
  118. else
  119. Result := DefWindowProc(hRecipient,LParam);
  120. end;
  121.  
  122. destructor TDeviceNotifier.Destroy;
  123. begin
  124. UnregisterDeviceNotification(FNotificationHandle);
  125. DeallocateHWnd(hRecipient);
  126. inherited;
  127. end;
  128.  
  129. procedure TForm1.arrival(Sender: TObject; const DeviceName: String);
  130. begin
  131. report (DeviceName);
  132.  
  133. ShowMessage(DeviceName);
  134. end;
  135.  
  136. procedure TForm1.FormCreate(Sender: TObject);
  137. const
  138. GUID_DEVINTERFACE_COMPORT : TGUID = '{86E0D1E0-8089-11D0-9CE4-08003E301F73}';
  139. begin
  140. DeviceNotifier:=TDeviceNotifier.Create(GUID_DEVINTERFACE_COMPORT);
  141. DeviceNotifier.FDeviceArrival:=arrival;
  142. DeviceNotifier.OnWin := report;
  143. end;
  144.  
  145. procedure TForm1.FormDestroy(Sender: TObject);
  146. begin
  147. DeviceNotifier.Free;
  148. end;
  149.  
  150. procedure TForm1.report (text: string);
  151. begin
  152. Memo.Lines.Add (text);
  153. end;
  154.  
  155. end.

解决方法

您可以使用 RegisterDeviceNotification WinAPI函数DEV_BROADCAST_DEVICEINTERFACE结构与 GUID_DEVINTERFACE_COMPORT设备接口类一起传递.

试试这个样本.

  1. type
  2. PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
  3. DEV_BROADCAST_HDR = packed record
  4. dbch_size: DWORD;
  5. dbch_devicetype: DWORD;
  6. dbch_reserved: DWORD;
  7. end;
  8. TDevBroadcastHdr = DEV_BROADCAST_HDR;
  9.  
  10. type
  11. PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
  12. DEV_BROADCAST_DEVICEINTERFACE = record
  13. dbcc_size: DWORD;
  14. dbcc_devicetype: DWORD;
  15. dbcc_reserved: DWORD;
  16. dbcc_classguid: TGUID;
  17. dbcc_name: Char;
  18. end;
  19. TDevBroadcastDeviceInterface = DEV_BROADCAST_DEVICEINTERFACE;
  20.  
  21. const
  22. DBT_DEVICEARRIVAL = $8000;
  23. DBT_DEVICEREMOVECOMPLETE = $8004;
  24. DBT_DEVTYP_DEVICEINTERFACE = $00000005;
  25.  
  26. type
  27. TDeviceNotifyProc = procedure(Sender: TObject; const DeviceName: String) of Object;
  28. TDeviceNotifier = class
  29. private
  30. hRecipient: HWND;
  31. FNotificationHandle: Pointer;
  32. FDeviceArrival: TDeviceNotifyProc;
  33. FDeviceRemoval: TDeviceNotifyProc;
  34. procedure WndProc(var Msg: TMessage);
  35. public
  36. constructor Create(GUID_DEVINTERFACE : TGUID);
  37. property OnDeviceArrival: TDeviceNotifyProc read FDeviceArrival write FDeviceArrival;
  38. property OnDeviceRemoval: TDeviceNotifyProc read FDeviceRemoval write FDeviceRemoval;
  39. destructor Destroy; override;
  40. end;
  41.  
  42. type
  43. TForm17 = class(TForm)
  44. procedure FormCreate(Sender: TObject);
  45. procedure FormDestroy(Sender: TObject);
  46. private
  47. { Private declarations }
  48. DeviceNotifier : TDeviceNotifier;
  49. public
  50. { Public declarations }
  51. procedure arrival(Sender: TObject; const DeviceName: String);
  52. end;
  53.  
  54. var
  55. Form17: TForm17;
  56.  
  57. implementation
  58.  
  59. {$R *.dfm}
  60.  
  61. constructor TDeviceNotifier.Create(GUID_DEVINTERFACE : TGUID);
  62. var
  63. NotificationFilter: TDevBroadcastDeviceInterface;
  64. begin
  65. inherited Create;
  66. hRecipient := AllocateHWnd(WndProc);
  67. ZeroMemory(@NotificationFilter,SizeOf(NotificationFilter));
  68. NotificationFilter.dbcc_size := SizeOf(NotificationFilter);
  69. NotificationFilter.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
  70. NotificationFilter.dbcc_classguid := GUID_DEVINTERFACE;
  71. //register the device class to monitor
  72. FNotificationHandle := RegisterDeviceNotification(hRecipient,DEVICE_NOTIFY_WINDOW_HANDLE);
  73. end;
  74.  
  75. procedure TDeviceNotifier.WndProc(var Msg: TMessage);
  76. var
  77. Dbi: PDevBroadcastDeviceInterface;
  78. begin
  79. with Msg do
  80. if (Msg = WM_DEVICECHANGE) and ((WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE)) then
  81. try
  82. Dbi := PDevBroadcastDeviceInterface(LParam);
  83. if Dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE then
  84. begin
  85. if WParam = DBT_DEVICEARRIVAL then
  86. begin
  87. if Assigned(FDeviceArrival) then
  88. FDeviceArrival(Self,PChar(@Dbi.dbcc_name));
  89. end
  90. else
  91. if WParam = DBT_DEVICEREMOVECOMPLETE then
  92. begin
  93. if Assigned(FDeviceRemoval) then
  94. FDeviceRemoval(Self,PChar(@Dbi.dbcc_name));
  95. end;
  96. end;
  97. except
  98. Result := DefWindowProc(hRecipient,LParam);
  99. end
  100. else
  101. Result := DefWindowProc(hRecipient,LParam);
  102. end;
  103.  
  104. destructor TDeviceNotifier.Destroy;
  105. begin
  106. UnregisterDeviceNotification(FNotificationHandle);
  107. DeallocateHWnd(hRecipient);
  108. inherited;
  109. end;
  110.  
  111.  
  112.  
  113. procedure TForm17.arrival(Sender: TObject; const DeviceName: String);
  114. begin
  115. ShowMessage(DeviceName);
  116. end;
  117.  
  118. procedure TForm17.FormCreate(Sender: TObject);
  119. const
  120. GUID_DEVINTERFACE_COMPORT : TGUID = '{86E0D1E0-8089-11D0-9CE4-08003E301F73}';
  121. begin
  122. DeviceNotifier:=TDeviceNotifier.Create(GUID_DEVINTERFACE_COMPORT);
  123. DeviceNotifier.FDeviceArrival:=arrival;
  124. end;
  125.  
  126. procedure TForm17.FormDestroy(Sender: TObject);
  127. begin
  128. DeviceNotifier.Free;
  129. end;
  130.  
  131. end.

猜你在找的Delphi相关文章