sábado 18 de octubre de 2008

[CSharp]Fun with Windows Handlers (2/3)

Siguiendo con la entrada anterior, veremos ahora una pequeña muestra de alguna cosa divertida conociendo el Handler de una ventana.

Si la ventana pertenece a nuestra aplicación, y sólo en ese caso, podemos obtener a partir del handle, la instancia de la clase Form al que está asociado:

Form formApp = (Form)Form.FromHandle( myAppWindowHandle );
Si el handle no pertenece a una ventana creada dentro de nuestra propia aplicación, Form.FromHandle retorna null, imagino que será por cuestiones de seguridad. El caso es que usando funciones de Win32 API por medio de P/Invoke podemos saltarnos en algunos casos esta seguridad.



Antes de mostrar lo que podemos hacer, tendremos que presentar dos conceptos que se aplican en las ventanas de Windows. Si, es un momento teórico, pero necesario.



Parent Window



En Windows, todo elemento visual (widgets), desde el formulario principal a los botones se consideran... windows (buen nombre para no confundir a la gente ¿eh? ) Una mejor manera de denominar a los widgets es usar la nomenclatura usada en .NET: Todo es un Control.



Una aplicación de Windows consiste en una jerarquía de controles: cada control puede a su vez contener a otros, ser padre de otros, creando una jerarquía en forma árbol. En Visual Studio podemos ver esa jerarquía por medio del menú View/Other Windows/Outline Document.



Por ejemplo, si tuviéramos el siguiente formulario la jerarquía sería la mostrada por la imagen a su derecha:



parentWindow1 parentWindowTree1



Sin embargo si ahora añadimos un GroupBox e introducimos el botón en él, tendríamos la siguiente ventana y jerarquía:



parentWindow2 parentWindowTree2



Una vez dicho esto, creo que queda claro de forma intuitiva lo que es una ventana padre o una ventana hija dentro de la jerarquía. Lo que tenemos que tener en cuenta que una ventana hija se posiciona en coordenadas relativas a la ventana padre, y que siempre se mantiene dentro de los límites del área de cliente de una ventana.



WindowParts





Owner Window



Esta es más sencilla: una ventana se considera propietaria de otra cuando se considera parte fundamental de la ventana propietaria. Pro ejemplo, si desde nuestra aplicación creamos un MessageBox, o mostramos un diálogo de selección de fichero, nuestra aplicación es la propietaria de éstas ventanas: nuestra aplicación las crea y las gestiona, pero no dependen de una jerarquía de controles dentro de la ventana principal. Esas ventanas no tienen por qué se modales, por ejemplo, las típicas ventanas flotantes de una aplicación de retoque fotográfico tienen como propietaria a la ventana de la aplicación principal:



La ventana principal es propietaria de las sombreadas en rojo



Las ventanas que son propiedad de otra tienen la particularidad de que se pueden dibujar en cualquier parte del escritorio, pero siempre se muestran por encima de la ventana propietaria.


UPDATE: Otro comportamiento muy importante de una ventana que tiene como propietaria a otra es que si cerramos la ventana principal, todas las ventanas de las que la ventana principal sea propietaria también se ocultarán.


 


Y por fin, veremos cómo hacer alguna cosa interesante con un handler en la tercera y última entrada de esta mini-serie.