Delphi message processing of threads

xiaoxiao2021-03-06  41

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 . So we just create a message mapping table in the thread and establish a corresponding message distribution mechanism. This will handle the form of the message to the thread. The following code is a class that implements message mapping tables and messages (see <../ message processing design (thread) 1 / MessageHandle.Pas>)

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;

转载请注明原文地址:https://www.9cbs.com/read-53046.html

New Post(0)