I have a small application that needs to react to a particular device being added or removed from the system. So I listen for WM_DEVICECHANGE
using CreateWindowEx()
and RegisterDeviceNotification()
.
This seems to work - however, I am left uncertain about how I properly check the message queue. This, in short, is my current approach:
procedure Main();
procedure HandleMessages(aWndHandle: HWND);
var
lpMsg: TMsg;
begin
while PeekMessage(lpMsg, aWndHandle, 0, 0, PM_REMOVE) do
DispatchMessage(lpMsg);
end;
begin
// ...
if (RegisterClassEx(wClass) = 0) then System.Exit;
wndHnd := CreateWindowEx(0, PChar(wClass.lpszClassName), nil, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, HInstance, nil);
// ...
notificationHandle := RegisterDeviceNotification(wndHnd, @bcInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
while True do
begin
HandleMessages();
DoThings();
HandleMessages();
DoOtherThings();
HandleMessages();
DoYetMoreThings();
end;
// ... (cleanup)
end;
Is this while True do
loop with repeated calls to HandleMessages()
viable? Or do I need to worry about some hidden problems - such as, if one of the DoThings()
routines were to take a long time to return?
It just seems somewhat awkward to me and I (suspiciously...) don't seem to be able to find any comparable examples online...
Edit: This application has no UI or console and no interaction. It reads the input from an HID scanner and needs to know if the scanner is removed or added to the system. It runs until the user logs off.
CodePudding user response:
As suggested in the comments, I have moved the window/messaging functionality to a separate thread and now use TEvent
to signal device change events to the main thread. This seems to be working well so far.
I have followed Remy's advice here (as well as other places) to create the window and queue in Execute()
and use DoTerminate()
for cleanup.