-1

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.

emno
  • 161
  • 1
  • 9
  • 1
    One thing to be aware of: [The dangers of filtering window messages](https://devblogs.microsoft.com/oldnewthing/20050209-00/?p=36493). In any case, I would simply move either the message loop or the in-between work to a separate thread, and use a blocking loop via `GetMessage()` for the message processing. But, there are other ways to implement this without using threads. – Remy Lebeau Nov 26 '21 at 19:04
  • @RemyLebeau Thanks for the input regarding message filtering. I will change that. Moving the message handling code or "work" code to a separate thread makes sense. However, I was hoping to avoid introducing threads to avoid complexity (and, admittedly, because that would probably raise further questions on my end about how to properly pass information from the thread or how to get it to terminate while it's stuck in a blocking call etc...) – emno Nov 26 '21 at 19:37
  • Hard to advise you without knowing about your program's architecture. Does it have any UI. Is it a console app. Does it support any interaction. How is it started and stopped. – David Heffernan Nov 27 '21 at 06:27
  • @DavidHeffernan I have added additional info. The program is supposed to run indefinitely. There are some error conditions that will cause it to self-terminate. – emno Nov 27 '21 at 17:54

1 Answers1

0

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.

emno
  • 161
  • 1
  • 9