Orden de inicialización de las unidades Delphi:

1. System.pas
2. Windows.pas
3. SysUtils.pas
4. VarUtils.pas
5. Variants.pas
6. TypInfo.pas
7. Classes.pas
8. IniFiles.pas
9. Registry.pas
10. Graphics.pas
11. MultiMon.pas
12. UxTheme.pas
13. Themes.pas
14. DwmApi.pas
15. Controls.pas (Aquí es donde se crea el objeto Application )
16. ActnList.pas
17. Menus.pas
18. HelpIntfs.pas
19. Printers.pas
20. FlatSB.pas
21. GraphUtil.pas
22. ExtCtrls.pas
23. Dialogs.pas
24. Clipbrd.pas
25. Forms.pas

Si se elimina la creación del formulario principal en el dpr del programa y se elimina la clausula Uses Forms; las unidades inicializadas son las siguientes:

1. System.pas

Delphi: Conceptos: Parpadeo de controles.


En ocasiones nos encontramos que al redimensionar un formulario Delphi los controles parpadean... vamos a ver por que y como evitarlo.


Los controles Delphi descendientes de la clase TWinControl como TForm cuando reciben el mensaje de pintado WM_PAINT este es procesado por el metodo TWincontrol.WMPaint. La definición del metodo es ...

TWinControl.WMPaint(var Message: TWMPaint);

Si observamos el código fuente del metodo que se encuentra en la unidad Controls.pas observaremos que independientemente del tema del doble buffer básicamente lo que se hace es llamar al metodo PaintHandler cuya definición es...

procedure TWinControl.PaintHandler(var Message: TWMPaint);


Este metodo es el encargado de dibujar el contenido de nuestra ventana o control.


Es en este metodo donde empezamos a ver el problema. Veamos...


Lo primero que se hace en este metodo es llamar a la función WinApi BeginPaint. Pues bien, antes de que nuestro programa continué en la siguiente línea la ejecución de BeginPaint mandará al procedimiento de nuestra ventana directamente un mensaje WM_ERASEBKGND que sera tratada por el metodo WMEraseBkgnd cuya definición es ...

procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);


dentro de este metodo se rellena el fondo de toda la ventana con el color de fondo definido para el control.


Es aquí precisamente donde notaremos el parpadeo ya que aun no hemos dibujado nada en nuestra ventana y esta ya ha sido borrada completamente solomente por haber llamado a la función WinApi BeginPaint.


 


Continuará...

WinApi: Mensajes: WM_PAINT


El mensaje WM_PAINT es quizás el más difícil de comprender en su totalidad. Y esto es un problema ya que de él depende que nuestros programas funcionen de una manera fluida y elegante. Uno de las consecuencias más comunes de no procesar correctamente este mensaje es el parpadeo que producen los controles de un formulario o ventana cuando esta se está redimensionando con el ratón. Otro efecto también común es ver como zonas de las ventanas de nuestros programas no se redibujan correctamente cuando son tapadas por otras ventanas.

¿ Por qué nuestra aplicación recibe mensajes WM_PAINT ?

Básicamente porque la filosofía de programación para Windows radica en el concepto de "No me llame, ya le llamare yo." o lo que es lo mismo... Que en la mayoría de las ocasiones será Windows quien le indique a nuestro programa que debe dibujar el contenido gráfico de sus ventanas. Obviamente también podemos forzar nosotros mismo el dibujado cuando sea necesario pero lo más habitual sea que el mismo Windows nos indique que debemos actualizar nuestra pantalla bien porque otra se haya colocado encima o por que se activado el salvapantallas o porque hemos maximizado o minimizado nuestra aplicación. Sea como sea tenga por seguro que Windows tarde o temprano nos va a mandar el mensaje WM_PAINT a nuestro programa.

¿ Dónde recibe nuestra aplicación los mensajes WM_PAINT ?

Los mensajes WM_PAINT pueden llegar a nuestra aplicación solamente a tres sitios. O llegan a la cola de mensajes principal del programa, o la cola de mensaje de un thread que haya creado una ventana o directamente al procedimiento de ventana de una ventana. Pero vengan como vengan en realidad solo hay un sitio donde deberemos ocuparnos de ellos, que es en el procedimiento de ventana.

¿ Cuándo recibe nuestra aplicación mensajes WM_PAINT ?


  • Cuando Windows necesite redibujar nuestras ventanas.
  • Cuando dentro de nuestros programas usemos las funciones del Api de Windows:

    • UpdateWindow
    • RedrawWindow


Programación: Conceptos: Relaciones entre objetos.

Tipos de las relaciones

  • Herencia
    Es la relación que se establece entre dos clases cuando una desciende de la otra.

  • Asociación
    Es cuando en una clase usamos un objeto de otra clase para realizar una tarea en particular y creamos , usamos y destruimos el objeto de una manera local.
    No se trata de relaciones fuertes entre objetos y suelen ser creadas en tiempo de ejecución.
    Se representa mediante una línea continua.
  • Agregación
    Suelen representar una relación Todo-Parte en la que el objeto contenedor contiene a otros objetos pero no ha sido la responsable de crearlos y tampoco tiene la responsabilidad de destruirlos.
    El caso mas normal se da cuando un objeto hace referencia a otro mediante una propiedad ejerciendo esta solamente como una referencia al objeto. La propiedad sera asignada o desasignada en tiempo de ejecución.
    Se representa con una linea que tiene un rombo blanco en el extremo correspondiente al objeto contenedor.
  • Composición
    Es como una agregación pero mas fuerte. Es decir, los objetos contenidos serán creados y destruidos por el objeto contenedor. Solo existirán en tanto exista el objeto que los contiene.
    Se representa por una línea que tiene un rombo negro en el extremo correspondiente al objeto contenedor.
  • Dependencia
  • Realización

Cardinalidad de las relaciones

Según el número y origen y destino de las relaciones entre objetos tendremos los siguientes tipos de relaciones:
  • Uno a Uno
  • Uno a Muchos
  • Muchos a Muchos

WinApi: Conceptos: Crear ventanas

La programación con el Api de Windows es un trabajo casi por completo centrado en las ventanas.

Por eso es muy importante saber que es y que no es una ventana desde el punto de vista de Windows que inicialmente no tiene que coincidir con el punto de vista del programador y explicaré por que.

Aunque en principio pudiera parecer que las ventanas en Windows son aquellas que representan a los programas como por ejemplo el Notepad, la Calculadora , etc lo cierto es que las ventanas Windows son en realidad casi todo lo que que vemos en la pantalla y que normalmente tiene una apariencia rectangular.

Me explico, y tomando como ejemplo la calculadora de Windows citaremos las ventanas que la forman:

* La ventana principal que incluye el titulo junto con los botones de minimizar y cerrar el programa.
* La zona donde se muestra el resultado de las operaciones también es una ventana windows.
* Y por ultimo cada uno de los botones que aparecen en la superficie de la calculadora también son ventanas.

Normalmente a las ventanas principales de los programas se le llaman ventanas superpuestas y a las ventanas que se encuentran en su interior se les llaman ventanas hija o simplemente controles.

La prueba mas clara de que tanto las ventanas principales de los programas como las ventanas hijas o controles son para Windows la misma cosa es que ambas se crean con la misma función del WinApi... CreateWindow().

WinApi: Conceptos: Procedimientos de ventana

Un procedimiento de ventana es una función que procesa todos los mensajes destinados a una ventana.

Cada ventana tiene asociado un procedimiento de ventana.

Todas las ventanas de una misma clase comparten el mismo procedimiento de ventana.

El procedimiento de ventana se define en la función de registro de una clase. ( RegisterClass )

Como el procedimiento de ventana es común a todas las ventanas hay que tener cuidado con los recursos que puedan estar compartidos por ellas dentro del procedimiento de ventana.

Un procedimiento es una función que recibe 4 parámetros:

* Window Handle
* Message Identifier
* wParam
* lParam

La función retorna un entero. El retorno debe ser interpretado según el tipo de mensaje procesado.

Como el procedimiento de ventana puede ser llamado recursivamente cuando se procesan los mensajes es conveniente no usar demasiadas variables locales en el mismo y realizar los procesos que demanden los mensajes mediante rutinas externas para no provocar un stack overflow.

En windows existe una función llamada DefWindowProc que define el comportamiento estándar y por defecto de cualquier ventana windows. Cuando escribimos procedimientos de ventana personalizados debemos llamar a esta función para cualquier mensaje que no procesemos explícitamente para dotar a la ventana de un comportamiento mínimo y estándar.

WinApi: Mensajes: Teclado

Mensaje

Descripción

WM_KEYDOWN

Es enviada a la ventana que tiene el foco. Solo si no es la tecla Alt o esta no está pulsada.

La tecla es recibida como un virtual key en el parámetro wParam. Debido a la auto repetición se pueden recibir varios keydown seguidos antes de recibir el keyup.

Si es un carácter entonces window colocara en la cola de mensajes un WM_CHAR o un WM_DEADCHAR

WM_SYSKEYDOWN

Es enviado cuando se pulsa la tecla Alt u otra estando Alt pulsada. Si no hay un control

con foco entonces la ventana activa recibirá todas las teclas como WM_SYSKEYDOWM

aunque la tecla ALT no esté pulsada. Si es un carácter colocara en la cola de mensajes un WM_SYSCHAR o WM_SYSDEADCHAR

WM_KEYUP

Es enviado cuando se suelta la tecla si no es la tecla Alt o esta pulsada. La tecla viene en wParam como un virtual key.

WM_SYSKEYUP

Es enviado cuando se suelta la tecla Alt o cualquier otra estando Alt pulsada. Tambien cuando no hay un control activo la ventana activa lo recibirá aunque no esté pulsada la tecla Alt.

WM_CHAR

Es mandada al control con foco cuando la tecla genera un carácter. El mensaje es creado por la función TranslateMessage del bucle de mensajes. También recibe el estado de la tecla control y Shift y cualquier carácter Dead pendiente (por ejemplo acentos).

El carácter se recibe en wParam.

WM_SYSCHAR

Es mandada al control con foco cuando la tecla genera un carácter y Alt esta pulsada o

Cuando la ventana no tiene ningún control con foco.

El mensaje es creado por la función TranslateMessage del bucle de mensajes.

También recibe el estado de la Tecla control y Shift y cualquier carácter Dead pendiente

(por ejemplo acentos).

El carácter se recibe en wParam.

WM_DEADCHAR

Es mandada al control con foco cuando se pulsa una tecla que genera un acento.

El mensaje es creado por la función TranslateMessage del bucle de mensajes.

Si el acento es válido el próximo mensaje será un WM_CHAR con el carácter acentuado.

Si no es válido será mandado un WM_CHAR con el acento solo y otro con el carácter.

WM_SYSDEADCHAR

Lo mismo que el anterior pero si esta pulsada la tecla Alt o la ventana activa no tiene un control activo. Con una excepción , si la tecla Alt se suelta antes de pulsar el carácter que va acentuado entonces se genera un WM_SYSCHAR para el acento y otro para el carácter sin acentuar.

WM_APPCOMMAND

Este mensaje se comporta distinto a los anteriores en el sentido que no es enviado al bucle de mensajes de la aplicación. Es enviado por la función DefWindowProc cuando se pulsan determinadas teclas como controles de sonido del teclado o botones extra de un ratón. Si la ventana destino no procesa el mensaje será enviado hacia el padre y si no hasta la ventana propietaria.