When you write a process, you always touch the form (TSTREAD) message communication problem. What is annoying is that the form cannot send messages to threads (threads no window handle). After a few days of toss, I came up with two solutions, and I took out to discuss it.
the first. We know that the MFC class library in VC is self-encapsulated message processing, and the processing of messages in the MFC is to save the address or process (Procedure) address. In the mapping table (message processing is essentially the method or process call), plus a message distribution mechanism to implement the message's reception to send
Unit MessageHandle;
Interface
Uses Messages, Classes, Sysutils, Dialogs;
Const PMSG_BASE = $ BE00; / / Custom Message Extracry;
PMSG_NUM = 200; // Message Table Size;
{** Custom Message Processing Class
*; Function = set a custom message table and process threads
* And custom messages between the main form (macro)
*}
// Message handle handle
TMESSAGEHANDE = procedure (var message: tMessage) OF Object;
TPDispatcher = Class (TOBJECT)
Private
// Message correspondence table (message ID is a quaternary subscript);
MessageHandles: array of tMessageHandle;
// Get the array ID from the message ID
Function getIndexfrommsgid (const amessageid: cardinal): Integer;
public
Constructor crete;
DESTRUCTOR DESTROY;
//send messages
Procedure SendMessage (Var Message: tMessage; Overload;
// Add a custom message to the message corresponding table;
Procedure addhandle (const amessageid: cardinal; amessagehandle: tMessageHandle);
END;
//
IMPLEMENTATION
{TPDISPATCHER}
Constructor tpdispatcher.create;
VAR i: integer;
Begin
SETLENGTH (MessageHandles, PMSG_NUM); // 200 message correspondence table
// Initialize the message queue;
For i: = 0 to PRED (PMSG_NUM) DO
MessageHandles [I]: = NIL;
END;
DESTRUCTOR TPDISPATCHER.DESTROY;
Begin
{Release message correspondence table}
Freeandnil (MessageHandles);
END;
Procedure tpdispatcher.addhandle (const amessage): cardinal
AMESSAGEHANDLE: TMESSAGEHANDLE;
VAR TID: INTEGER;
Begintid: = getIndexFromMSGID (AMESSAGEID);
Assert ((TID> 0) OR (TID Assign (AMessageHandle); MessageHandles [TID]: = AMESSAGEHANDLE; END; Function TPDispatcher.getIndexFromMSGID (Const AmessageId: Cardinal): Integer; Begin Result: = AMESSAGEID - PMSG_BASE; END; Procedure TPDispatcher.sendMessage (Var Message: tMessage); VAR TID: INTEGER; TMSGHANDLE: TMSGHENDLE: TMESSAGEHANDLE; Begin TID: = getIndexfrommsgid (message.msg); Assert ((TID> 0) OR (TID TMSGHANDLE: = MessageHandles [TID]; IF Assigned (TMSGHandle) THEN TMSGHANDLE (MESSAGE); END; Now we only need to register a custom message, then through the message distribution class (TPDispatcher), implement processing of thread messages. The code is as follows Unit Unit1 Const {Customary thread message} MY_MESSAGE2 = PMSG_Base 02; Type TFORM1 = Class (TFORM) AddMsglist: tbutton; Sendthead: tbutton; Sendform: tbutton; Sendother: tbutton; Procedure sendtheadclick (sender: TOBJECT); // Send a message Procedure formcreate (Sender: TOBJECT); Procedure FormDestroy (Sender: TOBJECT); Private FDISPATCHER: TPDISPATCHER; message mapping table class FHANDE: TPHANDLER; FTHREAD: TPTHREAD; custom thread class public {Public declarations} END; VAR FORM1: TFORM1; IMPLEMENTATION {$ R * .dfm} Procedure TFORM1.SendtheadClick (Sender: TOBJECT); Var Amessage: TMessage; Begin AMESSAGE.MSG: = my_Message2; AMessage.wParam: = 1; FDispatcher.sendMessage (AMESSAGE); END; END; Procedure TFORM1.FormCreate (Sender: TOBJECT); Begin {Create message mapping table class} FDISPATCHER: = TPDISPATCHER.CREATE FHANDE: = TPHANDLER.CREATE; {Create thread} FTHREAD: = tpthread.create (false); {Add a message to the mapping table} Fdispatcher.addhandle (my_message2, fthread.domessage); END; Procedure TForm1.FormDestroy (Sender: TOBJECT); VAR i: integer; Begin Freeandnil (FDISPATCHER); Freeandnil (FHANDLE); For i: = 0 to 3 do Freeandnil (fThread [i]); END; second. The window can handle the message because it has a window handle. In order to make the thread to process the message, we can add a window license of a corresponding window class by adding a thread. (Source code in <../ message processing design (thread) 2 / pthread.pas>) Unit pthread; Interface Uses Classes, Sysutils, Windows, Messages, Dialogs; Const my_message1 = $ bd00 01; Type {** message processing thread class *; Function = Add thread process capability, *} TPMSGTHREAD = Class (TTHREAD) Private // Window handle FWndHandle: hwnd; // Window data information FWNDCLASS: WNDCLASS; // Pointer to the window callback function FOBJECTINSTANCE: POINTER; // Initialization window data Procedure initwnd; // Create a hidden window PROCEDURE CREATEWND; // Register the hidden window PROCEDURE registWnd; Procedure destroywnd; // Window callback function Procedure PWNDPROC (VAR Message: tMessage); Virtual; protected Procedure execute; override; Procedure Doterminate; Override; public Constructor Create (CreateSuspended: Boolean); Virtual; Property WNDHANDLE: HWND Read FWndHandle Write FwndHandle; END; IMPLEMENTATION Const WND_NAME = 'PY20'; {Tpmsgthread} Constructor TPMSGTHREAD.CREATE (CREATESUSPENDED: BOOLEAN); Begin Inherited Create (createSuspend); FWndHandle: = Integer (NIL); Initwnd; Registwnd; CREATEWND; END; PROCEDURE TPMSGTHREAD.CREATEWND; Begin IF (WNDHANDLE = Integer (NIL)) THEN WNDHANDLE: = CREATEWINDOW (fwndclass.lpszclassname, fwndclass.lpszclassname, WS_POPUP or WS_CAPTION or WS_CLIPSIBLINGS OR WS_SYSMENU Or ws_minimizebox, GetSystemMetrics (SM_CXSCREEN) DIV 2, GetSystemMetrics (SM_CYSCREEN) DIV 2, 0, 0, 0, 0, fWndclass.hinstance, NIL); // Replace window callback function SetWindowlong (WndHandle, GWL_WndProc, Longint (FOBJECTINSTANCE)); END; Procedure TPMSGTHREAD.DESTROYWND; Begin UnregisterClass (fwndclass.lpszclassname, fwndclass.hinstance); DestroyWindow (WNDHANDLE); END; Procedure tpmsgthread.doterminate; Begin inherited; DESTROYWND; END; Procedure TPMSGTHREAD.EXECUTE; Begin END; Procedure tpmsgthread.initwnd; Begin FWndClass.lpszclassName: = PCHAR (WND_NAME); FWNDCLASS.HINSTANCE: = Handle; FWNDCLASS.LPFNWNDPROC: = @defwindowproc; END; Procedure TPMSGTHREAD.PWNDPROC (Var Message: TMESSAGE); Begin END; Procedure TPMSGTHREAD.REGISTWND; Begin FOBJECTINSTANCE: = Classes.makeObjectInstance (PWNDPROC); IF (fWndclass.hinstance <> integer (nil)) THEN RegisterClass (FWNDCLASS); END;