Al escribir programas, siempre encuentra problemas con la comunicación entre el mensaje de formulario (TFORM) y el hilo (tthread). Lo que es molesto es que el formulario no puede enviar mensajes al hilo (tthread) (el hilo no tiene un mango de ventana). Después de varios días de arduo trabajo, se me ocurrió dos soluciones y las llevé a discutir con usted.
Primero. Sabemos que la biblioteca de clases MFC en VC ++ ha encapsulado el procesamiento de mensajes (BeginMessage, EndMessage). La tabla de mapeo (el procesamiento de mensajes es esencialmente una llamada a un método o proceso), más un mecanismo de distribución de mensajes para realizar la recepción y transmisión de mensajes <Consulte VC ++ Insider Technical para obtener más detalles. Por lo tanto, solo necesitamos establecer una tabla de mapeo de mensajes para el hilo y establecer un mecanismo de distribución de mensajes correspondiente. Esto le permite procesar los mensajes enviados por el formulario al hilo. El siguiente código es una clase que implementa la tabla de asignación de mensajes y la distribución de mensajes (consulte <../ Diseño de procesamiento de mensajes (hilo) 1/MessageHandle.pas> Para más detalles)
Unidad MessageHandle;
interfaz
usa mensajes, clases, sysutils, diálogos;
const PMSG_Base = $ Be00;
PMSG_NUM = 200; // Tamaño de la tabla de mensajes;
{** Clase de procesamiento de mensajes personalizados
*; Function = Crear una tabla de mensajes personalizada y un proceso entre hilos
* y mensajes personalizados con el formulario principal (macro)
*}
// Mango de procesamiento de mensajes
TMessageHandle = procedimiento (mensaje var: tmessage) de objeto;
Tpdispatcher = class (tobject)
Privado
// La tabla correspondiente del mensaje (el ID del mensaje es un subíndice de matriz);
MessageHandles: matriz de TMessageHandle;
// Obtener la ID de matriz de la ID del mensaje
función getIndexfrommsgid (const amessageID: cardinal): integer;
público
constructor crear;
destructor destruir;
// Enviar un mensaje
Procedimiento SendMessage (Mensaje VAR: TMessage);
// Agregar un mensaje personalizado a la tabla correspondiente del mensaje;
procedimiento addHandle (const amessageid: cardenal; amessagehandle: tMessageHandle);
fin;
//
Implementación
{Tpdispatcher}
constructor tpdispatcher.create;
var i: entero;
Comenzar
SetLength (MessageHandles, PMSG_NUM);
// Inicializar la cola de mensajes;
para i: = 0 a pred (pmsg_num) hacer
MessageHandles [i]: = nil;
fin;
destructor tpdispatcher.destroy;
Comenzar
{Tabla de correspondencia de mensaje de lanzamiento}
Freeandnil (MessageHandles);
fin;
procedimiento tpdispatcher.addhandle (const amessageid: cardinal;
AmessageHandle: tMessageHandle);
var tid: entero;
Comenzar
tid: = getIndexfrommsgid (amessageID);
Afirmar ((tid> 0) o (tid <pred (pmsg_num)));
Afirmar (asignado (amessageHandle));
MessageHandles [tid]: = amessageHandle;
fin;
función tpdispatcher.getIndexfrommsgid (const amessageID: cardinal): integer;
Comenzar
Resultado: = amessageId - pmsg_base;
fin;
procedimiento tpdispatcher.sendMessage (mensaje var: tmessage);
var tid: entero;
TMSGHANDLE: TMessageHandle;
Comenzar
tid: = getIndexfrommsgid (Message.msg);
Afirmar ((tid> 0) o (tid <pred (pmsg_num)));
tmsghandle: = MessageHandles [tid];
Si se asigna (tmsghandle) entonces
tmsghandle (mensaje);
fin;
Ahora solo necesitamos registrar un mensaje personalizado y luego usar la clase de distribución de mensajes (TPDISPatcher) para procesar los mensajes de subprocesos. El código es el siguiente <Ver ../ Diseño de procesamiento de mensajes (hilo) 1/test/unit1.pas> Para más detalles:
Unidad Unidad1
estúpido
{Mensaje de hilo a largo plazo personalizado}
My_message2 = pmsg_base + 02;
tipo
TForm1 = class (tForm)
Addmsglist: tbutton;
SendThehead: tbutton;
SendForm: tbutton;
Sendother: tbutton;
procedimiento sendTheadClick (remitente: tobject);
procedimiento formulcreate (remitente: tobject);
procedimiento FormDestrOY (remitente: tobject);
Privado
FDISPATHER: TPDISPATCHER;
Fhandle: tphandler;
Fthread: tpthread;
público
{Declaraciones públicas}
fin;
varilla
Form1: tform1;
Implementación
{$ R *.dfm}
procedimiento tForm1.sendTheadClick (remitente: tobject);
var amessage: tmessage;
amessage.msg: = my_message2;
amessage.wparam: = 1;
Fdispatcher.sendMessage (Amessage);
fin;
fin;
procedimiento tForm1.FormCreate (remitente: tobject);
Comenzar
{Crear una clase de tabla de mapa de mensajes}
Fdispatcher: = tpDispatcher.create;
Fhandle: = tphandler.create;
{crear hilo}
Fthread: = tpthread.create (falso);
{Agregar mensaje a la tabla de mapeo}
Fdispatcher.addhandle (my_message2, fthread.domessage);
fin;
procedimiento tForm1.FormDestroy (remitente: tobject);
var i: entero;
Comenzar
FreeAndnil (fdispatcher);
Freeandnil (fhandle);
para i: = 0 a 3 hacer
Freeandnil (fthread [i]);
fin;
segundo. Una ventana puede manejar mensajes porque tiene un mango de ventana. Para que el hilo maneje los mensajes, podemos agregar un mango de ventana al hilo de la clase de ventana correspondiente. (El código fuente está en <../ Diseño de procesamiento de mensajes (hilo) 2 / pthread.pas>)
Unidad PTHread;
interfaz
utiliza clases, sysutils, ventanas, mensajes, diálogos;
const my_message1 = $ bd00 + 01;
Tipo
{** Clase de hilo de procesamiento de mensajes
*; Función = agregar capacidad de procesamiento de subprocesos,
*}
Tpmsgthread = class (tthread)
Privado
// mango de la ventana
Fwndhandle: hwnd;
// Información de datos de ventana
FwndClass: WndClass;
// Función de devolución de llamada de puntero a la ventana
Fobjectinstance: puntero;
// Inicializar los datos de la ventana
procedimiento initWnd;
// crear una ventana oculta
procedimiento creóWnd;
// Registre la ventana oculta
procedimiento registwnd;
procedimiento destruir ahora;
// función de devolución de llamada de la ventana
Procedimiento PWNDProc (Mensaje VAR: TMessage);
protegido
procedimiento ejecutar;
procedimiento doterminado;
público
constructor crea (createSoSpended: boolean);
propiedad wndhandle: hwnd leer fwndhandle escribir fwndhandle;
fin;
Implementación
const wnd_name = 'py20';
{Tpmsgthread}
constructor tpmsgthread.create (createSoSpended: boolean);
Comenzar
create heredado (createSoSpended);
Fwndhandle: = Integer (nil);
Initwnd;
Registwnd;
Createwnd;
fin;
procedimiento tpmsgthread.createWnd;
Comenzar
if (wndhandle = integer (nil)) entonces
Wndhandle: = createwindow (fwndclass.lpszclassname, fwndclass.lpszclassname,
Ws_popup o ws_caption o ws_clipsiblings o ws_sysmenu
o ws_minimizebox,
GetSystemMetrics (SM_CXScreen) Div 2,
GetSystemMetrics (SM_CYSCREEN) DIV 2,
0, 0, 0, 0, fwndclass.hinstance, nil);
// Reemplazar la función de devolución de llamada de la ventana
Setwindowlong (wndhandle, gwl_wndproc, longint (fobjectInstance));
fin;
procedimiento tpmsgthread.destroywnd;
Comenzar
UnregisterClass (fwndclass.lpszClassName, fwndclass.hinstance);
DestroyWindow (wndhandle);
fin;
procedimiento tpmsgthread.doterminate;
Comenzar
heredado;
Destruir;
fin;
procedimiento tpmsgthread.execute;
Comenzar
fin;
procedimiento tpmsgthread.initwnd;
Comenzar
Fwndclass.lpszClassName: = Pchar (wnd_name);
Fwndclass.hinstance: = handle;
Fwndclass.lpfnwndproc: = @defwindowproc;
fin;
procedimiento tpmsgthread.pwndproc (mensaje var: tmessage);
Comenzar
fin;
procedimiento tpmsgthread.registwnd;
Comenzar
FobjectInstance: = classes.makeObjectInstance (pwndproc);
if (fwndclass.hinstance <> integer (nil)) luego
RegisterClass (FWNDClass);
fin;