Delphi es una nueva herramienta de desarrollo de programación WINDOWS proporcionada por Borland. Debido a que utiliza el lenguaje Pascal orientado a objetos (pascal orientado a objetos), flexible y reutilizable, y tiene un potente motor de base de datos (BDE), el compilador de código rápido también proporciona muchos excelentes. componentes Es el preferido por la mayoría de los programadores. Se destaca entre muchos lenguajes de programación (como VB, PowerBuilder, Powerpoint, etc.).
Una de las ventajas de DELPHI sobre otros lenguajes de programación (como VB4.0) es que los mensajes se pueden personalizar en DELPHI y se pueden procesar directamente. Esto es adecuado para quienes desean escribir sus propios componentes (Component). , o que quieran interceptar y filtrar mensajes. Es esencial para los usuarios porque escribir componentes generalmente requiere procesar los mensajes correspondientes. La siguiente es una introducción al mecanismo de procesamiento de mensajes en Delphi.
1. Entrega de mensajes en DELPHI VCL
Cada componente VCL (Biblioteca de componentes visuales) (como Tbutton, Tedit, etc.) en Delphi tiene un mecanismo de procesamiento de mensajes inherente. El punto básico es que la clase de componente recibe ciertos mensajes y los envía al método de procesamiento apropiado. No hay ningún método de procesamiento específico, se llama al identificador de procesamiento de mensajes predeterminado. Entre ellos, mainwndPRoc es un método estático definido en la clase Twincontrol y no se puede sobrecargar (Override). No procesa el mensaje directamente, sino que lo deja en manos del método wndproc para su procesamiento y proporciona un módulo de manejo de excepciones para el método wndproc. El método Mainwndproc se declara de la siguiente manera:
procedimiento MainWndProc(var Mensaje: TMessage);
Wndproc es un método virtual definido en la clase Tcontrol, que llama al método de envío para distribuir mensajes. El método wndproc se declara de la siguiente manera:
procedimiento WndProc(var Mensaje: TMessage);
El método de envío se define en la clase raíz de Tobject y se declara de la siguiente manera:
procedimiento Tobject.dispatch(var Mensaje) El parámetro de mensaje pasado al envío debe ser un tipo de registro y el primer punto de entrada en este registro debe ser un campo de tipo cardinal, que contiene el mensaje del mensaje que se distribuirá. . Por ejemplo:
tipo
Tmensaje=registro
Mensaje: cardenal;
wparam:Palabra;
lparam:inteto largo;
resultado: entero largo;
fin;
El método Dispatch llamará al método de manejo de la clase de última generación del componente que maneja este mensaje según el número de mensaje. Si no hay un controlador correspondiente a este mensaje en este componente y su clase ancestral, el método Dispatch llamará al Defaulthandler. El método Defaulthandler es El método virtual definido en Tobject se declara de la siguiente manera:
procedimiento Defaulthandler(var Mensaje);virtual;
El método Defaulthandler en la clase Tobject solo implementa un retorno simple sin ningún procesamiento del mensaje. Podemos implementar el procesamiento predeterminado del mensaje en la subclase sobrecargando este método virtual. Para los componentes en la VCL, su método Defaulthandler iniciará las ventanas. Función API Defwindowproc para procesar el mensaje.
2. Controlador de procesamiento de mensajes en DELPHI
En DELPHI, los usuarios pueden personalizar mensajes y identificadores de procesamiento de mensajes. La definición de identificadores de procesamiento de mensajes tiene los siguientes principios:
El método de manejo de procesamiento de mensajes debe ser un procedimiento y solo puede pasar un parámetro variable de tipo Tmessage.
La declaración del método debe ir seguida de un comando de mensaje, seguido de una etiqueta de mensaje (constante entera) entre 0 y 32767.
El método del controlador de mensajes no necesita usar el comando de anulación para indicar explícitamente la anulación de un controlador de mensajes del antepasado. Además, generalmente se declara en el área protegida o privada del componente.
En el identificador de procesamiento de mensajes, el usuario generalmente procesa el mensaje primero y finalmente usa el comando heredado para llamar al identificador de procesamiento correspondiente a este mensaje en la clase ancestral (en algunos casos, puede ser lo contrario porque el identificador de procesamiento de). este mensaje en la clase ancestral puede ser El nombre y el tipo de parámetro no están claros, y llamar al comando heredado puede evitar este problema. De manera similar, si no hay un controlador correspondiente a este mensaje en la clase ancestral, heredado llamará automáticamente al método Defaulthandler. (Por supuesto, si quieres bloquear este mensaje, No es necesario utilizar el comando heredado).
El método del controlador de mensajes se declara como:
procedimiento Mymsgmethod(var mensaje:Tmessage tipo de mensaje);
De manera similar, los usuarios también pueden definir sus propios mensajes. Los mensajes definidos por el usuario deben comenzar con WM_USER.
A continuación se muestran ejemplos de mensajes personalizados y identificadores de procesamiento de mensajes:
const mi_pintura=Wm_user+1;
tipo
Tmypaint=registro
msgstr: cardenal;
tamañom:palabra;
mcolor:entrada larga;
msgresult:longint;
fin;
tipo
Tmycontrol=clase(TCustomControl)
protegido
cambio de procedimiento (var mensaje: Tmypaint mensaje my_paint);
.....
fin;
...
procedimiento Tmycontrol.change(var mensaje:Tmypaint);
comenzar
tamaño:=message.msize; {Establecer atributo de tamaño de Tmybutton}
color:=message.mcolor; {Establecer atributo de color Tmybutton}
{hacer algo más}
heredado; {Entregado a Tcustomcontrol}
fin;
3. Filtrar mensajes
El filtrado de mensajes también se denomina trampa de mensajes. En determinadas circunstancias, es posible que los usuarios necesiten bloquear ciertos mensajes o interceptar ciertos mensajes para su procesamiento. De la introducción anterior, podemos ver que generalmente hay tres formas de filtrar mensajes: (1). Sobrecargar el método virtual wndproc heredado por el componente (2). Sobrecarga el método virtual Defhandler heredado por el componente, donde se procesan los mensajes. El método más utilizado es el método (2), que se presentó en la sección anterior. El método (1) es similar al método (3). Aquí solo presentamos brevemente el método (1).
El proceso general de sobrecarga del método virtual wndproc es el siguiente:
procedimiento Tmyobject.wndproc(var mensaje:Tmessage);
comenzar
{... Determinar si este mensaje debe procesarse...}
wndproc heredado (mensaje);
{Los mensajes no procesados son manejados por el método principal wndproc}
fin;
De esto se puede ver que la ventaja de procesar mensajes en el método wndproc es que puede filtrar todo el rango de mensajes sin tener que especificar un identificador de procesamiento para cada mensaje. De hecho, se usa en el componente Tcontrol para filtrar y. procesar todos los mensajes del mouse (desde WM_mousefirst hasta WM_mouselast, como se muestra en el siguiente código). También se puede usar para evitar que ciertos mensajes se envíen al controlador.
procedimiento TControl.WndProc(var Mensaje: TMessage);
comenzar
si (Mensaje.Msg>=WM_MOUSEFIRST) y
(Mensaje.Msg <= WM_MOUSELAST)
entonces
si arrastra entonces {Manejar evento de arrastre}
ArrastrarMouseMsg(TWMMouse(Mensaje))
demás
... {manejar otros mensajes del mouse}
fin;
Despacho(Mensaje);
{De lo contrario, envíe el mensaje normalmente}
fin;
El siguiente ejemplo es un ejemplo simple de componente personalizado:
La clase Tmyedit es una nueva clase derivada de la clase Tedit. Su característica es que no puede obtener el foco durante la operación y no puede ser ingresada por el teclado (algo similar al componente Tlabel. Podemos filtrar los mensajes WM_setfocus y WM_mousemove). método wndproc y realizar Para lograr los requisitos anteriores, el programa fuente es el siguiente:
unidad myedit;
interfaz
usos
Windows, Mensajes, SysUtils, Clases, Gráficos,
Controles, formularios, cuadros de diálogo,
Controles estándar;
tipo
Tmyedit = clase(TEdit)
privado
{Declaraciones privadas}
protegido
{ Declaraciones protegidas }
{otros campos y métodos}
procedimiento wndproc(var mensaje:Tmessage);anular;
público
{Declaraciones públicas}
publicado
{ Declaraciones publicadas }
fin;
Registro de trámites;
implementación
Registro de trámites;
comenzar
RegisterComponents('Muestras', [Tmyedit]);
fin;
procedimiento Tmyedit.wndproc(var mensaje:tmessage);
comenzar
si mensaje.msg=wm_mousemove entonces
comenzar
cursor:=carrow;
{Establezca el cursor en crarrow en lugar del cursor crBeam predeterminado}
salida;
fin;
si message.msg=wm_SetFocus entonces salga;
{Proteger el mensaje WM_setfocus y evitar que el control Tmyedit obtenga el foco de entrada}
wndproc heredado (mensaje);
{Otros mensajes se entregan al wndproc principal para su procesamiento}
fin;
fin.
Puede agregar Tmyedit a la paleta de componentes para probar su rendimiento.
Como se puede ver en la introducción anterior, solo comprendiendo el mecanismo de procesamiento de mensajes en Delphi VCL, dominando los métodos y tiempos de procesamiento de varios mensajes (usando varias herramientas si es necesario, como winsight32, spy, etc.) y combinando las características del lenguaje OOP, podemos compilar componentes de alta calidad. Esto, por supuesto, requiere que los lectores exploren y acumulen experiencia en la práctica constantemente.