Unit WakeMeSoon; { Use this to queue up a message. The message has no payload, it is a simple wakeup message. If multiple messages are sent before the first message is received, the messages will typically be combined into one message. This is always the case if RequestWakeup is only called from the main GUI thread. If other threads try call RequestWakeup, it's possible to get additional wakeup messages, but you will never loose a message. One purpose of this unit is to consolidate responses. Image you have a complicated object with a lot of individual properties. A caller might change many of the properties one at a time. You immediately record the requests, but you don't want to take any action until you've seen the group of these. One option is to force the caller to call BeginUpdate and EndUpdate on your object. Using this unit provides a simpler interface to the caller. Each time the caller changes a property, you send a wakeup request. Then, when you receive the wakeup request, you can finally take action. This unit can also be used to allow other threads to send a simple message to the GUI thread. For example, another thread can add one or more items to a thread-safe queue, then send a wakup call to the GUI thread. The GUI thread will know to look at the queue. The callback function is always called in the main GUI thread. } Interface Uses Classes, Windows, Messages; Type TWakeMeSoon = Class(TObject) Private FOnWakeUp : TThreadMethod; FWindowHandle : HWND; WakeupPending : Boolean; Procedure WndProc(Var Msg : TMessage); Public Property OnWakeUp : TThreadMethod Read FOnWakeUp Write FOnWakeUp; Constructor Create; Destructor Destroy; Override; // This function is thread safe. Procedure RequestWakeup; End; Implementation Uses MiscDebugWindows, SysUtils; Const CM_WAKEUP = WM_USER + 1; Constructor TWakeMeSoon.Create; Begin FWindowHandle := AllocateHWnd(WndProc) End; Destructor TWakeMeSoon.Destroy; Begin DeallocateHWnd(FWindowHandle) End; Procedure TWakeMeSoon.WndProc(Var Msg : TMessage); Begin If Msg.Msg = CM_WAKEUP Then Try WakeupPending := False; If Assigned(FOnWakeup) Then FOnWakeup Except On Ex : Exception Do SendMiscDebugMessage(Ex, 'WakeMeSoon, TWakeMeSoon.WndPrc') End Else With Msg Do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam) End; Procedure TWakeMeSoon.RequestWakeup; Begin If Not WakeupPending Then Begin WakeupPending := True; PostMessage(FWindowHandle, CM_WAKEUP, 0, 0) End End; End.