WinRat
asked on
Improve code for detecting USB drive insertion & removal
Dear Experts,
Please refer to the included code which detects when a USB device is connected or disconnected.
It worked perfectly for me. As you can see it handles the Windows message WM_DEVICECHANGE.
However as it stands its not that flexible for easily adding to a project..
It would be nice to have this in a self-contained unit that generates suitable events when a USB device is attached or removed. I would prefer that it not be made into a component that I have to install, in order to produce more portable code.
I don't know if its possible to handle a message without a form, but maybe it could be a small non-visible dummy form.
If it seems possible I would appreciate a working Delphi 5 compatible version.
Many thanks!
Please refer to the included code which detects when a USB device is connected or disconnected.
It worked perfectly for me. As you can see it handles the Windows message WM_DEVICECHANGE.
However as it stands its not that flexible for easily adding to a project..
It would be nice to have this in a self-contained unit that generates suitable events when a USB device is attached or removed. I would prefer that it not be made into a component that I have to install, in order to produce more portable code.
I don't know if its possible to handle a message without a form, but maybe it could be a small non-visible dummy form.
If it seems possible I would appreciate a working Delphi 5 compatible version.
Many thanks!
unit USBDetectF;
{taken from an Experts Exchange solution:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/
Q_21552015.html?sfQueryTermInfo=1+drive+letter+usb
ginsonic:
Here is a complete sample project. Use a form and a label.
}
interface
uses
Windows, Messages, Classes, Forms, Controls, StdCtrls, Buttons;
type
TUSBDetectForm = class(TForm)
Label1: TLabel;
BitBtn1: TBitBtn;
Label2: TLabel;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
protected
procedure WMDEVICECHANGE(var Msg: TMessage); message WM_DEVICECHANGE;
public
{ Public declarations }
end;
var
USBDetectForm: TUSBDetectForm;
{----------------------------------------------------------------------------}
// Device constants
const
DBT_DEVICEARRIVAL = $00008000;
DBT_DEVICEREMOVECOMPLETE = $00008004;
DBT_DEVTYP_VOLUME = $00000002;
// Device structs
type
_DEV_BROADCAST_HDR = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
end;
DEV_BROADCAST_HDR = _DEV_BROADCAST_HDR;
TDevBroadcastHeader = DEV_BROADCAST_HDR;
PDevBroadcastHeader = ^TDevBroadcastHeader;
type
_DEV_BROADCAST_VOLUME = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
dbcv_unitmask: DWORD;
dbcv_flags: WORD;
end;
DEV_BROADCAST_VOLUME = _DEV_BROADCAST_VOLUME;
TDevBroadcastVolume = DEV_BROADCAST_VOLUME;
PDevBroadcastVolume = ^TDevBroadcastVolume;
implementation
{$R *.dfm}
procedure TUSBDetectForm.WMDEVICECHANGE(var Msg: TMessage);
var lpdbhHeader: PDevBroadcastHeader;
lpdbvData: PDevBroadcastVolume;
dwIndex: Integer;
lpszDrive: String;
begin
// Perform inherited
inherited;
// Get the device notification header
lpdbhHeader:=PDevBroadcastHeader(Msg.lParam);
// Handle the message
lpszDrive:='Drive ';
case Msg.WParam of
DBT_DEVICEARRIVAL : {a USB drive was connected}
begin
if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
begin
lpdbvData:=PDevBroadcastVolume(Msg.lParam);
for dwIndex :=0 to 25 do
begin
if ((lpdbvData^.dbcv_unitmask shr dwIndex) = 1) then
begin
lpszDrive:=lpszDrive+Chr(65+dwIndex)+':';
break;
end;
end;
Label1.Caption:=lpszDrive + ' connected';
end;
end;
DBT_DEVICEREMOVECOMPLETE: {a USB drive was removed}
begin
if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
begin
lpdbvData:=PDevBroadcastVolume(Msg.lParam);
for dwIndex:=0 to 25 do
begin
if ((lpdbvData^.dbcv_unitmask shr dwIndex) = 1) then
begin
lpszDrive:=lpszDrive+Chr(65+dwIndex)+':';
break;
end;
end;
Label1.Caption:=lpszDrive + ' removed';
end;
end;
end;
end;
procedure TUSBDetectForm.FormCreate(Sender: TObject);
begin
Label1.Caption := '';
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi!
Thanks for a great solution that does *exactly* what I wanted! So nice to get a solution where you can just copy and paste it into Delphi without having to add missing identifiers or debug it first! I just made a minor change to suit my preferences (to the returned Drive string)
Some of your code is outside my Delphi level so it will be great to go through it and learn some new techniques.
Mike
Thanks for a great solution that does *exactly* what I wanted! So nice to get a solution where you can just copy and paste it into Delphi without having to add missing identifiers or debug it first! I just made a minor change to suit my preferences (to the returned Drive string)
Some of your code is outside my Delphi level so it will be great to go through it and learn some new techniques.
Mike
a bit of basic component creation with a window message loop
glad to be of service
if you need more help, just let me know
glad to be of service
if you need more help, just let me know
use below snippet like :
uses UsbDetector, StrUtils;
procedure TForm1.Usb(Sender: TObject; Drive: string; Attached: boolean);
begin
ShowMessage(Drive + IfThen(Attached, 'connected', 'disconnected'));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
StartUsbDetector(Usb);
end;
Open in new window