マイクロコントローラーと通信するには、シリアルポートを使用します。正常に動作するTCommPortDriver2.1を使用しています。ただし、新しいコンポートの追加または削除を検出する機能はありません。これは、セッション中に定期的に発生します。
コンポートが追加または削除されたことを知らせるイベントはありますか?
アップデート1
私はRRUZの最初の提案を試し、それをスタンドアロンプログラムに変えました。WM_DEVICECHANGE
ケーブルが差し込まれているとき、または差し込まれているときに反応しますがWParam
、デバイスの到着または取り外しは表示されません。結果は次のとおりです。
msg = 537, wparam = 7, lparam = 0
msg = 537, wparam = 7, lparam = 0
msg = 537, wparam = 7, lparam = 0
最初のメッセージはUSBケーブルが接続されているときに送信され、次の2つは接続されているときに送信されます。メッセージ部分にはWM_DEVICECHANGE
メッセージ(537)が表示されますがWParam
、7であり、WM_DEVICECHANGE
またはではありませんDBT_DEVICEARRIVAL
。メッセージを処理するためにコードを多少変更しましたが、LParam
ゼロであるため、これは役に立ちません。結果はVCLおよびFMXと同じです。チェックとして、以下のコードを参照してください。
アップデート2
これで、WMIコードが実行されました。COMポートが追加された場合にのみ起動し、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);
if Dbi.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, Msg, WParam, 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.