Tutoriais e Programação
Linguagem C - Uma janela de verdade
Sex 28 Nov 2008 10:57 |
- Detalhes
- Categoria: Linguagem C
- Atualização: Sexta, 28 Novembro 2008 12:09
- Autor: vovó Vicki
- Acessos: 24449
A vontade de ver as coisas funcionarem depressinha é grande. Ficar digerindo teoria é o tipo da coisa chata. O melhor é ver o resultado e depois esmiuçar a teoria - aí a coisa não fica no ar. Então, já que estamos programando para Windows, que tal encarar uma janela de verdade?
Criando o projeto
Os passos para criar um projeto você já conhece: |Project|Create|, dar nome ao projeto (eu dei o nome de "janela"), selecionar o diretório de trabalho (continuei usando o /lcc/projects/teste/), selecionar "Windows application" e clicar em [Create]. Confirme o diretório com [Yes], aceite o wizard com [Yes]. Selecione "Single window" e clique em [Ok], [Next], [Finish] e novamente em [OK]. Deixe tudo como está e clique em [Next], [Next] e [Finish] para finalmente chegar na janela de edição.
Deu para perceber que aceitamos todas as configurações apresentadas pelo wedit - só tivemos o trabalho de assinalar "Windows application". Dando uma olhada no código fonte gerado automaticamente, dá para perceber que é um pouco mais elaborado do que o código fonte da caixa de diálogo. Algumas coisas já conhecemos, em compensação tem umas outras que... bem, serão vistas mais para frente.
Compile e rode o programa. O que se vê é uma janela de fundo branco, com uma barra de título na parte superior, uma barra de status na parte inferior e um menu - este é o esqueleto de um aplicativo windows (mas não esquecido dentro do armário )
Analisando o código fonte
Como sempre, vamos começar com a função WinMain. Sabemos que ela não pode faltar, pois é a porta de entrada do nosso aplicativo:
O esquema básico é o mesmo dos nossos projetos de caixas de diálogo, mas esta função é mais parruda: iniciamos o aplicativo chamando a função InitApplication (onde será registrada a classe da janela, etc), carregamos os aceleradores de teclado (as teclas de atalho), criamos a janela, a barra de status, mostramos a janela na tela e entramos num loop de mensagens - o mesmo que dizer que entramos na central de comunicação do nosso programa. A única mensagem que pode nos "expulsar" da central de comunicação é a WM_QUIT.
Como sempre, um aplicativo windows nada mais é do que receber e enviar mensagens entre o sistema operacional e a central de comunicação do nosso programa. Vamos analisar o código por partes, começando com a primeira função chamada, a InitApplication.
A inicialização
Este procedimento começa manifestando a estrutura wc, do tipo WNDCLASS (esta estrutura já está manifestada no arquivo cabeçalho windows.h que inclui o win.h). Não é a primeira vez que falamos em estruturas, aliás, um conceito tão importante que será o assunto do próximo tutorial. Se quiser se antecipar, dê uma lida em Estruturas e Uniões e depois volte para este texto.
Vamos dar uma olhada na função estática InitApplication, que não precisa de parâmetros (void) e que retorna um valor lógico ou BOOL (1=verdadeiro ou 0=falso):
O estilo da janela (wc.style) é uma combinação de constantes inteiras (CS_HREDRAW, CS_VREDRAW e CS_DBLCLKS) feita através do operador OR, representado por uma barra vertical.
O operador OR, um operador lógico cuja tradução é OU, é o modo padrão da linguagem C manipular bits. Quais bits? Neste caso, dos valores correspondentes às constantes. Experimente o seguinte: clique com o botão direito do mouse sobre CS_HREDRAW e escolha |Show definition of CS_HREDRAW|. Na janelinha pop-up é possível verificar que o valor desta constante é 2. Faça o mesmo com as outras duas. A declaração wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; pode ser traduzida para wc.style = 2 OR 1 OR 8; ou wc.style = 2 | 1 | 8;. Aliás, HREDRAW pode ser traduzido para "Redesenhar a Horizontal", VREDRAW para "Redesenhar a Vertical" e DBLCLKS para "Cliques Duplos".
Note que os valores das constantes são potências de 2, ou seja, 2 é igual a 2 elevado a 1, 1 é igual a 2 elevado a 0 e 8 é igual a 2 elevado a 3. Existe uma regrinha fácil de ser guardada: toda potência de 2 possui apenas um único bit com valor 1; todos os outros bits estão zerados. Outra dica: a operação lógica OR é a comparação de dois bits. Apenas se os dois bits forem 0, o resultado será 0; caso contrário, será 1.
Conhecendo os valores e sabendo como funciona o OR, fica fácil perceber que 2 OR 1 OR 8, expresso em binário, será 0010 OR 0001 OR 1000, o que é igual a 1011, que correspode a 11 na notação decimal. Na verdade, cada bit desta "tripinha" de 4 bits, onde os bits são numerados da direita para a esquerda a partir de 0, funciona como uma flag: bit 0 ligado = janela redesenha na vertical; bit 1 ligado = janela redesenha na vertical; bit 3 ligado = janela aceita duplos cliques.
Logo após, ao invés de usar o DefDialogProc (próprio para caixas de diálogo), atribui-se o MainWndProc. O restante não difere da definição da estrutura WNDCLASS vista nas caixas de diálogo.
A tabela de teclas de atalho
Os aceleradores, dispostos em uma tabela, são as de teclas de atalho que permitem o acesso rápido a itens de menu sem o uso do mouse. Encontram-se nos recursos e podem ser editados.
Clique em |Design|New/Open|, a seguir escolha janelares.h, clique em [Open] e escolha "Accelerator" com um duplo clique. Você obterá uma janela de teclas aceleradoras indicando IDM_EXIT, com o valor 300 e com um valor de tecla ("Key value") de 81. 81 corresponde ao valor ASCII da letra "q".
Dê um duplo clique na linha do "Key value" 81 para obter a janela "Changing an accelerator key". Você pode mudar, adicionar ou eliminar teclas aceleradoras. Fique à vontade... só que, como já compilamos nosso programa, as alterações nos recursos terão de ser feitas "na unha", o que é assunto para mais tarde.
Isto foi só um adendo. Vamos voltar à vaca fria...
A central de mensagens
Após carregar os aceleradores, é criada a barra de status no rodapé da janela e, finalmente, a janela é mostrada. Até então, enquanto estava sendo "enfeitada", a janela permaneceu "escondida". Isto impediu que uma janela inacabada ficasse sassaricando na tela, mareando o usuário, e economizou muito tempo de execução.
Na verdade, a parte mais importante é o loop de mensagens que vem logo depois da chamada à função da API ShowWindow (mostre a janela):
Este loop, administrado por um comando de controle de fluxo while, chama a função da API GetMessage (pegar mensagem). Se a função retornar verdadeiro (TRUE), chamamos novamente a API para traduzir teclas aceleradoras (TranslateAccelerator). Esta função converterá uma sequência de teclas digitadas numa mensagem WM_COMMAND, como se tivesse sido enviada por um item de menu, se encontrar uma correspondência entre as teclas digitadas e a tabela de aceleradores que foi carregada algumas linhas antes.
Se TranslateAccelerator não encontrar nenhuma correspondência, a linha de execução passa para a função da API TranslateMessage (traduzir mensagem). Esta função controla as teclas digitadas e realiza o trabalho penoso de depurar a digitação do usuário (controlar sequências repetidas, intervalos, etc).
Finalmente é chamada a função da API DispatchMessage (despachar mensagem), que envia a mensagem para o procedimento indicado na classe janela, o MainWndProc.
É isso aí. Ficamos dando voltas e mais voltas neste loop até que, num dado momento seja gerada a mensagem WM_QUIT (terminar). Esta mensagem faz com que GetMessage retorne FALSE, interrompendo o loop e terminando o programa.
- Anterior
- Próximo >>