is it possible to add usb detection to a formless (dpr only) Delphi Program? I have written the detection class but it seems to work only when I add a form to the program.
Here is the class
unit uMyUSB;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
Winapi.ShellApi, Vcl.Dialogs;
// Start of Declarations
const
DBT_DEVICEARRIVAL = $00008000;
DBT_DEVICEREMOVECOMPLETE = $00008004;
DBT_DEVTYP_VOLUME = $00000002;
DBTF_MEDIA = $00000001;
USB_INTERFACE = $00000005;
// Device structs
type
PDevBroadcastDeviceInterface = ^_DEV_BROADCAST_HDR;
_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;
// End of Declarations
type
TUSB = class(TObject)
private
FHandle: HWND;
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;
procedure WinMethod(var Msg: TMessage);
procedure RegisterUsbHandler;
{ Public declarations }
public
{ Public declarations }
constructor Create();
destructor Destroy(); override;
end;
implementation
constructor TUSB.Create();
begin
inherited Create;
FHandle := AllocateHWnd(WinMethod);
RegisterUsbHandler;
end;
destructor TUSB.Destroy();
begin
DeallocateHWnd(FHandle);
inherited Destroy;
end;
procedure TUSB.WinMethod(var Msg: TMessage);
begin
if (Msg.Msg = WM_DEVICECHANGE) then
begin
WMDeviceChange(Msg);
end
else
begin
Msg.Result := DefWindowProc(FHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
end;
procedure TUSB.RegisterUsbHandler;
var
rDbi: _DEV_BROADCAST_HDR;
iSize: Integer;
begin
iSize := SizeOf(_DEV_BROADCAST_HDR);
ZeroMemory(@rDbi, iSize);
rDbi.dbch_size := iSize;
rDbi.dbch_devicetype := USB_INTERFACE;
rDbi.dbch_reserved := 0;
RegisterDeviceNotification(FHandle, @rDbi, DEVICE_NOTIFY_WINDOW_HANDLE);
end;
procedure TUSB.WMDeviceChange(var Msg: TMessage);
var
lpdbhHeader: PDevBroadcastHeader;
begin
lpdbhHeader := PDevBroadcastHeader(Msg.LParam);
case Msg.WParam of
DBT_DEVICEARRIVAL:
begin
if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
begin
ShowMessage('Inserted');
end;
end;
DBT_DEVICEREMOVECOMPLETE:
begin
if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
begin
ShowMessage('Removed');
end;
end;
end;
end;
and Here is the TestUnit
// My dpr Program
program TestUSB;
uses
System.SysUtils,
System.Classes,
uMyUSB in 'Sources\uMyUSB.pas';
{$R *.res}
var
FUSB: TUSB;
begin
{$WARNINGS OFF}
ReportMemoryLeaksOnShutdown := DebugHook <> 0;
{$WARNINGS ON}
FUSB := TUSB.Create();
// Loop to keep the Program Running Continually.
while 1 = 1 do
begin
// Do Something
end;
FreeandNil(CustomUsb);
end.
How can I make a formless program accept USB change (WM_DEVICECHANGE) commands?
Thanks a Lot.
Delphi XE7.
答案 0 :(得分:3)
虽然消息是同步的,即非排队的,但您需要调度消息以便传递同步消息。通常,当您调用GetMessage
或类似函数时,消息循环将完成消息调度。
您的应用程序没有消息循环,也不会分发消息。您只需要安排您的程序发送消息。添加消息循环就可以了。但是你只需要做一些调度消息的事情。不需要成为一个完整的消息循环。例如,你可以用以下代码替换你的循环:
while True do
SendMessage(hwnd, WM_NULL, 0, 0);
这可以满足您的需求,因为SendMessage
是分发消息的功能之一。
您需要决定使用哪个窗口句柄。您可以使用您创建的窗口句柄。或者您可以将消息发送到值为0
的无效窗口句柄。
或者您可以决定运行标准的消息循环:
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;