I created a WindowProc to be notified for system time changes:
constructor TJJWScheduler.Create;
begin
fTimeChangeWnd := Classes.AllocateHWnd(TimeChangeWndProc);
end;
procedure TJJWScheduler.TimeChangeWndProc(var msg: TMessage);
var
i: integer;
begin
case msg.Msg of
WM_TIMECHANGE:
begin
// my things
end;
end;
end;
This code is running inside a Windows Service. The problem is that it isn't fired when I change the system time!
Why not the broadcast message (WM_TIMECHANGE) isn't delivered to my window? There is another way to do this without a loop?
EDIT
I don't known why, but I hardcoded the PeekMessage to process messages to that window, and everything comes to work fine. The code below solved my problem:
var
msg: TMsg;
if PeekMessage(msg, fTimeChangeWnd, WM_TIMECHANGE, WM_TIMECHANGE, PM_REMOVE) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
This workaround is very strange, because I already have others windows processing messages (by generic ProcessMessages), only this one isn't processing its messages.
The reason your window was not receiving the WM_TIMECHANGE
messages is that your window is created from a secondary thread.
Each thread in a process has its own message queue. Synchronous messages are delivered when you service the message queue, so ever for a non-queued message like WM_TIMECHANGE
you do need to service the secondary threads message queue in order for messages to be delivered.
For example, look at the documentation for GetMessage
, the most common way to pull messages of the queue:
The function dispatches incoming sent messages until a posted message is available for retrieval.
The same is true for PeekMessage
. It dispatches incoming sent messages before peeking the queue.
There are a handful of other ways for sent messages to be dispatched, but these are the primary ones.
Now, I suspect that it may be inconvenient for you to periodically dispatch messages from your secondary thread. If your secondary thread does nothing else then it can simply sit in the traditional GetMessage
, TranslateMessage
, DispatchMessage
loop. And most of the time it will happily block in GetMessage
dispatching any incoming sent messages. But if your secondary thread does more work then that's probably not a viable option.
You are already running and servicing a message queue on the main service thread. It may make more sense to make your listener window have affinity with the main service thread. Do that by creating it from code that runs in the main service thread.
Note also that AllocateHWnd
is documented not to be thread-safe. You must not call it from any thread other than the main thread of the process. So, if you do wish to remain on a secondary thread, you'll need to use CreateWindow
rather than AllocateHWnd
. But this is perhaps yet another good reason to move this window onto the main thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With