Delphi   发布时间:2022-04-11  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了delphi – 如何检测新串口的添加?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
要与微控制器通信,我使用串行端口.我使用TCommPortDriver 2.1工作正常.但是,它缺乏检测新组合的添加或删除的能力.这会在会话期间定期发生.

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

更新1

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

@H_863_8@msg = 537,wparam = 7,lparam = 0 msg = 537,lparam = 0

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

更新2

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

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

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

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

感谢RRUZ的代码和帮助!

unit dev_change;

  interface

  uses
    Winapi.Windows,Winapi.messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;

  type
    TProc = procedure (text: String) of object;

    BroadcastHdr  = ^DEv_broaDCAST_HDR;
    DEv_broaDCAST_HDR = packed record
      dbch_size: DWORD;
      dbch_deviCEType: DWORD;
      dbch_reserved: DWORD;
    end;
    TDevBroadcastHdr = DEv_broaDCAST_HDR;

  type
    PDevBroadcastDeviceInterface  = ^DEv_broaDCAST_DEVICEINTERFACE;
    DEv_broaDCAST_DEVICEINTERFACE = record
      dbcc_size: DWORD;
      dbcc_deviCEType: DWORD;
      dbcc_reserved: DWORD;
      dbcc_classguid: TGUID;
      dbcc_name: Char;
    end;
    TDevBroadcastDeviceInterface = DEv_broaDCAST_DEVICEINTERFACE;

  const
    DBT_DEVICESOMETHING        = $0007;
    DBT_DEVICEARRIVAL          = $8000;
    DBT_DEVICEREMOVECOMPLETE   = $8004;
    DBT_DEVTYP_DEVICEINTERFACE = $00000005;

  type
    TDeviceNotifyProc = procedure(Sender: TObject; const deviceName: String) of Object;
    TDeviceNotifier = class
    private
      hRecipient: HWND;
      FNotificationHandle: Pointer;
      FDeviceArrival: TDeviceNotifyProc;
      FDeviceRemoval: TDeviceNotifyProc;
      FOnWin: TProc;

      procedure WndProc(var Msg: TmessagE);

    public
      constructor Create(GUID_DEVINTERFACE : TGUID);
      property OnDeviceArrival: TDeviceNotifyProc read FDeviceArrival write FDeviceArrival;
      property OnDeviceRemoval: TDeviceNotifyProc read FDeviceRemoval write FDeviceRemoval;
      destructor Destroy; override;

      property OnWin: TProc read FOnWin write FOnWin;
    end;

    TForm1 = class(TForm)
      Memo: TMemo;
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
    private
      { Private declarations }
      DeviceNotifier : TDeviceNotifier;
    public
      { Public declarations }
      procedure arrival(Sender: TObject; const deviceName: String);
      procedure report (text: String);
    end;

  var
    Form1: TForm1;

  implementation

  {$R *.dfm}

  constructor TDeviceNotifier.Create(GUID_DEVINTERFACE : TGUID);
  var
    NotificationFilter: TDevBroadcastDeviceInterface;
  begin
    inherited Create;
    hRecipient := AllocateHWnd(WndProc);
    ZeroMemory (@NotificationFilter,SizeOf(NotificationFilter));
    NotificationFilter.dbcc_size := SizeOf(NotificationFilter);
    NotificationFilter.dbcc_deviCEType := DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid  := GUID_DEVINTERFACE;
    //register the device class to monitor
    FNotificationHandle := RegisterDeviceNotification(hRecipient,@NotificationFilter,DEVICE_NOTIFY_WINDOW_HANDLE);
  end;

  procedure TDeviceNotifier.WndProc(var Msg: TmessagE);
  var
    Dbi: PDevBroadcastDeviceInterface;
  begin
    OnWin (Format ('msg = %d,wparam = %d,lparam = %d',[msg.Msg,msg.WParam,msg.LParam]));
    with Msg do
    if (Msg = WM_DEVICECHANGE) and ((WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE) or
                                    (WParam = DBT_DEVICESOMETHING)) then
    try
      Dbi := PDevBroadcastDeviceInterface (LParam);
      @R_197_9792@bi.dbcc_deviCEType = DBT_DEVTYP_DEVICEINTERFACE then
      begin
        if WParam = DBT_DEVICEARRIVAL then
        begin
          if Assigned(FDeviceArrival) then
            FDeviceArrival(Self,PChar(@Dbi.dbcc_Name));
        end
        else
        if WParam = DBT_DEVICEREMOVECOMPLETE then
        begin
          if Assigned(FDeviceRemoval) then
            FDeviceRemoval(Self,PChar(@Dbi.dbcc_Name));
        end;
      end;
    except
      Result := DefWindowProc(hRecipient,Msg,WParam,LParam);
    end
    else
      Result := DefWindowProc(hRecipient,LParam);
  end;

  destructor TDeviceNotifier.Destroy;
  begin
    UnregisterDeviceNotification(FNotificationHandlE);
    DeallocateHWnd(hRecipient);
    inherited;
  end;

  procedure TForm1.arrival(Sender: TObject; const deviceName: String);
  begin
     report (deviceName);

     Showmessage(deviceName);
  end;

  procedure TForm1.FormCreate(Sender: TObject);
  const
    GUID_DEVINTERFACE_COMPORT  : TGUID = '{86E0D1E0-8089-11D0-9CE4-08003E301F73}';
  begin
    DeviceNotifier:=TDeviceNotifier.Create(GUID_DEVINTERFACE_COMPORT);
    DeviceNotifier.FDeviceArrival:=arrival;
    DeviceNotifier.onWin := report;
  end;

  procedure TForm1.FormDestroy(Sender: TObject);
  begin
    DeviceNotifier.Free;
  end;

  procedure TForm1.report (text: String);
  begin
     Memo.Lines.Add (text);
  end;

  end.

解决方法

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

试试这个样本.

type
  PDevBroadcastHdr  = ^DEv_broaDCAST_HDR;
  DEv_broaDCAST_HDR = packed record
    dbch_size: DWORD;
    dbch_deviCEType: DWORD;
    dbch_reserved: DWORD;
  end;
  TDevBroadcastHdr = DEv_broaDCAST_HDR;

type
  PDevBroadcastDeviceInterface  = ^DEv_broaDCAST_DEVICEINTERFACE;
  DEv_broaDCAST_DEVICEINTERFACE = record
    dbcc_size: DWORD;
    dbcc_deviCEType: DWORD;
    dbcc_reserved: DWORD;
    dbcc_classguid: TGUID;
    dbcc_name: Char;
  end;
  TDevBroadcastDeviceInterface = DEv_broaDCAST_DEVICEINTERFACE;

const
  DBT_DEVICEARRIVAL          = $8000;
  DBT_DEVICEREMOVECOMPLETE   = $8004;
  DBT_DEVTYP_DEVICEINTERFACE = $00000005;

type
  TDeviceNotifyProc = procedure(Sender: TObject; const deviceName: String) of Object;
  TDeviceNotifier = class
  private
    hRecipient: HWND;
    FNotificationHandle: Pointer;
    FDeviceArrival: TDeviceNotifyProc;
    FDeviceRemoval: TDeviceNotifyProc;
    procedure WndProc(var Msg: TmessagE);
  public
    constructor Create(GUID_DEVINTERFACE : TGUID);
    property OnDeviceArrival: TDeviceNotifyProc read FDeviceArrival write FDeviceArrival;
    property OnDeviceRemoval: TDeviceNotifyProc read FDeviceRemoval write FDeviceRemoval;
    destructor Destroy; override;
  end;

type
  TForm17 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    DeviceNotifier : TDeviceNotifier;
  public
    { Public declarations }
    procedure arrival(Sender: TObject; const deviceName: String);
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

constructor TDeviceNotifier.Create(GUID_DEVINTERFACE : TGUID);
var
  NotificationFilter: TDevBroadcastDeviceInterface;
begin
  inherited Create;
  hRecipient := AllocateHWnd(WndProc);
  ZeroMemory(@NotificationFilter,SizeOf(NotificationFilter));
  NotificationFilter.dbcc_size := SizeOf(NotificationFilter);
  NotificationFilter.dbcc_deviCEType := DBT_DEVTYP_DEVICEINTERFACE;
  NotificationFilter.dbcc_classguid  := GUID_DEVINTERFACE;
  //register the device class to monitor
  FNotificationHandle := RegisterDeviceNotification(hRecipient,DEVICE_NOTIFY_WINDOW_HANDLE);
end;

procedure TDeviceNotifier.WndProc(var Msg: TmessagE);
var
  Dbi: PDevBroadcastDeviceInterface;
begin
  with Msg do
  if (Msg = WM_DEVICECHANGE) and ((WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE)) then
  try
    Dbi := PDevBroadcastDeviceInterface(LParam);
    @R_197_9792@bi.dbcc_deviCEType = DBT_DEVTYP_DEVICEINTERFACE then
    begin
      if WParam = DBT_DEVICEARRIVAL then
      begin
        if Assigned(FDeviceArrival) then
          FDeviceArrival(Self,PChar(@Dbi.dbcc_Name));
      end
      else
      if WParam = DBT_DEVICEREMOVECOMPLETE then
      begin
        if Assigned(FDeviceRemoval) then
          FDeviceRemoval(Self,PChar(@Dbi.dbcc_Name));
      end;
    end;
  except
    Result := DefWindowProc(hRecipient,LParam);
  end
  else
    Result := DefWindowProc(hRecipient,LParam);
end;

destructor TDeviceNotifier.Destroy;
begin
  UnregisterDeviceNotification(FNotificationHandlE);
  DeallocateHWnd(hRecipient);
  inherited;
end;



procedure TForm17.arrival(Sender: TObject; const deviceName: String);
begin
  Showmessage(deviceName);
end;

procedure TForm17.FormCreate(Sender: TObject);
const
  GUID_DEVINTERFACE_COMPORT  : TGUID = '{86E0D1E0-8089-11D0-9CE4-08003E301F73}';
begin      
  DeviceNotifier:=TDeviceNotifier.Create(GUID_DEVINTERFACE_COMPORT);
  DeviceNotifier.FDeviceArrival:=arrival;
end;

procedure TForm17.FormDestroy(Sender: TObject);
begin
  DeviceNotifier.Free;
end;

end.

大佬总结

以上是大佬教程为你收集整理的delphi – 如何检测新串口的添加?全部内容,希望文章能够帮你解决delphi – 如何检测新串口的添加?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。