Добрый день.
Регистрирую обработчик WM_DEVICECHANGE и получаю DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE.
Вопрос: как узнать какое именно устройство подключалось и отключалось? Конкретно интерисует случай с USB устройствами HardwareID?
Или по крайнер мере как узнать его в этом обработчике?
А>Вопрос: как узнать какое именно устройство подключалось и отключалось? Конкретно интерисует случай с USB устройствами HardwareID?А>Или по крайнер мере как узнать его в этом обработчике?
Конкретно про USB.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, DBT;
type
TForm1 = class(TForm)
lbDevice: TListBox;
private// обработчик сообщения WM_DEVICECHANGEprocedure WMDEVICECHANGE(var Msg : TWMDeviceChange); message WM_DEVICECHANGE;
// получение имени дискаfunction GetDiskName(unitmask : Longint) : string;
public
end;
var
Form1: TForm1;
implementation{$R *.dfm}
{обработчик сообщения WM_DEVICECHANGE}procedure TForm1.WMDEVICECHANGE(var Msg: TWMDeviceChange);
var
lpdb : PDevBroadcastHdr;
lpdbv : PDevBroadcastVolume;
lpdbpr: PDevBroadCastPort;
begin{Заголовок сообщения}
lpdb := PDevBroadcastHdr(Msg.dwData);
{Отображаем код события}
lbDevice.Items.Add('Обнаружено событие. Код:'+IntToHex(Msg.Event, 4));
Case Msg.Event of
DBT_DEVICEARRIVAL: begin{Добавление}
lbDevice.Items.Add('>Добавлено устройство. Код:'+IntToHex(lpdb^.dbch_devicetype, 4));
{ Новое устройство - порт (последовательный или параллельный) }If lpdb^.dbch_devicetype = DBT_DEVTYP_PORT then begin
lpdbpr:= PDevBroadCastPort(Msg.dwData);
lbDevice.Items.Add('>>Добавлен порт. Имя:'+WideCharToString(@lpdbpr.dbcp_name));
End;
{ Новое устройство - логический диск }If lpdb^.dbch_devicetype = DBT_DEVTYP_VOLUME then begin
lpdbv := PDevBroadcastVolume(Msg.dwData);
lbDevice.Items.Add('>>Добавлен логический диск. Имя: '+GetDiskName(lpdbv.dbcv_unitmask));
End;
End;
DBT_DEVICEREMOVECOMPLETE: begin{Удаление}
lbDevice.Items.Add('>Удалено устройство. Код: '+IntToHex(lpdb^.dbch_devicetype, 4));
{ Удаленное устройство - порт (последовательный или параллельный) }If lpdb^.dbch_devicetype = DBT_DEVTYP_PORT then begin
lpdbpr:= PDevBroadCastPort(Msg.dwData);
lbDevice.Items.Add('>>Удален порт. Имя: '+WideCharToString(@lpdbpr.dbcp_name));
End;
{ Удаленное устройство - логический диск }If lpdb^.dbch_devicetype = DBT_DEVTYP_VOLUME then begin
lpdbv := PDevBroadcastVolume(Msg.dwData);
lbDevice.Items.Add('>>Удален логический диск. Имя: '+GetDiskName(lpdbv.dbcv_unitmask));
End;
End;
End;
end;
// Маска имени диска. Возвращаемое значение состоит из битов,
// соответствующих именам дисков:
// бит 0=A, бит 1=B, бит 3=C и т.д. function TForm1.GetDiskName(unitmask : Longint) : string;
var i : Integer;
begin
For i:= 0 to 26 do begin
if ((unitmask and 1) <> 0) then Break;
unitmask:= unitmask shr 1;
End;
Result:= Char(Integer('A')+i);
end;
end.
Модуль DBT.pas возьмите из JEDI.
На C#:
private System.Windows.Forms.ListBox listBox1;
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
const int WM_DEVICECHANGE = 0x0219;
const int DBT_DEVICEARRIVAL = 0x8000;
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_HDR
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE)
{
int EventCode = m.WParam.ToInt32();
Log(string.Format("WM_DEVICECHANGE. Код={0}", EventCode));
switch (EventCode)
{
case DBT_DEVICEARRIVAL:
{
Log("Добавление устройства");
break;
}
case DBT_DEVICEREMOVECOMPLETE:
{
Log("Удаление устройства");
break;
}
}
}
base.WndProc (ref m);
}
private void Log(string s)
{
listBox1.Items.Add(s);
listBox1.SelectedIndex = listBox1.Items.Count-1;
}
}
Здравствуйте, Pavel_Agurov, Вы писали:
P_A>Конкретно про USB.
Спасибо за Ваш ответ.
То что оно появилось или удалилось я и так знаю, мне не интересно какое это устройство диск, порт или еще что то, мне конкретно нужно знать какое устройство USB подключилось — его HARDWARE ID
Здравствуйте, Аноним,
А>Спасибо за Ваш ответ. А>То что оно появилось или удалилось я и так знаю, мне не интересно какое это устройство диск, порт или еще что то, мне конкретно нужно знать какое устройство USB подключилось — его HARDWARE ID
--
Можно попробовать определить HARWARE_ID нового устройства (кстати, а почему именно нужно знать HARDWARE_ID ?) следующим образом.
Напишите функцию перечисления всех устройств USB с помощью функций SetupDiXxx (SetupDiGetClassDevs, SetupDiEnumDeviceInfo) и получите для всех этих устройств их HARDWARE_ID (SetupDiGetDeviceRegistryProperty, SPDRP_HARDWAREID).
Вызовите эту функцию и запомните все эти HARDWARE_ID до регистрации получения WM_DEVICECHANGE. По появлению нового устройства вновь вызывайте эту функцию и сравнивайте вновь полученный список HARDWARE_ID с запомненным для нахождения новых HARDWARE_ID.
C уважением,
Геннадий Майко.
Re[4]: обработка WM_DEVICECHANGE
От:
Аноним
Дата:
13.05.06 16:21
Оценка:
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Здравствуйте, Аноним,
А>>Спасибо за Ваш ответ. А>>То что оно появилось или удалилось я и так знаю, мне не интересно какое это устройство диск, порт или еще что то, мне конкретно нужно знать какое устройство USB подключилось — его HARDWARE ID ГМ>-- ГМ>Можно попробовать определить HARWARE_ID нового устройства (кстати, а почему именно нужно знать HARDWARE_ID ?) следующим образом. ГМ>Напишите функцию перечисления всех устройств USB с помощью функций SetupDiXxx (SetupDiGetClassDevs, SetupDiEnumDeviceInfo) и получите для всех этих устройств их HARDWARE_ID (SetupDiGetDeviceRegistryProperty, SPDRP_HARDWAREID). ГМ>Вызовите эту функцию и запомните все эти HARDWARE_ID до регистрации получения WM_DEVICECHANGE. По появлению нового устройства вновь вызывайте эту функцию и сравнивайте вновь полученный список HARDWARE_ID с запомненным для нахождения новых HARDWARE_ID.
Так собсвенно и делаю, просто думал может есть какой то способ внутри обработчика узнать от системы какое устройство подключилось или отключилось.
ГМ>C уважением, ГМ>Геннадий Майко.
Извините, не понял сразу. Действительно Вы спросили про ID
Вот такой код, надеюсь подойдет. Я правда его Name обозвал, в общем смысл — что имя передается в поле dbcc_name.
unit U_Usb;
interface
uses
Windows, Messages, SysUtils, Classes, Forms;
type
TNotifyUSBEvent = procedure(Sender: TObject; Name : String) of object;
PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
DEV_BROADCAST_HDR = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
end;
PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
DEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size: DWORD;
dbcc_devicetype: DWORD;
dbcc_reserved: DWORD;
dbcc_classguid: TGUID;
dbcc_name: Array [1..1024] of char;
end;
const
GUID_DEVINTERFACE_USB_DEVICE: TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
DBT_DEVICEARRIVAL = $8000; // system detected a new device
DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone
DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface classtype
TComponentUSB = class(TComponent)
private
FWindowHandle: HWND;
FOnUSBArrival: TNotifyUSBEvent;
FOnUSBRemove: TNotifyUSBEvent;
procedure WndProc(var Msg: TMessage);
function USBRegister: Boolean;
protected
procedure WMDeviceChange(var Msg: TMessage); dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnUSBArrival: TNotifyUSBEvent read FOnUSBArrival write FOnUSBArrival;
property OnUSBRemove: TNotifyUSBEvent read FOnUSBRemove write FOnUSBRemove;
end;
implementation
constructor TComponentUSB.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowHandle := AllocateHWnd(WndProc);
USBRegister;
end;
destructor TComponentUSB.Destroy;
begin
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;
procedure TComponentUSB.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_DEVICECHANGE) then
begin
try
WMDeviceChange(Msg);
except
Application.HandleException(Self);
end;
end
else
Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;
procedure TComponentUSB.WMDeviceChange(var Msg: TMessage);
var
devType: Integer;
Datos: PDevBroadcastHdr;
Device : PDevBroadcastDeviceInterface;
Name : String;
begin
if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE) then
begin
Datos := PDevBroadcastHdr(Msg.lParam);
devType := Datos^.dbch_devicetype;
if devType = DBT_DEVTYP_DEVICEINTERFACE then
begin// USB Deviceif Msg.wParam = DBT_DEVICEARRIVAL then
begin
Device:= PDevBroadcastDeviceInterface(Msg.LParam);
Name:= Device^.dbcc_name;
if Assigned(FOnUSBArrival) then
FOnUSBArrival(Self, Name);
end
else
begin
Device:= PDevBroadcastDeviceInterface(Msg.LParam);
Name:= Device^.dbcc_name;
if Assigned(FOnUSBRemove) then
FOnUSBRemove(Self, Name);
end;
end;
end;
end;
function TComponentUSB.USBRegister: Boolean;
var
dbi: DEV_BROADCAST_DEVICEINTERFACE;
Size: Integer;
r: Pointer;
begin
Result := False;
Size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
ZeroMemory(@dbi, Size);
dbi.dbcc_size := Size;
dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_reserved := 0;
dbi.dbcc_classguid := GUID_DEVINTERFACE_USB_DEVICE;
r := RegisterDeviceNotification(FWindowHandle, @dbi,
DEVICE_NOTIFY_WINDOW_HANDLE
);
if Assigned(r) then Result := True;
end;
end.
Используется так:
procedure TForm1.FormCreate(Sender: TObject);
begin
USB:= TComponentUSB.Create(Self);
USB.OnUSBArrival:= OnUSBArrival;
USB.OnUSBRemove := OnUSBRemove;
end;
procedure TForm1.OnUSBArrival(Sender: TObject; Name : String);
begin
lbDevice.Items.Add('OnUSBArrival>'+Name);
end;
procedure TForm1.OnUSBRemove(Sender: TObject; Name : String);
begin
lbDevice.Items.Add('OnUSBRemove>'+Name);
end;
Re[4]: обработка WM_DEVICECHANGE
От:
Аноним
Дата:
13.05.06 17:40
Оценка:
Здравствуйте, Pavel_Agurov, Вы писали:
P_A>Извините, не понял сразу. Действительно Вы спросили про ID
P_A>Вот такой код, надеюсь подойдет. Я правда его Name обозвал, в общем смысл — что имя передается в поле dbcc_name.