【发布时间】:2022-01-04 16:05:17
【问题描述】:
我有一个小型应用程序,它需要对系统中添加或删除的特定设备做出反应。所以我使用CreateWindowEx() 和RegisterDeviceNotification() 收听WM_DEVICECHANGE。
这似乎可行 - 但是,我不确定如何正确检查消息队列。简而言之,这是我目前的做法:
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;
重复调用HandleMessages() 的while True do 循环是否可行?还是我需要担心一些隐藏的问题 - 例如,如果 DoThings() 例程之一需要很长时间才能返回?
这对我来说似乎有点尴尬,我(怀疑......)似乎无法在网上找到任何可比的例子......
编辑:此应用程序没有 UI 或控制台,也没有交互。它从 HID 扫描仪读取输入,并且需要知道扫描仪是否被移除或添加到系统中。它一直运行到用户注销为止。
【问题讨论】:
-
有一点需要注意:The dangers of filtering window messages。在任何情况下,我都会简单地将消息循环或中间工作移动到单独的线程,并通过
GetMessage()使用阻塞循环进行消息处理。但是,还有其他方法可以在不使用线程的情况下实现这一点。 -
@RemyLebeau 感谢您提供有关消息过滤的意见。我会改变的。将消息处理代码或“工作”代码移动到单独的线程是有意义的。但是,我希望避免引入线程以避免复杂性(并且,诚然,因为这可能会引发我的进一步问题,即如何正确地从线程传递信息或如何让它在卡在阻塞调用中时终止等等...)
-
在不了解程序架构的情况下很难为您提供建议。它有任何用户界面。它是一个控制台应用程序。它是否支持任何交互。它是如何启动和停止的。
-
@DavidHeffernan 我添加了其他信息。该程序应该无限期地运行。有一些错误情况会导致它自行终止。
标签: delphi message-queue message-handlers windowless