Sobre classes de janela

Cada classe de janela tem um procedimento de janela associado compartilhado por todas as janelas da mesma classe. O procedimento de janela processa mensagens para todas as janelas dessa classe e, portanto, controla seu comportamento e aparência. Para obter mais informações, confira Procedimentos do Windows.

Um processo deve registrar uma classe de janela antes de criar uma janela dessa classe. Registrar uma classe de janela associa um procedimento de janela, estilos de classe e outros atributos de classe a um nome de classe. Quando um processo especifica um nome de classe na função CreateWindow ou CreateWindowEx , o sistema cria uma janela com o procedimento de janela, estilos e outros atributos associados a esse nome de classe.

Esta seção discute os tópicos a seguir.

Tipos de classes de janela

Há três tipos de classes de janela:

Esses tipos diferem no escopo e em quando e como são registrados e destruídos.

Classes do sistema

Uma classe de sistema é uma classe de janela registrada pelo sistema. Muitas classes de sistema estão disponíveis para todos os processos usarem, enquanto outras são usadas apenas internamente pelo sistema. Como o sistema registra essas classes, um processo não pode destruí-las.

O sistema registra as classes do sistema para um processo na primeira vez que um de seus threads chama um usuário ou uma função GDI (Interface de Dispositivo gráfico) do Windows.

Cada aplicativo recebe sua própria cópia das classes do sistema. Todos os aplicativos baseados no Windows de 16 bits nas mesmas classes de sistema de compartilhamento de VDM, assim como fazem no Windows de 16 bits.

A tabela a seguir descreve as classes do sistema que estão disponíveis para uso por todos os processos.

Classe Descrição
Botão A classe de um botão.
ComboBox A classe para uma caixa de combinação.
Editar A classe para um controle de edição.
ListBox A classe de uma caixa de listagem.
Mdiclient A classe para uma janela de cliente MDI.
ScrollBar A classe para uma barra de rolagem.
Estático A classe para um controle estático.

 

A tabela a seguir descreve as classes do sistema que estão disponíveis apenas para uso pelo sistema. Eles estão listados aqui para fins de integridade.

Classe Descrição
ComboLBox A classe da caixa de listagem contida em uma caixa de combinação.
DDEMLEvent A classe para eventos DDEML (Dynamic Data Exchange Management Library).
Mensagem A classe para uma janela somente de mensagem.
#32768 A classe de um menu.
#32769 A classe para a janela da área de trabalho.
#32770 A classe de uma caixa de diálogo.
#32771 A classe para a janela de comutador de tarefas.
#32772 A classe para títulos de ícone.

 

Classes globais de aplicativo

Uma classe global de aplicativo é uma classe de janela registrada por um executável ou DLL que está disponível para todos os outros módulos no processo. Por exemplo, seu .dll pode chamar a função RegisterClassEx para registrar uma classe de janela que define um controle personalizado como uma classe global de aplicativo para que um processo que carrega o .dll possa criar instâncias do controle personalizado.

Para criar uma classe que pode ser usada em cada processo, crie a classe de janela em um .dll e carregue o .dll em cada processo. Para carregar o .dll em cada processo, adicione seu nome ao valor AppInit_DLLs na seguinte chave do Registro:

HKEY_LOCAL_MACHINE\Software\Microsoft\\ Windows NT CurrentVersion\Windows

Sempre que um processo é iniciado, o sistema carrega o .dll especificado no contexto do processo recém-iniciado antes de chamar sua função de ponto de entrada. O .dll deve registrar a classe durante seu procedimento de inicialização e deve especificar o estilo CS_GLOBALCLASS . Para obter mais informações, consulte Estilos de classe.

Para remover uma classe global de aplicativo e liberar o armazenamento associado a ela, use a função UnregisterClass .

Classes locais do aplicativo

Uma classe local de aplicativo é qualquer classe de janela que um executável ou .dll registra para seu uso exclusivo. Embora você possa registrar qualquer número de classes locais, é comum registrar apenas uma. Essa classe de janela dá suporte ao procedimento de janela da janela main do aplicativo.

O sistema destrói uma classe local quando o módulo que a registrou é fechado. Um aplicativo também pode usar a função UnregisterClass para remover uma classe local e liberar o armazenamento associado a ela.

Como o sistema localiza uma classe de janela

O sistema mantém uma lista de estruturas para cada um dos três tipos de classes de janela. Quando um aplicativo chama a função CreateWindow ou CreateWindowEx para criar uma janela com uma classe especificada, o sistema usa o procedimento a seguir para localizar a classe .

  1. Pesquise na lista de classes locais do aplicativo uma classe com o nome especificado cujo identificador de instância corresponde ao identificador de instância do módulo. (Vários módulos podem usar o mesmo nome para registrar classes locais no mesmo processo.)
  2. Se o nome não estiver na lista de classes locais do aplicativo, pesquise a lista de classes globais do aplicativo.
  3. Se o nome não estiver na lista de classes globais do aplicativo, pesquise a lista de classes do sistema.

Todas as janelas criadas pelo aplicativo usam esse procedimento, incluindo janelas criadas pelo sistema em nome do aplicativo, como caixas de diálogo. É possível substituir classes do sistema sem afetar outros aplicativos. Ou seja, um aplicativo pode registrar uma classe local de aplicativo com o mesmo nome que uma classe do sistema. Isso substitui a classe do sistema no contexto do aplicativo, mas não impede que outros aplicativos usem a classe do sistema.

Registrando uma classe de janela

Uma classe de janela define os atributos de uma janela, como seu estilo, ícone, cursor, menu e procedimento de janela. A primeira etapa no registro de uma classe de janela é preencher uma estrutura WNDCLASSEX com as informações da classe de janela. Para obter mais informações, consulte Elementos de uma classe window. Em seguida, passe a estrutura para a função RegisterClassEx . Para obter mais informações, consulte Usando classes de janela.

Para registrar uma classe global de aplicativo, especifique o estilo CS_GLOBALCLASS no membro de estilo da estrutura WNDCLASSEX . Ao registrar uma classe local do aplicativo, não especifique o estilo CS_GLOBALCLASS .

Se você registrar a classe de janela usando a versão ANSI de RegisterClassEx, RegisterClassExA, o aplicativo solicitará que o sistema passe parâmetros de texto de mensagens para as janelas da classe criada usando o conjunto de caracteres ANSI; se você registrar a classe usando a versão Unicode de RegisterClassEx, RegisterClassExW, o aplicativo solicitará que o sistema passe parâmetros de texto de mensagens para as janelas da classe criada usando o conjunto de caracteres Unicode. A função IsWindowUnicode permite que os aplicativos consultem a natureza de cada janela. Para obter mais informações sobre as funções ANSI e Unicode, consulte Convenções para protótipos de função.

A DLL ou executável que registrou a classe é o proprietário da classe . O sistema determina a propriedade da classe do membro hInstance da estrutura WNDCLASSEX passada para a função RegisterClassEx quando a classe é registrada. Para DLLs, o membro hInstance deve ser o identificador para a instância .dll.

A classe não é destruída quando o .dll que a possui é descarregado. Portanto, se o sistema chamar o procedimento de janela para uma janela dessa classe, isso causará uma violação de acesso, pois o .dll que contém o procedimento de janela não está mais na memória. O processo deve destruir todas as janelas usando a classe antes que o .dll seja descarregado e chamar a função UnregisterClass .

Elementos de uma classe window

Os elementos de uma classe de janela definem o comportamento padrão das janelas pertencentes à classe . O aplicativo que registra uma classe de janela atribui elementos à classe definindo membros apropriados em uma estrutura WNDCLASSEX e passando a estrutura para a função RegisterClassEx . As funções GetClassInfoEx e GetClassLong recuperam informações sobre uma determinada classe de janela. A função SetClassLong altera elementos de uma classe local ou global que o aplicativo já registrou.

Embora uma classe de janela completa seja composta por muitos elementos, o sistema requer apenas que um aplicativo forneça um nome de classe, o endereço de procedimento de janela e um identificador de instância. Use os outros elementos para definir atributos padrão para janelas da classe, como a forma do cursor e o conteúdo do menu da janela. Você deve inicializar todos os membros não utilizados da estrutura WNDCLASSEX como zero ou NULL. Os elementos da classe de janela são conforme mostrado na tabela a seguir.

Elemento Finalidade
Nome de Classe Distingue a classe de outras classes registradas.
Endereço do procedimento de janela Ponteiro para a função que processa todas as mensagens enviadas para janelas na classe e define o comportamento da janela.
Identificador de Instância Identifica o aplicativo ou .dll que registrou a classe .
Cursor de Classe Define o cursor do mouse que o sistema exibe para uma janela da classe .
Ícones de classe Define o ícone grande e o ícone pequeno.
Pincel de Plano de Fundo de Classe Define a cor e o padrão que preenchem a área do cliente quando a janela é aberta ou pintada.
Menu classe Especifica o menu padrão para janelas que não definem explicitamente um menu.
Estilos de Classe Define como atualizar a janela depois de movê-la ou redimensioná-la, como processar cliques duplos do mouse, como alocar espaço para o contexto do dispositivo e outros aspectos da janela.
Memória de classe extra Especifica a quantidade de memória extra, em bytes, que o sistema deve reservar para a classe . Todas as janelas da classe compartilham a memória extra e podem usá-la para qualquer finalidade definida pelo aplicativo. O sistema inicializa essa memória como zero.
Memória extra da janela Especifica a quantidade de memória extra, em bytes, que o sistema deve reservar para cada janela pertencente à classe . A memória extra pode ser usada para qualquer finalidade definida pelo aplicativo. O sistema inicializa essa memória como zero.

 

Nome da Classe

Cada classe de janela precisa de um Nome de Classe para distinguir uma classe de outra. Atribua um nome de classe definindo o membro lpszClassName da estrutura WNDCLASSEX para o endereço de uma cadeia de caracteres terminada em nulo que especifica o nome. Como as classes de janela são específicas do processo, os nomes de classe de janela precisam ser exclusivos apenas no mesmo processo. Além disso, como os nomes de classe ocupam espaço na tabela atom privada do sistema, você deve manter as cadeias de caracteres de nome de classe o mais curto possível.

A função GetClassName recupera o nome da classe à qual uma determinada janela pertence.

Endereço do procedimento de janela

Cada classe precisa de um endereço de procedimento de janela para definir o ponto de entrada do procedimento de janela usado para processar todas as mensagens para janelas na classe . O sistema passa mensagens para o procedimento quando exige que a janela execute tarefas, como pintar sua área de cliente ou responder à entrada do usuário. Um processo atribui um procedimento de janela a uma classe copiando seu endereço para o membro lpfnWndProc da estrutura WNDCLASSEX . Para obter mais informações, confira Procedimentos do Windows.

Identificador de Instância

Cada classe de janela requer um identificador de instância para identificar o aplicativo ou .dll que registrou a classe . O sistema requer identificadores de instância para acompanhar todos os módulos. O sistema atribui um identificador a cada cópia de um executável em execução ou .dll.

O sistema passa um identificador de instância para a função de ponto de entrada de cada executável (consulte WinMain) e .dll (consulte DllMain). O executável ou .dll atribui esse identificador de instância à classe copiando-o para o membro hInstance da estrutura WNDCLASSEX .

Cursor de Classe

O cursor de classe define a forma do cursor quando ele está na área do cliente de uma janela na classe . O sistema define automaticamente o cursor para a forma determinada quando o cursor entra na área do cliente da janela e garante que ele mantenha essa forma enquanto ela permanece na área do cliente. Para atribuir uma forma de cursor a uma classe de janela, carregue uma forma de cursor predefinida usando a função LoadCursor e atribua o identificador de cursor retornado ao membro hCursor da estrutura WNDCLASSEX . Como alternativa, forneça um recurso de cursor personalizado e use a função LoadCursor para carregá-lo dos recursos do aplicativo.

O sistema não requer um cursor de classe. Se um aplicativo definir o membro hCursor da estrutura WNDCLASSEX como NULL, nenhum cursor de classe será definido. O sistema pressupõe que a janela define a forma do cursor sempre que o cursor se move para a janela. Uma janela pode definir a forma do cursor chamando a função SetCursor sempre que a janela receber a mensagem WM_MOUSEMOVE . Para obter mais informações sobre cursores, consulte Cursores.

Ícones de classe

Um ícone de classe é uma imagem que o sistema usa para representar uma janela de uma classe específica. Um aplicativo pode ter dois ícones de classe: um grande e outro pequeno. O sistema exibe o ícone de classe grande de uma janela na janela de comutador de tarefas que aparece quando o usuário pressiona ALT+TAB e nas exibições de ícone grande da barra de tarefas e do gerenciador. O ícone de classe pequena aparece na barra de título de uma janela e nos modos de exibição de ícone pequenos da barra de tarefas e do explorador.

Para atribuir um ícone grande e pequeno a uma classe de janela, especifique os identificadores dos ícones nos membros hIcon e hIconSm da estrutura WNDCLASSEX . As dimensões de ícone devem estar em conformidade com as dimensões necessárias para ícones de classe grandes e pequenas. Para um ícone de classe grande, você pode determinar as dimensões necessárias especificando os valores SM_CXICON e SM_CYICON em uma chamada para a função GetSystemMetrics . Para um ícone de classe pequena, especifique os valores SM_CXSMICON e SM_CYSMICON . Para obter informações, consulte Ícones.

Se um aplicativo definir os membros hIcon e hIconSm da estrutura WNDCLASSEX como NULL, o sistema usará o ícone de aplicativo padrão como os ícones de classe grande e pequena para a classe de janela. Se você especificar um ícone de classe grande, mas não um pequeno, o sistema criará um ícone de classe pequena com base no grande. No entanto, se você especificar um ícone de classe pequena, mas não um grande, o sistema usará o ícone de aplicativo padrão como o ícone de classe grande e o ícone especificado como o ícone de classe pequena.

Você pode substituir o ícone de classe grande ou pequena para uma janela específica usando a mensagem WM_SETICON . Você pode recuperar o ícone de classe grande ou pequena atual usando a mensagem WM_GETICON .

Pincel de Plano de Fundo de Classe

Um pincel de plano de fundo de classe prepara a área do cliente de uma janela para o desenho subsequente do aplicativo. O sistema usa o pincel para preencher a área do cliente com uma cor ou padrão sólido, removendo assim todas as imagens anteriores desse local, quer elas pertençam à janela ou não. O sistema notifica uma janela de que sua tela de fundo deve ser pintada enviando a mensagem WM_ERASEBKGND para a janela. Para obter mais informações, consulte Pincéis.

Para atribuir um pincel de plano de fundo a uma classe, crie um pincel usando as funções GDI apropriadas e atribua a alça de pincel retornada ao membro hbrBackground da estrutura WNDCLASSEX .

Em vez de criar um pincel, um aplicativo pode definir o membro hbrBackground como um dos valores de cor padrão do sistema. Para obter uma lista dos valores de cor padrão do sistema, consulte SetSysColors.

Para usar uma cor padrão do sistema, o aplicativo deve aumentar o valor da cor da tela de fundo em um. Por exemplo, COLOR_BACKGROUND + 1 é a cor da tela de fundo do sistema. Como alternativa, você pode usar a função GetSysColorBrush para recuperar um identificador para um pincel que corresponde a uma cor do sistema padrão e especificar o identificador no membro hbrBackground da estrutura WNDCLASSEX .

O sistema não exige que uma classe de janela tenha um pincel de plano de fundo de classe. Se esse parâmetro for definido como NULL, a janela deverá pintar seu próprio plano de fundo sempre que receber a mensagem WM_ERASEBKGND .

Menu classe

Um menu de classe define o menu padrão a ser usado pelas janelas da classe se nenhum menu explícito for dado quando as janelas forem criadas. Um menu é uma lista de comandos dos quais um usuário pode escolher ações para o aplicativo realizar.

Você pode atribuir um menu a uma classe definindo o membro lpszMenuName da estrutura WNDCLASSEX para o endereço de uma cadeia de caracteres terminada em nulo que especifica o nome do recurso do menu. Supõe-se que o menu seja um recurso no aplicativo especificado. O sistema carrega automaticamente o menu quando é necessário. Se o recurso de menu for identificado por um inteiro e não por um nome, o aplicativo poderá definir o membro lpszMenuName para esse inteiro aplicando a macro MAKEINTRESOURCE antes de atribuir o valor.

O sistema não requer um menu de classe. Se um aplicativo definir o membro lpszMenuName da estrutura WNDCLASSEX como NULL, as janelas da classe não terão barras de menu. Mesmo que nenhum menu de classe seja dado, um aplicativo ainda poderá definir uma barra de menus para uma janela ao criar a janela.

Se um menu for dado para uma classe e uma janela filho dessa classe for criada, o menu será ignorado. Para obter mais informações, consulte Menus.

Estilos de Classe

Os estilos de classe definem elementos adicionais da classe de janela. Dois ou mais estilos podem ser combinados usando o operador OR (|) bit a bit. Para atribuir um estilo a uma classe de janela, atribua o estilo ao membro de estilo da estrutura WNDCLASSEX . Para obter uma lista de estilos de classe, consulte Estilos de classe de janela.

Classes e contextos de dispositivo

Um contexto de dispositivo é um conjunto especial de valores que os aplicativos usam para desenhar na área do cliente de suas janelas. O sistema requer um contexto de dispositivo para cada janela na tela, mas permite alguma flexibilidade na forma como o sistema armazena e trata esse contexto de dispositivo.

Se nenhum estilo de contexto de dispositivo for fornecido explicitamente, o sistema pressupõe que cada janela use um contexto de dispositivo recuperado de um pool de contextos mantido pelo sistema. Nesses casos, cada janela deve recuperar e inicializar o contexto do dispositivo antes de pintá-lo e liberá-lo após a pintura.

Para evitar recuperar um contexto de dispositivo sempre que precisar pintar dentro de uma janela, um aplicativo pode especificar o estilo CS_OWNDC para a classe de janela. Esse estilo de classe direciona o sistema para criar um contexto de dispositivo privado, ou seja, para alocar um contexto de dispositivo exclusivo para cada janela na classe . O aplicativo só precisa recuperar o contexto uma vez e, em seguida, usá-lo para toda a pintura subsequente.

Memória de classe extra

O sistema mantém uma estrutura WNDCLASSEX internamente para cada classe de janela no sistema. Quando um aplicativo registra uma classe de janela, ele pode direcionar o sistema para alocar e acrescentar vários bytes adicionais de memória ao final da estrutura WNDCLASSEX . Essa memória é chamada de memória de classe extra e é compartilhada por todas as janelas pertencentes à classe . Use a memória de classe extra para armazenar qualquer informação relativa à classe .

Como a memória extra é alocada do heap local do sistema, um aplicativo deve usar memória de classe extra com moderação. A função RegisterClassEx falhará se a quantidade de memória de classe extra solicitada for maior que 40 bytes. Se um aplicativo exigir mais de 40 bytes, ele deverá alocar sua própria memória e armazenar um ponteiro para a memória na memória de classe extra.

As funções SetClassWord e SetClassLong copiam um valor para a memória de classe extra. Para recuperar um valor da memória de classe extra, use as funções GetClassWord e GetClassLong . O membro cbClsExtra da estrutura WNDCLASSEX especifica a quantidade de memória de classe extra a ser alocada. Um aplicativo que não usa memória de classe extra deve inicializar o membro cbClsExtra como zero.

Memória extra da janela

O sistema mantém uma estrutura de dados interna para cada janela. Ao registrar uma classe de janela, um aplicativo pode especificar vários bytes adicionais de memória, chamados de memória de janela extra. Ao criar uma janela da classe , o sistema aloca e acrescenta a quantidade especificada de memória de janela extra ao final da estrutura da janela. Um aplicativo pode usar essa memória para armazenar dados específicos da janela.

Como a memória extra é alocada do heap local do sistema, um aplicativo deve usar memória de janela extra com moderação. A função RegisterClassEx falhará se a quantidade de memória de janela extra solicitada for maior que 40 bytes. Se um aplicativo exigir mais de 40 bytes, ele deverá alocar sua própria memória e armazenar um ponteiro para a memória na memória de janela extra.

A função SetWindowLong copia um valor para a memória extra. A função GetWindowLong recupera um valor da memória extra. O membro cbWndExtra da estrutura WNDCLASSEX especifica a quantidade de memória de janela extra a ser alocada. Um aplicativo que não usa a memória deve inicializar cbWndExtra como zero.