A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Tutoriais e Programação

Linguagem C - A primeira janela

Dom

23

Nov

2008


01:41

(26 votos, média 4.58 de 5) 


A função WinMain

A função WinMain é o ponto de entrada do programa. É uma função da API do Windows que pede quatro parâmetros, usando a convenção de chamada stdcall (APIENTRY especifica este tipo de chamada), e que retorna um inteiro (int):

int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow);
  1. HINSTANCE hinst é o manipulador (handle) da instância do programa. Seu valor é sempre 0x400000 em hexadecimal e não é usado para nada... coisas do Windows.
  2. HINSTANCE hinstPrev refere-se a uma instância anterior do programa: outro manipulador misterioso. Contém sempre zero e também nunca é usado.
  3. LPSTR lpCmdLine é importante! É um ponteiro para uma string de caracteres que contém os argumentos da linha de comando.
  4. int nCmdShow contém um inteiro que indica se o programa foi chamado com a instrução de ficar oculto ou aparecer normalmente, ou outras instruções que podem ser usadas quando a janela principal for criada.
int APIENTRY WinMain( HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; INITCOMMONCONTROLSEX cc; memset(&wc,0,sizeof(wc)); wc.lpfnWndProc = DefDlgProc; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hinst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wc.lpszClassName = "testedlg"; RegisterClass(&wc); memset(&cc,0,sizeof(cc)); cc.dwSize = sizeof(cc); cc.dwICC = 0xffffffff; InitCommonControlsEx(&cc); return DialogBox( hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc); }

A tarefa principal desta função é criar uma estrutura WNDCLASS, preenchê-la com dados e depois chamar a função da API DialogBox. WNDCLASS wc; cria a estrutura e todas as linhas com wc.algumaCoisa atribuem valores aos campos desta estrutura. Depois de pronta, esta estrutura precisa ser registrada como uma classe do sistema operacional Windows, o que é feito com RegisterClass(&wc);.

Uma classe, no Windows, é um conjunto de objetos de janela que compartilham um procedimento comum. Quando alguma mensagem ou evento referente a esta janela é detectado pelo sistema, é enviada uma mensagem à esta janela. Por exemplo, quando movemos o cursor do mouse sobre esta janela, o sistema envia uma mensagem do tipo WM_MOUSEMOVE para o procedimento da janela, informando-o do evento. Este sistema de troca de mensagens pode ser comparado ao um serviço SAC (serviço de atendimento ao consumidor). Não se confunda: SAC não é um acrônimo usado em informática - serve apenas como comparação.

Quando um programa está rodando, existe um caminhão de mensagens sendo constantemente enviadas e recebidas. Seria impossível gerenciar todas. Para nossa sorte, apenas tratamos as mensagens que nos interessam e, as restantes, passamos para o procedimento padrão (o SAC que se vire!).

Existem vários procedimentos padrão: para uma janela normal há o DefWindowProc; para uma janela MDI, existe o MDIDefWindowProc; e para caixas de diálogo, como neste caso, há o procedimento DefDlgProc. Dá para perceber que, para cada tipo de janela, podemos contar com um SAC especializado wink

Sabendo disso, informamos na nossa estrutura wc que o procedimento padrão de troca de mensagens é o DefDlgProc (wc.lpfnWndProc = DefDlgProc;), indicando ao sistema o SAC apropriado.

Os dados mais importantes da estrutura foram explicados. Agora está na hora de registrar a estrutura para que seja colocada à nossa disposição pelo sistema: chamamos a função da API RegisterClass(&wc); levando como parâmetro o ponteiro para a nossa estrutura wc. O Windows que se vire com o resto...

A última declaração da função WinMain vale uma explicação mais detalhada. Agora que temos uma estrutura registrada, chamamos a função da API DialogBox:

DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc);

O parâmetro hinst, que muitas funções da API ainda exigem, é o valor que recebemos do sistema quando chamamos a função WinMain. Depois usamos a macro MAKEINTRESOURCE para fazer com que o compilador transforme em ponteiro o valor de IDD_MAINDIALOG. Este valor foi definido nos recursos, que serão tema do próximo módulo. Por enquanto, deixa quieto...

O terceiro parâmetro é NULL. Na verdade, deveria ser o valor do manipulador (handle) da janela-mãe desta caixa de diálogo. As caixas de diálogo, normalmente, são acessórios do aplicativo e têm nesse parâmetro a indicação do manipulador da janela à qual pertencem. Acontece que estamos construindo uma caixa de diálogo autônoma, que não possui uma janela-mãe (pobrezinha, é órfã!), portanto podemos passar um NULL (nadinha de nada) como referência.

O quarto e último parâmetro é a indicação de que, caso existam mensagens importantes, estas devem ser direcionadas para a função DialogFunc, que será vista a seguir.

Informações adicionais