Compartir a través de


Acerca de las clases ventana

Cada clase de ventana tiene un procedimiento de ventana asociado compartido por todas las ventanas de la misma clase. El procedimiento de ventana procesa mensajes para todas las ventanas de esa clase y, por tanto, controla su comportamiento y apariencia. Para más información, vea Procedimientos de ventanas.

Un proceso debe registrar una clase de ventana para poder crear una ventana de esa clase. El registro de una clase de ventana asocia un procedimiento de ventana, estilos de clase y otros atributos de clase con un nombre de clase. Cuando un proceso especifica un nombre de clase en la función CreateWindow o CreateWindowEx , el sistema crea una ventana con el procedimiento de ventana, estilos y otros atributos asociados a ese nombre de clase.

En esta sección se describen los temas siguientes.

Tipos de clases de ventana

Hay tres tipos de clases de ventana:

Estos tipos difieren en el ámbito y en cuándo y cómo se registran y destruyen.

Clases del sistema

Una clase del sistema es una clase de ventana registrada por el sistema. Muchas clases del sistema están disponibles para todos los procesos que se van a usar, mientras que otras solo las usa internamente el sistema. Dado que el sistema registra estas clases, un proceso no puede destruirlas.

El sistema registra las clases del sistema para un proceso la primera vez que uno de sus hilos llama a una función de usuario o de la Interfaz de Dispositivos Gráficos de Windows (GDI).

Cada aplicación recibe su propia copia de las clases del sistema. Todas las aplicaciones basadas en Windows de 16 bits dentro del mismo VDM comparten clases del sistema, al igual que en Windows de 16 bits.

En la tabla siguiente se describen las clases del sistema que están disponibles para su uso por todos los procesos.

Clase Descripción
Botón La clase para un botón.
ComboBox La clase para un cuadro combinado.
Editar La clase para un control de edición.
Cuadro de lista La clase de un cuadro de lista.
MDIClient Clase para una ventana de cliente MDI.
ScrollBar La clase para una barra de desplazamiento.
estática La clase para un control estático.

 

En la tabla siguiente se describen las clases del sistema que solo están disponibles para su uso por parte del sistema. Se enumeran aquí para asegurar la exhaustividad.

Clase Descripción
ComboLBox La clase para un cuadro de lista contenido en un cuadro combinado.
DDEMLEvent La clase para eventos DDEML (Dynamic Data Exchange Management Library).
Mensaje La clase para una ventana de solo mensaje.
#32768 La clase para un menú.
#32769 La clase para la ventana de escritorio.
#32770 La clase para un cuadro de diálogo.
#32771 La clase para la ventana para cambiar de tarea.
#32772 La clase para títulos de iconos.

 

Clases globales de aplicaciones

Una clase global de aplicación es una clase de ventana registrada por un archivo ejecutable o DLL que está disponible para todos los demás módulos del proceso. Por ejemplo, el .dll puede llamar a la función RegisterClassEx para registrar una clase de ventana que define un control personalizado como una clase global de aplicación para que un proceso que cargue el .dll pueda crear instancias del control personalizado.

Para crear una clase que se pueda usar en cada proceso, cree la clase de ventana en un .dll y cargue el .dll en cada proceso. Para cargar el .dll en cada proceso, agregue su nombre al valor AppInit_DLLs en la siguiente clave del Registro:

\ HKEY_LOCAL_MACHINESoftware\Microsoft\Windows NT\CurrentVersion\Windows

Cada vez que se inicia un proceso, el sistema carga el .dll especificado en el contexto del proceso recién iniciado antes de llamar a su función de punto de entrada. El .dll debe registrar la clase durante su procedimiento de inicialización y debe especificar el estilo CS_GLOBALCLASS . Para obtener más información, vea Estilos de clase.

Para quitar una clase global de aplicación y liberar el almacenamiento asociado, use la función UnregisterClass .

Clases locales de la aplicación

Una clase local de aplicación es cualquier clase de ventana que un archivo ejecutable o .dll registra para su uso exclusivo. Aunque puede registrar cualquier número de clases locales, es habitual registrar solo una. Esta clase de ventana es compatible con el procedimiento de la ventana principal de la aplicación.

El sistema destruye una clase local cuando se cierra el módulo que lo registró. Una aplicación también puede usar la función UnregisterClass para quitar una clase local y liberar el almacenamiento asociado a ella.

Cómo el sistema busca una clase de ventana

El sistema mantiene una lista de estructuras para cada uno de los tres tipos de clases de ventana. Cuando una aplicación llama a la función CreateWindow o CreateWindowEx para crear una ventana con una clase especificada, el sistema usa el procedimiento siguiente para buscar la clase.

  1. Busque en la lista de clases locales de aplicación una clase con el nombre especificado cuyo identificador de instancia coincida con el identificador de instancia del módulo. (Varios módulos pueden usar el mismo nombre para registrar clases locales en el mismo proceso).
  2. Si el nombre no está en la lista de clases locales de la aplicación, busque en la lista de clases globales de la aplicación.
  3. Si el nombre no está en la lista de clases globales de la aplicación, busque en la lista de clases del sistema.

Todas las ventanas creadas por la aplicación usan este procedimiento, incluidas las ventanas creadas por el sistema en nombre de la aplicación, como los cuadros de diálogo. Es posible invalidar las clases del sistema sin afectar a otras aplicaciones. Es decir, una aplicación puede registrar una clase local de aplicación que tenga el mismo nombre que una clase del sistema. Esto reemplaza la clase del sistema en el contexto de la aplicación, pero no impide que otras aplicaciones usen la clase del sistema.

Registrar una clase de ventana

Una clase de ventana define los atributos de una ventana, como su estilo, icono, cursor, menú y procedimiento de ventana. El primer paso para registrar una clase de ventana es rellenar una estructura WNDCLASSEX con la información de clase de ventana. Para obtener más información, vea Elementos de una clase Window. A continuación, pase la estructura a la función RegisterClassEx . Para obtener más información, vea Usar clases de ventana.

Para registrar una clase global de aplicación, especifique el estilo CS_GLOBALCLASS en el miembro style de la estructura WNDCLASSEX. Al registrar una clase local de aplicación, no especifique el estilo CS_GLOBALCLASS .

Si registra la clase de ventana mediante la versión ANSI de RegisterClassEx, RegisterClassExA, la aplicación solicita que el sistema pase parámetros de texto de mensajes a las ventanas de la clase creada mediante el juego de caracteres ANSI; si registra la clase mediante la versión Unicode de RegisterClassEx, RegisterClassExW, la aplicación solicita que el sistema pase parámetros de texto de mensajes a las ventanas de la clase creada mediante el juego de caracteres Unicode. La función IsWindowUnicode permite a las aplicaciones consultar la naturaleza de cada ventana. Para obtener más información sobre las funciones ANSI y Unicode, consulte Convenciones para prototipos de función.

El archivo ejecutable o DLL que registró la clase es el propietario de la clase . El sistema determina la propiedad de clase del miembro hInstance de la estructura WNDCLASSEX que se pasa a la función RegisterClassEx cuando se registra la clase. En el caso de los DLLs, el miembro hInstance debe ser el identificador de la instancia .dll.

La clase no se destruye cuando se retira el .dll que la posee. Por lo tanto, si el sistema llama al procedimiento de ventana para una ventana de esa clase, provocará una infracción de acceso, ya que el .dll que contiene el procedimiento de ventana ya no está en memoria. El proceso debe destruir todas las ventanas que usan la clase antes de descargar el .dll y llamar a la función UnregisterClass .

Elementos de una clase Window

Los elementos de una clase de ventana definen el comportamiento predeterminado de las ventanas que pertenecen a la clase . La aplicación que registra una clase de ventana asigna elementos a la clase estableciendo los miembros adecuados en una estructura WNDCLASSEX y pasando la estructura a la función RegisterClassEx . Las funciones GetClassInfoEx y GetClassLong recuperan información sobre una clase de ventana determinada. La función SetClassLong cambia los elementos de una clase local o global que la aplicación ya ha registrado.

Aunque una clase de ventana completa consta de muchos elementos, el sistema solo requiere que una aplicación proporcione un nombre de clase, la dirección de procedimiento de ventana y un identificador de instancia. Use los demás elementos para definir atributos predeterminados para ventanas de la clase, como la forma del cursor y el contenido del menú de la ventana. Se debe inicializar a cero cualquier miembro no usado de la estructura WNDCLASSEX o a NULL. Los elementos de la clase window se muestran en la tabla siguiente.

Elemento Propósito
Nombre de clase Distingue la clase de otras clases registradas.
Dirección del procedimiento de ventana Puntero a la función que procesa todos los mensajes enviados a las ventanas de la clase y define el comportamiento de la ventana.
Identificador de instancia Identifica la aplicación o .dll que ha registrado la clase.
Clase Cursor Define el cursor del mouse que el sistema muestra para una ventana de la clase .
Iconos de clase Define el icono grande y el icono pequeño.
Clase Background Brush Define el color y el patrón que rellenan el área de cliente cuando se abre o pinta la ventana.
Clase Menú Especifica el menú predeterminado para las ventanas que no definen explícitamente un menú.
Estilos de clase Define cómo actualizar la ventana después de moverla o cambiar su tamaño, cómo procesar los doble clics del mouse, cómo asignar espacio para el contexto del dispositivo y otros aspectos de la ventana.
Memoria de clase adicional Especifica la cantidad de memoria adicional, en bytes, que el sistema debe reservar para la clase . Todas las ventanas de la clase comparten la memoria adicional y pueden usarla para cualquier propósito definido por la aplicación. El sistema inicializa esta memoria en cero.
Memoria de ventana adicional Especifica la cantidad de memoria adicional, en bytes, que el sistema debe reservar para cada ventana que pertenezca a la clase . La memoria adicional se puede usar para cualquier propósito definido por la aplicación. El sistema inicializa esta memoria en cero.

 

Class Name (Nombre de clase)

Cada clase de ventana necesita un nombre de clase para distinguir una clase de otra. Asigne un nombre de clase estableciendo el miembro lpszClassName de la estructura WNDCLASSEX en la dirección de una cadena terminada en null que especifica el nombre. Dado que las clases de ventana son específicas del proceso, los nombres de clase de ventana deben ser únicos solo dentro del mismo proceso. Además, dado que los nombres de clase ocupan espacio en la tabla atom privada del sistema, debe mantener las cadenas de nombre de clase lo más cortas posible.

La función GetClassName recupera el nombre de la clase a la que pertenece una ventana determinada.

Dirección del procedimiento de ventana

Cada clase necesita una dirección de procedimiento de ventana para definir el punto de entrada del procedimiento de ventana que se usa para procesar todos los mensajes para las ventanas de la clase. El sistema pasa mensajes al procedimiento cuando requiere la ventana para llevar a cabo tareas, como pintar su área cliente o responder a la entrada del usuario. Un proceso asigna un procedimiento de ventana a una clase copiando su dirección al miembro lpfnWndProc de la estructura WNDCLASSEX . Para más información, vea Procedimientos de ventanas.

Identificador de instancia

Cada clase de ventana requiere un identificador de instancia para identificar la aplicación o .dll que registró la clase. El sistema requiere identificadores de instancia para realizar un seguimiento de todos los módulos. El sistema asigna un identificador a cada copia de un ejecutable en ejecución o .dll.

El sistema pasa un identificador de instancia a la función de punto de entrada de cada archivo ejecutable (consulte WinMain) y .dll (consulte DllMain). El ejecutable o .dll asigna este identificador de instancia a la clase copiandolo en el miembro hInstance de la estructura WNDCLASSEX .

Clase Cursor

El cursor de clase define la forma del cursor cuando se encuentra en el área cliente de una ventana de la clase . El sistema establece automáticamente el cursor en la forma especificada cuando el cursor entra en el área cliente de la ventana y garantiza que mantiene esa forma mientras permanece en el área cliente. Para asignar una forma de cursor a una clase de ventana, cargue una forma de cursor predefinida mediante la función LoadCursor y, a continuación, asigne el identificador de cursor devuelto al miembro hCursor de la estructura WNDCLASSEX . Como alternativa, proporcione un recurso de cursor personalizado y use la función LoadCursor para cargarlo desde los recursos de la aplicación.

El sistema no requiere una clase cursor. Si una aplicación establece el miembro hCursor de la estructura WNDCLASSEX en NULL, no se define ningún cursor de clase. El sistema supone que la ventana establece la forma del cursor cada vez que el cursor se mueve a la ventana. Una ventana puede establecer la forma del cursor llamando a la función SetCursor cada vez que la ventana recibe el mensaje WM_MOUSEMOVE . Para obtener más información sobre los cursores, vea Cursores.

Iconos de clase

Un icono de clase es una imagen que el sistema usa para representar una ventana de una clase determinada. Una aplicación puede tener dos iconos de clase: uno grande y otro pequeño. El sistema muestra el icono de clase grande de una ventana en la ventana del conmutador de tareas que aparece cuando el usuario presiona ALT+TAB y en las vistas de icono grandes de la barra de tareas y el explorador. El icono pequeño de clase aparece en la barra de título de una ventana y en las vistas de iconos pequeños de la barra de tareas y del explorador.

Para asignar un icono grande y uno pequeño a una clase de ventana, especifique los identificadores de los iconos en los miembros hIcon y hIconSm de la estructura WNDCLASSEX. Las dimensiones de icono deben ajustarse a las dimensiones necesarias para iconos de clase grandes y pequeños. Para un icono de clase grande, puede determinar las dimensiones necesarias especificando los valores de SM_CXICON y SM_CYICON en una llamada a la función GetSystemMetrics . Para un icono de clase pequeña, especifique los valores SM_CXSMICON y SM_CYSMICON . Para obtener información, vea Iconos.

Si una aplicación establece los miembros hIcon y hIconSm de la estructura WNDCLASSEX en NULL, el sistema usa el icono de aplicación predeterminado como los iconos de clase grande y pequeño para la clase de ventana. Si especifica un icono de clase grande pero no uno pequeño, el sistema crea un icono de clase pequeño basado en el grande. Sin embargo, si especifica un icono de clase pequeño pero no uno grande, el sistema usa el icono de aplicación predeterminado como el icono de clase grande y el icono especificado como el icono de clase pequeña.

Puede invalidar el icono de clase grande o pequeña para una ventana determinada mediante el mensaje WM_SETICON . Puede recuperar el icono de clase grande o pequeño actual mediante el mensaje WM_GETICON .

Clase Background Brush

Un pincel de fondo de clase prepara el área cliente de una ventana para el dibujo posterior por parte de la aplicación. El sistema usa el pincel para rellenar el área de cliente con un color o patrón sólidos, quitando así todas las imágenes anteriores de esa ubicación si pertenecen a la ventana o no. El sistema notifica a una ventana que debe pintarse su fondo enviando el mensaje WM_ERASEBKGND a la ventana. Para más información, véase Pinceles.

Para asignar un pincel de fondo a una clase, cree un pincel mediante las funciones GDI adecuadas y asigne el identificador de pincel devuelto al miembro hbrBackground de la estructura WNDCLASSEX .

En lugar de crear un pincel, una aplicación puede establecer el miembro hbrBackground en uno de los valores de color del sistema estándar. Para obtener una lista de los valores de color del sistema estándar, vea SetSysColors.

Para usar un color estándar del sistema, la aplicación debe aumentar el valor de color de fondo en uno. Por ejemplo, COLOR_BACKGROUND + 1 es el color de fondo del sistema. Como alternativa, puede usar la función GetSysColorBrush para recuperar un identificador de un pincel que corresponda a un color del sistema estándar, y, a continuación, especificar el identificador en el miembro hbrBackground de la estructura WNDCLASSEX.

El sistema no requiere que una clase de ventana tenga que tener un pincel de fondo de clase. Si este parámetro se establece en NULL, la ventana debe pintar su propio fondo siempre que reciba el mensaje de WM_ERASEBKGND .

Menú de Clase

Un menú de clase define el menú predeterminado que usarán las ventanas de la clase si no se especifica ningún menú explícito cuando se crean las ventanas. Un menú es una lista de comandos desde los que un usuario puede elegir las acciones que debe llevar a cabo la aplicación.

Puede asignar un menú a una clase estableciendo el miembro lpszMenuName de la estructura WNDCLASSEX en la dirección de una cadena terminada en null que especifica el nombre del recurso del menú. Se supone que el menú es un recurso de la aplicación determinada. El sistema carga automáticamente el menú cuando es necesario. Si el recurso de menú se identifica mediante un entero y no por un nombre, la aplicación puede establecer el miembro lpszMenuName en ese entero aplicando la macro MAKEINTRESOURCE antes de asignar el valor.

El sistema no requiere un menú de clase. Si una aplicación establece el miembro lpszMenuName de la estructura WNDCLASSEX en NULL, las ventanas de la clase no tienen barras de menú. Incluso si no se proporciona ningún menú de clase, una aplicación todavía puede definir una barra de menús para una ventana cuando crea la ventana.

Si se asigna un menú para una clase y se crea una ventana secundaria de esa clase, se omite el menú. Para obtener más información, vea Menús.

Estilos de clase

Los estilos de clase definen elementos adicionales de la clase window. Se pueden combinar dos o más estilos mediante el operador OR bit a bit (|). Para asignar un estilo a una clase de ventana, asigne el estilo al miembro style de la estructura WNDCLASSEX . Para obtener una lista de estilos de clase, vea Estilos de clase de ventana.

Clases y contextos de dispositivo

Un contexto de dispositivo es un conjunto especial de valores que las aplicaciones usan para dibujar en el área cliente de sus ventanas. El sistema requiere un contexto de dispositivo para cada ventana de la pantalla, pero permite cierta flexibilidad en la forma en que el sistema almacena y trata ese contexto del dispositivo.

Si no se especifica explícitamente ningún estilo de contexto de dispositivo, el sistema asume que cada ventana usa un contexto de dispositivo recuperado de un grupo de contextos mantenidos por el sistema. En tales casos, cada ventana debe recuperar e inicializar el contexto del dispositivo antes de pintarlo y liberarlo después de pintar.

Para evitar recuperar un contexto de dispositivo cada vez que necesite pintar dentro de una ventana, una aplicación puede especificar el estilo CS_OWNDC para la clase de ventana. Este estilo de clase dirige al sistema para crear un contexto de dispositivo privado, es decir, para asignar un contexto de dispositivo único para cada ventana de la clase . La aplicación solo necesita recuperar el contexto una vez y, a continuación, usarlo para todas las pinturas posteriores.

Memoria de clase adicional

El sistema mantiene internamente una estructura WNDCLASSEX para cada clase de ventana del sistema. Cuando una aplicación registra una clase de ventana, puede dirigir al sistema para asignar y anexar varios bytes adicionales de memoria al final de la estructura WNDCLASSEX . Esta memoria se denomina memoria de clase adicional y la comparten todas las ventanas que pertenecen a la clase . Use la memoria de clase adicional para almacenar cualquier información relacionada con la clase .

Dado que se asigna memoria adicional desde el montón local del sistema, una aplicación debería usar con moderación la memoria de clase adicional. Se produce un error en la función RegisterClassEx si la cantidad de memoria de clase adicional solicitada es superior a 40 bytes. Si una aplicación necesita más de 40 bytes debe asignar su propia memoria y almacenar un puntero a la memoria en la memoria adicional de clase.

Las funciones SetClassWord y SetClassLong copian un valor en la memoria de clase adicional. Para recuperar un valor de la memoria de clase adicional, use las funciones GetClassWord y GetClassLong . El miembro cbClsExtra de la estructura WNDCLASSEX especifica la cantidad de memoria de clase adicional que se va a asignar. Una aplicación que no usa memoria de clase adicional debe inicializar el miembro cbClsExtra en cero.

Memoria de ventana adicional

El sistema mantiene una estructura de datos interna para cada ventana. Al registrar una clase de ventana, una aplicación puede especificar varios bytes adicionales de memoria, denominado memoria de ventana adicional. Al crear una ventana de la clase , el sistema asigna y anexa la cantidad especificada de memoria de ventana adicional al final de la estructura de la ventana. Una aplicación puede usar esta memoria para almacenar datos específicos de la ventana.

Dado que se asigna memoria adicional desde el montón local del sistema, una aplicación debería usar con moderación la memoria de ventana adicional. Se produce un error en la función RegisterClassEx si la cantidad de memoria de ventana adicional solicitada es superior a 40 bytes. Si una aplicación necesita más de 40 bytes debe asignar su propia memoria y almacenar un puntero a la memoria en la memoria adicional de ventana.

La función SetWindowLong copia un valor en la memoria adicional. La función GetWindowLong recupera un valor de la memoria adicional. El miembro cbWndExtra de la estructura WNDCLASSEX especifica la cantidad de memoria de ventana adicional que se va a asignar. Una aplicación que no usa la memoria debe inicializar cbWndExtra en cero.