Delphi é uma nova ferramenta de desenvolvimento de programação WINDOWS fornecida pela Borland. Porque usa a linguagem Pascal (pascal orientada a objetos) flexível e reutilizável e possui um poderoso mecanismo de banco de dados (BDE), código rápido O compilador também oferece muitos recursos excelentes. componentes. É preferido pela maioria dos programadores. Destaca-se entre muitas linguagens de programação (como VB, PowerBuilder, Powerpoint, etc.).
Uma das vantagens do DELPHI em relação a outras linguagens de programação (como VB4.0) é que as mensagens podem ser customizadas no DELPHI e podem ser processadas diretamente. Isso é para quem deseja escrever seus próprios componentes (Component). ou que desejam interceptar e filtrar mensagens. É essencial para os usuários porque escrever componentes geralmente requer o processamento de mensagens correspondentes.
1. Entrega de mensagens em DELPHI VCL
Cada componente VCL (Visual Component Library) (como Tbutton, Tedit, etc.) no Delphi possui um mecanismo de processamento de mensagens inerente. O ponto básico é que a classe do componente receba certas mensagens e as envie para o método de processamento apropriado, se houver. nenhum método de processamento específico, o identificador de processamento de mensagens padrão é chamado. Dentre eles, mainwndPRoc é um método estático definido na classe Twincontrol e não pode ser sobrecarregado (Override). Ele não processa a mensagem diretamente, mas a deixa para o método wndproc processar e fornece um módulo de tratamento de exceções para o método wndproc. O método Mainwndproc é declarado da seguinte forma:
procedimento MainWndProc(var Mensagem: TMessage);
Wndproc é um método virtual definido na classe Tcontrol, que chama o método de expedição para distribuir mensagens. O método wndproc é declarado da seguinte forma:
procedimento WndProc(var Mensagem: TMessage virtual);
O método de expedição é definido na classe raiz Tobject e é declarado da seguinte forma:
procedimento Tobject.dispatch(var Mensagem); O parâmetro mensagem passado para despacho deve ser do tipo registro, e o primeiro ponto de entrada neste registro deve ser um campo do tipo cardinal (campo), que contém a mensagem da mensagem a ser distribuída Número. . Por exemplo:
tipo
Tmessage=registro
Mensagem: cardeal;
wparam:Palavra;
lparam:inteiro longo;
resultado: inteiro longo;
fim;
O método Dispatch chamará o método handle da classe de última geração do componente que trata esta mensagem com base no número da mensagem. Se não houver nenhum manipulador correspondente a esta mensagem neste componente e sua classe ancestral, o método Dispatch chamará o Defaulthandler. O método Defaulthandler é O método virtual definido em Tobject é declarado da seguinte forma:
procedimento Defaulthandler(var Mensagem);virtual;
O método Defaulthandler na classe Tobject implementa apenas um retorno simples sem qualquer processamento da mensagem. Podemos implementar o processamento padrão da mensagem na subclasse sobrecarregando este método virtual. Para componentes na VCL, seu método Defaulthandler iniciará as janelas. Função API Defwindowproc para processar a mensagem.
2. Identificador de processamento de mensagens em DELPHI
No DELPHI, os usuários podem personalizar mensagens e identificadores de processamento de mensagens. A definição de identificadores de processamento de mensagens tem os seguintes princípios:
O método de manipulação de processamento de mensagens deve ser um procedimento e só pode passar um parâmetro de variável do tipo Tmessage.
A declaração do método deve ser seguida por um comando de mensagem, seguido por um rótulo de mensagem (constante inteira) entre 0 e 32767.
O método manipulador de mensagens não precisa usar o comando override para indicar explicitamente a substituição de um manipulador de mensagens do ancestral. Além disso, geralmente é declarado na área protegida ou privada do componente.
No identificador de processamento de mensagens, o usuário geralmente processa a mensagem primeiro e, finalmente, usa o comando herdado para chamar o identificador de processamento correspondente a esta mensagem na classe ancestral (em alguns casos, pode ser o oposto). esta mensagem na classe ancestral pode ser O nome e o tipo de parâmetro não são claros, e chamar o comando herdado pode evitar esse problema. Da mesma forma, se não houver nenhum manipulador correspondente a esta mensagem na classe ancestral, herdado chamará automaticamente o método Defaulthandler. (Claro, se você quiser bloquear esta mensagem, Não há necessidade de usar o comando herdado).
O método do manipulador de mensagens é declarado como:
procedimento Mymsgmethod(var mensagem:Tmessage Msgtype);
Da mesma forma, os usuários também podem definir suas próprias mensagens. As mensagens definidas pelo usuário devem começar com WM_USER.
Exemplos de mensagens personalizadas e identificadores de processamento de mensagens são os seguintes:
const meu_paint=Wm_user+1;
tipo
Tmypaint = registro
msgstr:cardinal;
msize:palavra;
mcolor:inteiro longo;
resultado da mensagem: inteiro longo;
fim;
tipo
Tmycontrol=class(TCustomControl)
protegido
mudança de procedimento(var mensagem:Tmypaint mensagem my_paint);
.....
fim;
...
procedimento Tmycontrol.change(var mensagem:Tmypaint);
começar
size:=message.msize; {Definir atributo de tamanho do Tmybutton}
color:=message.mcolor; {Definir atributo de cor do Tmybutton}
{faça outra coisa}
herdado; {Entregue ao Tcustomcontrol}
fim;
3. Filtre mensagens
A filtragem de mensagens também é chamada de armadilha de mensagens. Sob certas circunstâncias, os usuários podem precisar bloquear determinadas mensagens ou interceptar determinadas mensagens para processamento. A partir da introdução acima, podemos ver que geralmente existem três maneiras de filtrar mensagens: (1). Sobrecarregar o método virtual wndproc herdado pelo componente (2). Sobrecarregue o método virtual Defhandler herdado pelo componente, onde as mensagens são processadas. O método mais comumente usado é o método (2), que foi apresentado na seção anterior. O método (1) é semelhante ao método (3). Aqui apresentamos apenas brevemente o método (1).
O processo geral de sobrecarga do método virtual wndproc é o seguinte:
procedimento Tmyobject.wndproc(var mensagem:Tmessage);
começar
{... Determine se esta mensagem deve ser processada..}
herdado wndproc(mensagem);
{Mensagens não processadas são tratadas pelo método pai wndproc}
fim;
Pode-se perceber a partir disso que a vantagem de processar mensagens no método wndproc é que ele pode filtrar todo o intervalo de mensagens sem ter que especificar um identificador de processamento para cada mensagem. Na verdade, ele é usado no componente Tcontrol para filtrar e. processar todas as mensagens do mouse (de WM_mousefirst a WM_mouselast, conforme mostrado no código a seguir).
procedimento TControl.WndProc(var Mensagem: TMessage);
começar
if (Message.Msg>=WM_MOUSEFIRST) e
(Mensagem.Msg <= WM_MOUSELAST)
então
se arrastar então {Handle drag event}
DragMouseMsg(TWMMouse(Mensagem))
outro
... {lidar com outras mensagens do mouse}
fim;
Envio(Mensagem);
{Caso contrário, envie a mensagem normalmente}
fim;
O exemplo a seguir é um exemplo simples de componente personalizado:
A classe Tmyedit é uma nova classe derivada da classe Tedit. Sua característica é que ela não pode obter foco durante a operação e não pode ser inserida pelo teclado (um pouco semelhante ao componente Tlabel. Podemos filtrar as mensagens WM_setfocus e WM_mousemove em seu). Método wndproc e execute Para atingir os requisitos acima, o programa de origem é o seguinte:
unidade minhaedição;
interface
usa
Windows, Mensagens, SysUtils, Classes, Gráficos,
Controles, formulários, caixas de diálogo,
StdCtrls;
tipo
Tmyedit = classe(TEdit)
privado
{Declarações privadas}
protegido
{Declarações protegidas}
{outros campos e métodos}
procedimento wndproc(var mensagem:Tmessage);substituir;
público
{Declarações públicas}
publicado
{Declarações publicadas}
fim;
Cadastro de procedimento;
implementação
Cadastro de procedimento;
começar
RegisterComponents('Amostras', [Tmyedit]);
fim;
procedimento Tmyedit.wndproc(var mensagem:tmessage);
começar
se mensagem.msg=wm_mousemove então
começar
cursor:=carrow;
{Defina o cursor para crarrow em vez do cursor crBeam padrão}
saída;
fim;
se message.msg=wm_SetFocus então saia;
{Proteja a mensagem WM_setfocus e evite que o controle Tmyedit obtenha o foco de entrada}
herdado wndproc(mensagem);
{Outras mensagens são entregues ao wndproc pai para processamento}
fim;
fim.
Você pode adicionar Tmyedit à paleta de componentes para testar seu desempenho.
Como pode ser visto na introdução acima, somente compreendendo o mecanismo de processamento de mensagens no Delphi VCL, dominando os métodos e o tempo de processamento de várias mensagens (usando várias ferramentas, se necessário, como Winsight32, Spy, etc.) e combinando as características da linguagem OOP, podemos compilar componentes de alta qualidade. Isto, claro, exige que os leitores explorem e acumulem constantemente experiência na prática.