I have a Delphi 6 application that has a thread dedicated to communicating with a foreign application that uses SendMessage() and WM_COPYDATA messages to interface with external programs. Therefore, I create a hidden window with AllocateHWND() to service that need since a thread message queue won't work due to the SendMessage() function only accepting window handles, not thread IDs. What I'm not sure about is what to put in the thread Execute() method.
I assume that if I use a GetMessage() loop or a create a loop with a WaitFor*() function call in it that the thread will block and therefore the thread's WndProc() will never process the SendMessage() messages from the foreign program right? If so, what is the correct code to put in an Execute() loop that will not consume CPU cycles unnecessarily but will exit once a WM_QUIT message is received? I can always do a loop with a Sleep() if necessary but I'm wondering if there is a better way.
Here is a loop that doesn't require Classes.pas and relies solely on System.pas for some auxiliary functions, Windows.pas for Win32 API functions and Messages.pas for the WM_ constants.
Please note that the window handle here is created and destroyed from the worker thread, but the main thread waits until the worker thread completes the initialization. You can postpone this wait until a later moment, when you actually need the window handle, so the main thread may do some work in the meanwhile, while the worker thread sets itself up.
AllocateHWnd()
(more specifically,MakeObjectInstance()
) is not thread-safe, so you have to be careful with it. Better to useCreatWindow/Ex()
directly instead (or a thread-safe version ofAllocateHWnd()
, likeDSiAllocateHwnd()
.In any case, an
HWND
is tied to the thread context that creates it, so you have to create and destroy theHWND
inside yourExecute()
method, not in the thread's constructor/destructor. Also, even thoughSendMessage()
is being used to send the messages to you, they are coming from another process, so they will not be processed by yourHWND
until its owning thread performs message retrieval operations, so the thread needs its own message loop.Your
Execute()
method should look something like this:Alternatively: