Beim Schreiben von Programmen stoßen Sie immer auf Probleme mit der Kommunikation zwischen Form (tform) und der Thread -Nachricht (Thread). Was ärgerlich ist, ist, dass das Formular keine Nachrichten an den Thread (tThread) senden kann (der Thread hat keinen Fenstergriff). Nach mehreren Tagen harter Arbeit hatte ich zwei Lösungen und nahm sie heraus, um mit Ihnen zu besprechen.
Erste. Wir wissen, dass die MFC -Klassenbibliothek in VC ++ die Nachrichtenverarbeitung (BeginnMessage, EndMessage) in MFC eingedämmt hat Die Zuordnungstabelle (Nachrichtenverarbeitung ist im Wesentlichen ein Aufruf einer Methode oder eines Prozesses) sowie ein Nachrichtenverteilungsmechanismus, um den Empfang und die Übertragung von Nachrichten zu realisieren. Daher müssen wir nur eine Nachrichtenzuordnungstabelle für den Thread festlegen und einen entsprechenden Nachrichtenverteilungsmechanismus festlegen. Auf diese Weise können Sie Nachrichten verarbeiten, die über das Formular an den Thread gesendet werden. Der folgende Code ist eine Klasse, die die Tabelle und die Nachrichtenverteilung von Nachrichten zu Mapping implementiert (siehe <../ Nachrichtenverarbeitung Design (Thread) 1/MessageHandle.pas> Für Details))
Einheit MessageHandle;
Schnittstelle
Verwendet Nachrichten, Klassen, Systeme, Dialoge;
const pmsg_base = $ be00;
PMSG_NUM = 200;
{** benutzerdefinierte Nachrichtenverarbeitungsklasse
*; Funktion = Erstellen Sie eine benutzerdefinierte Nachrichtentabelle und einen Prozess zwischen Threads
* und benutzerdefinierte Nachrichten mit dem Hauptformular (Makro)
*}
// Message Processing -Handle
TmessageHandle = procedure (var message: tmessage) des Objekts;
TpDispatcher = class (tobject)
Privat
// Nachricht entsprechende Tabelle (Nachrichten -ID ist ein Array -Index);
MessageHandles: Array von TmessageHandle;
// Holen Sie sich die Array -ID aus der Nachrichten -ID
Funktion getIndexfrommsgid (const AmessageId: Kardinal): Ganzzahl;
öffentlich
Konstruktor erstellen;
Zerstörer zerstören;
// eine Nachricht senden
Prozedur sendMessage (var message: tmessage);
// Fügen Sie der entsprechenden Meldung eine benutzerdefinierte Nachricht hinzu.
Verfahren addHandle (const AmessageId: Kardinal; AmessageHandle: tmessageHandle);
Ende;
//
Durchführung
{TpDispatcher}
Konstruktor TPDispatcher.create;
var i: Ganzzahl;
Beginnen
SetLength (MessageHandles, PMSG_NUM);
// Initialisieren Sie die Nachrichtenwarteschlange;
für i: = 0 bis pred (pmsg_num) tun
MessageHandles [i]: = nil;
Ende;
destructor tpDispatcher.destroy;
Beginnen
{Release Message Korrespondence Tabelle}
Freeandnil (MessageHandles);
Ende;
procedure tpDispatcher.addHandle (const amessageId: kardinal;
amessageHandle: tmessageHandle);
var tid: Ganzzahl;
Beginnen
TID: = GetIndexfrommsgid (AmessageId);
ASSERT ((TID> 0) oder (TID <pred (pmsg_num)));
Assert (zugewiesen (AmessageHandle));
MessageHandles [TID]: = AmessageHandle;
Ende;
Funktion tpdispatcher.getIndexfrommsgid (const AmessageId: Kardinal): Integer;
Beginnen
Ergebnis: = AmessageId - pmsg_base;
Ende;
procedure tpDispatcher.sendMessage (var message: tmessage);
var tid: Ganzzahl;
tmsghandle: tmessageHandle;
Beginnen
TID: = GetIndexfrommsgid (message.msg);
ASSERT ((TID> 0) oder (TID <pred (pmsg_num)));
TMSGHandle: = MessageHandles [TID];
Wenn zugewiesen (TMSGHandle), dann
TMSGHandle (Nachricht);
Ende;
Jetzt müssen wir nur noch eine benutzerdefinierte Nachricht registrieren und dann die Nachrichtenverteilungsklasse (TPDispatcher) verwenden, um Threadnachrichten zu verarbeiten. Der Code lautet wie folgt <siehe ../ Message Processing Design (Thread) 1/Test/Unit1.pas> Für Details:
Einheit Einheit1
Const
{Benutzerdefinierte Langzeit-Thread-Nachricht}
My_message2 = pmsg_base + 02;
Typ
Tform1 = Klasse (tform)
Addmsglist: Tbutton;
SendThead: Tbutton;
SendForm: Tbutton;
Sendother: Tbutton;
Prozedur SENDTheadClick (Absender: Tobject);
Prozedur Formcreate (Absender: Tobject);
VerfahrensformularDestroy (Absender: Tobject);
Privat
FDispatcher: TPDispatcher;
Fhandle: Tphandler;
Fthread: tphread;
öffentlich
{Öffentliche Erklärungen}
Ende;
var
Form1: tform1;
Durchführung
{$ R *.dfm}
procedure tform1.sendtheadclick (Absender: tobject);
var amessage: tmessage;
amessage.msg: = my_message2;
amessage.wparam: = 1;
FDispatcher.sendMessage (Amessage);
Ende;
Ende;
procedure tform1.formcreate (Absender: tobject);
Beginnen
{Erstellen Sie eine Meldungstabelleklasse}}
FDispatcher: = tpDispatcher.create;
Fhandle: = tPhandler.create;
{Thread erstellen}
Fthread: = tphread.create (falsch);
{Meldung zur Zuordnungstabelle hinzufügen}
FDispatcher.addHandle (my_message2, fthread.Domessage);
Ende;
procedure tform1.FormDestroy (Absender: Tobject);
var i: Ganzzahl;
Beginnen
Freeandnil (fDispatcher);
Freeandnil (Fhandle);
für i: = 0 bis 3 tun
Freeandnil (fthread [i]);
Ende;
zweite. Ein Fenster kann Nachrichten verarbeiten, da es über einen Fenstergriff verfügt. Damit der Thread Meldungen verarbeiten kann, können wir dem Thread der entsprechenden Fensterklasse einen Fenstergriff hinzufügen. (Der Quellcode befindet sich in <../ Message Processing Design (Thread) 2 / pthread.pas>)
Einheit PThread;
Schnittstelle
Verwendet Klassen, Systeme, Fenster, Nachrichten, Dialoge;
const my_message1 = $ bd00 + 01;
Typ
{** Message Processing Thread Class
*; Funktion = Funktionenverarbeitungsfähigkeit hinzufügen,
*}
TpmsgThread = Klasse (tThread)
Privat
// Fensterhandle
Fwndhandle: hwnd;
// Fensterdateninformationen
FwndClass: wndClass;
// Zeiger auf Fenster -Rückruffunktion
FobjectInstance: Zeiger;
// Fensterdaten initialisieren
Verfahren initwnd;
// Erstellen Sie ein verstecktes Fenster
Verfahren createwnd;
// Verstecktes Fenster registrieren
Verfahren registriert;
Verfahren zerstören;
// Fenster -Rückruffunktion
Prozedur PWNDPROC (var message: tmessage);
geschützt
Verfahren ausführen;
Verfahren doterminat;
öffentlich
Konstruktor erstellen (erstellt: boolean);
Eigenschaft Wndhandle: hwnd lesen fwndhandle write fwndhandle;
Ende;
Durchführung
const wnd_name = 'py20';
{TpmsgThread}
Konstruktor tpmsgThread.create (erstellt: boolean);
Beginnen
erbte Erstellung (erstellt);
FwndHandle: = Integer (nil);
Initwnd;
Registisch;
Kreaturen;
Ende;
Verfahren tpmsgThread.Createwnd;
Beginnen
if (wndHandle = Integer (nil)) dann
WndHandle: = createwindow (fwndClass.lpsZClassName, fwndClass.lpsZClassName,
WS_POPUP oder WS_CAPTION oder WS_CLIPSIBLINGS oder WS_SYSMENU
oder WS_MinimizeBox,
GetSystemMetrics (SM_CXScreen) Div 2,
GetSystemMetrics (SM_CYSCYREEN) Div 2,
0, 0, 0, 0, fwndClass.Hinstance, nil);
// Fenster Rückruffunktion ersetzen
SetWindowlong (Wndhandle, gwl_wndproc, longint (fobjectInstance));
Ende;
procedure tpmsgThread.destroywnd;
Beginnen
UnregisterClass (fwndClass.lpsZClassName, fwndClass.Hinstance);
ZerstöreWindow (Wndhandle);
Ende;
Prozedur tpmsgThread.Doterminat;
Beginnen
geerbt;
Zerstören;
Ende;
procedure tpmsgThread.execute;
Beginnen
Ende;
procedure tpmsgThread.initwnd;
Beginnen
FwndClass.lpsZClassName: = pchar (Wnd_Name);
FwndClass.Hinstance: = Handle;
FwndClass.lpfnwndproc: = @defwindowProc;
Ende;
procedure tpmsgThread.pwndproc (var message: tmessage);
Beginnen
Ende;
procedure tpmsgThread.registWnd;
Beginnen
FOBjectInstance: = classes.MakeObjectInstance (pwndProc);
if (fwndClass.Hinstance <> Integer (nil)) dann
RegisterClass (fwndClass);
Ende;