Ao escrever programas, você sempre encontra problemas com a comunicação entre o formulário (TForm) e a mensagem Thread (tThread). O que é irritante é que o formulário não pode enviar mensagens para o thread (tThread) (o thread não possui uma alça de janela). Depois de vários dias de trabalho duro, criei duas soluções e as levei para discutir com você.
Primeiro. Sabemos que a biblioteca da classe MFC no VC ++ encapsulou o processamento de mensagens (BeginMessage, EndMessage) A tabela de mapeamento (processamento de mensagens é essencialmente uma chamada para um método ou processo), além de um mecanismo de distribuição de mensagens para realizar a recepção e transmissão de mensagens <consulte VC ++ Technical Insider> para obter detalhes. Portanto, precisamos apenas estabelecer uma tabela de mapeamento de mensagens para o thread e estabelecer um mecanismo de distribuição de mensagens correspondente. Isso permite que você processe mensagens enviadas pelo formulário para o thread. O código a seguir é uma classe que implementa a tabela de mapeamento de mensagens e a distribuição de mensagens (consulte <../ Design de processamento de mensagens (thread) 1/messageHandle.pas> para obter detalhes)
MessageHandle da unidade;
interface
usa mensagens, classes, sysutils, diálogos;
const pmsg_base = $ be00;
Pmsg_num = 200;
{** Classe de processamento de mensagens personalizada
*; Function = Crie uma tabela de mensagens personalizada e processo entre threads
* e mensagens personalizadas com o formulário principal (macro)
*}
// identificador de processamento de mensagens
TMessageHandle = Procedimento (Var Mensagem: TMessage) do objeto;
Tpdispatcher = classe (objeto)
Privado
// tabela correspondente da mensagem (ID da mensagem é um subscrito de matriz);
MessageHandles: Matriz de TMessageHandle;
// Obtenha o ID da matriz do ID da mensagem
função getIndexFROMSGID (const AMESSAGEID: Cardinal): Inteiro;
público
construtor Criar;
destruidor destruir;
// Envie uma mensagem
Procedimento SendMessage (VAR Mensagem: TMessage);
// Adicione uma mensagem personalizada à tabela correspondente da mensagem;
Procedimento AddHandle (const AMESSAGEID: cardeal; amessageHandle: tMessageHandle);
fim;
//
Implementação
{Tpdispatcher}
construtor tpdispatcher.create;
var i: número inteiro;
Começar
SetLength (MessageHandles, PMSG_NUM);
// inicialize a fila de mensagens;
para i: = 0 a pred (pmsg_num)
MessageHandles [i]: = nil;
fim;
destruidor tpdispatcher.destroy;
Começar
{Libere a tabela de correspondência da mensagem}
Freeandnil (MessageHandles);
fim;
procedimento tpdispatcher.addhandle (const amessageid: cardeal;
amessageHandle: tMessageHandle);
var tid: número inteiro;
Começar
Tid: = getIndexFromsgid (amessageID);
Assert ((tid> 0) ou (tid <pred (pmsg_num)));
Assert (atribuído (amessageHandle));
MessageHandles [Tid]: = AmessageHandle;
fim;
function tpdispatcher.getIndexFROMSGID (const amessageId: cardeal): inteiro;
Começar
Resultado: = amessageId - pmsg_base;
fim;
procedimento tpdispatcher.sendMessage (VAR Message: tMessage);
var tid: número inteiro;
tmsghandle: tMessageHandle;
Começar
tid: = getIndexFromsgid (message.msg);
Assert ((tid> 0) ou (tid <pred (pmsg_num)));
tmsghandle: = messagehandles [tid];
se atribuído (tmsghandle), então
tmsgHandle (mensagem);
fim;
Agora, precisamos apenas registrar uma mensagem personalizada e usar a classe de distribuição de mensagens (tpdispatcher) para processar mensagens de threads. O código é o seguinte <ver ../ Design de processamento de mensagens (thread) 1/test/unit1.pas> Para detalhes:
Unidade Unidade1
const
{Mensagem de encadeamento personalizada de longo prazo}
My_message2 = pmsg_base + 02;
tipo
Tform1 = classe (tform)
Addmsglist: tbutton;
Enviar a cabeça: tbutton;
SendForm: tbutton;
SendOther: tbutton;
Procedimento SendtheadClick (remetente: Tobject);
Procedimento FormCreate (remetente: Tobject);
procedimento formDestroy (remetente: tabjas);
Privado
Fdispatcher: tpdispatcher;
Fhandle: Tphandler;
Fthread: tpthread;
público
{Declarações públicas}
fim;
var
Form1: TForm1;
Implementação
{$ R *.dfm}
procedimento tform1.sendtheadClick (remetente: tabjas);
var amessage: tmessage;
amessage.msg: = my_message2;
amessage.wparam: = 1;
Fdispatcher.sendMessage (amessage);
fim;
fim;
procedimento TForm1.FormCreate (remetente: Tobject);
Começar
{Crie uma tabela de mapa de mensagens classe}
Fdispatcher: = tpdispatcher.create;
FHandle: = tphandler.create;
{Create Thread}
Fthread: = ttthread.create (false);
{Adicione mensagem à tabela de mapeamento}
Fdispatcher.addhandle (my_message2, fthread.domessage);
fim;
procedimento TFFORM1.FORMDESTROY (remetente: Tobject);
var i: número inteiro;
Começar
FreeAndnil (fdispatcher);
Freeandnil (Fhandle);
para i: = 0 a 3 fazer
Freeandnil (fthread [i]);
fim;
segundo. Uma janela pode lidar com mensagens porque possui uma alça de janela. Para que o encadeamento lide com as mensagens, podemos adicionar uma alça de janela ao encadeamento da classe de janela correspondente. (O código -fonte está em <../ design de processamento de mensagens (thread) 2 / pthread.pas>)
unidade pthread;
interface
usa classes, sysutils, janelas, mensagens, diálogos;
const my_message1 = $ bd00 + 01;
Tipo
{** Classe de thread de processamento de mensagens
*; Function = adicionar capacidade de processamento de roscas,
*}
Tpmsgthread = classe (tThread)
Privado
// Janganete de janela
Fwnndhandle: hwnd;
// Informações sobre dados da janela
FwnndClass: wndclass;
// Ponteiro para a função de retorno de chamada da janela
FobjectInstance: ponteiro;
// Inicialize os dados da janela
procedimento initwnd;
// Crie uma janela oculta
procedimento createwnd;
// Registre a janela oculta
Registro de procedimentos;
Procedimento Destrua;
// Função de retorno de chamada de janela
procedimento PWNDPROC (VAR Mensagem: TMessage);
protegido
procedimento executado;
procedimento doterminado;
público
Construtor Create (CreaSpended: Boolean);
Propriedade wndhandle: hwnd leia fwnndhandle write fwnndhandle;
fim;
Implementação
const wnd_name = 'py20';
{Tpmsgthread}
construtor tpmsgthread.create (CreateSuspended: boolean);
Começar
Criar herdado (CreateSuspended);
FwnndHandle: = Inteiro (nulo);
Initwnd;
Registwnd;
Createwnd;
fim;
procedimento tpmsgthread.createwnd;
Começar
if (wndhandle = inteiro (nulo)) então
Wndhandle: = createwindow (fwnndclass.lpszclassName, fwnndclass.lpszclassName,
WS_POPUP ou WS_CAPTION ou WS_CLIPSIBLINGS ou WS_SYSMENU
ou ws_minimizebox,
GetSystemMetrics (sm_cxscreen) div 2,
GetSystemMetrics (sm_cyscreen) div 2,
0, 0, 0, 0, fwndclass.hinstance, nil);
// Substitua a função de retorno de chamada da janela
SetWindowlong (wndhandle, gwl_wndproc, longnt (fobjectInstance));
fim;
procedimento tpmsgthread.DestroyWnd;
Começar
Não registro (fwnndclass.lpszclassName, fwnndclass.hinstance);
DestrowWindow (wndhandle);
fim;
procedimento tpmsgthread.Doterminate;
Começar
herdado;
Destruir;
fim;
procedimento tpmsgthread.execute;
Começar
fim;
procedimento tpmsgthread.initwnd;
Começar
FwnndClass.lpszClassName: = pchar (wnd_name);
Fwnndclass.hinstance: = handle;
Fwnndclass.lpfnwndproc: = @defwindowproc;
fim;
procedimento tpmsgthread.pwndproc (var message: tmessage);
Começar
fim;
procedimento tpmsgthread.registWnd;
Começar
FObjectInstance: = classes.makeObjectInstance (pwnndProc);
if (fwnndclass.hinstance <> integer (nil)) então
Registerclass (FWNDCLASS);
fim;