Tutoriais e Programação

Linguagem C - Diálogo personalizado

Dom

23

Nov

2008


21:24

  • Imprimir
(10 votos, média 5.00 de 5) 


C

Já sei, já sei... não estamos aqui para deixar o lcc-win32 fazer o que achar melhor. Afinal de contas, nós é que estamos no comando.

Já que sabemos como criar uma janela rapidinho, agora só falta saber como trabalhar com os recursos para personalizá-la. Não é necessário (ainda não) dominar a Resource Script Language, o lcc-win oferece uma maneira mais fácil: trabalhar no VISUAL!

Uma janela com firulas

Proceda exatamente como indicado no tutorial anterior, A primeira janela para criar um novo projeto com o nome dlg2. NÃO compile o programa. Quando chegar à janela de edição do programa, está na hora de dar uma olhada nos recursos. Mas, o que são recursos? Acompanhe a seguir e tente entender o máximo possível, porque é exatamente nos recursos que vamos mexer para personalizar nossa caixa de diálogo.

Os recursos da caixa de diálogo

Recursos são a descrição gráfica de elementos da interface com o usuário. Esta descrição fica num arquivo à parte, o arquivo de recursos. Numa linguagem com sintaxe própria - a Resource Script Language - são descritos elementos como menus, cursores, ícones, caixas de diálogo com botões, strings de texto, etc. É como se fosse um "programa" à parte. Para ser incorporado ao executável, este "programa" também precisa ser compilado, o que é feito com compiladores especiais, os compiladores de recursos (o lcc-win32 também possui um compilador de recursos, o lrc.exe).

Como até agora não fizemos nada relacionado aos recursos, é sinal que o lcc-win32 cuidou disso para nós. Efetivamente, o sistema criou dois arquivos "irmãos": o dlg2res.h e o dlg2.rc. O primeiro, o dlg2res.h, é um arquivo cabeçalho com uma definição:

#define IDD_MAINDIALOG 100

Se você quiser conferir o conteúdo deste arquivo, clique em |File/Open|, selecione o arquivo dlg2res.h e clique em [Open]. Na janela de edição aparece o texto acima. Este texto nada mais é do que a definição do apelido IDD_MAINDIALOG para o número identificador 100. Cada elemento da interface gráfica descrito nos recursos precisa de um número de identificação (ou ID) próprio. Digamos que se pretenda incluir uma caixa de texto nos recursos - é claro que ela não poderá ser identificada pelo ID 100 (pode ser 110, 120, 15, qualquer número diferente de 100). O apelido também pode ser outro. Podemos trocá-lo por ID_DIALOGOPRINCIPAL ou qualquer outra coisa.

O arquivo "irmão" do dlg2res.h é o arquivo de código fonte dos recursos, o dlg2.rc, escrito em Resource Scripting Language (RSL). Neste arquivo encontram-se as características dos elementos gráficos:

IDD_MAINDIALOG DIALOG 38, 27, 195, 86 STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "testedlg" FONT 8, "Helv" BEGIN DEFPUSHBUTTON "OK", IDOK, 35, 66, 40, 14 PUSHBUTTON "Cancel", IDCANCEL, 95, 66, 40, 14 END

Confira abrindo o arquivo com |File/Open| e, na caixa de diálogo "Open as resource file?" clique em [No]. Todas estas declarações se referem à caixa de diálogo, sua aparência, a posição das janelas-filhas (lembre-se, cada elemento é, na verdade, uma janela-filha), etc. Analisando as declarações temos:

  1. Encontramos o mesmo "apelido" IDD_MAINDIALOG seguido pela declaração DIALOG e por algumas coordenadas. Isto significa em RSL que o elemento IDD_MAINDIALOG é uma caixa de diálogo e que as coordenadas estão expressas em Unidades de Diálogo (não em pixels!). Estas unidades são uma mandrakaria para fazer com que a caixa de diálogo tenha uma aparência semelhante em todas as resoluções e em diferentes tamanhos de tela. Estão baseadas indiretamente no tamanho da fonte do sistema e existem APIs que transformam estas unidades em pixels e vice-versa.
  2. A declaração STYLE (estilo) indica ao interpretador o que deve ser feito quando a janela for criada. Mais adiante, em outro módulo, quando criarmos uma janela real e não uma caixa de diálogo, existe uma porção de coisas que podem ser feitas. Mas, no presente caso, o estilo indica que se trata de uma janela pop-up, visível, com título e um menu padrão do sistema.
  3. E, já que indicamos que queremos um título, precisamos indicar qual é este título através de uma string que segue a declaração CAPTION.
  4. A declaração FONT indica que queremos tamanho 8 e Helv.
  5. As declarações seguintes enumeram os controles da caixa de diálogo e suas descrições estão entre os delimitadores de bloco BEGIN e END. Aí se encontram dois botões, um destacado (DEFPUSHBUTTON) e um normal (PUSHBUTTON). Ambos possuem um texto ("Ok" e "Cancel"), IDs (IDOK, de valor numérico 1 e IDCANCEL, de valor numérico 2) e as coordenadas.

Este é o conjunto de instruções que será transformado pelo compilador de recursos num arquivo binário de recursos que o Windows possa interpretar. O mesmo será incorporado ao executável através de uma diretiva include. Reveja o início do programa:

#include #include #include #include #include "testedlgres.h"

Observe a forma de chamar os quatro primeiros (#include <...>) e o último (#include "..."). Para o pre-processador, include com <...> significa que o arquivo a ser incluído se encontra no diretório indicado na configuração do lcc (no caso, \lcc\include\), enquanto que o include "dlg2res.h" se encontra no diretório do projeto (no caso, \lcc\projects\teste\).


Editando os recursos com o lcc-win32

Na primeira compilação e linkedição, o lcc-win32 também compila o arquivo de recursos para que possa ser incorporado ao executável. Se quisermos modificar os recursos gerados automaticamente, precisamos fazer as alterações antes de compilar o programa. Uma outra possibilidade é compilar os recursos através de um comando de linha do lcc-win32, assunto de tutoriais posteriores.

Para editar os recursos com o lcc-win32, clique em |Design/Open/New|, selecione dlg2res.h, clique em [Open], expanda o diretório "Dialogs" clicando no sinal de + e dê um duplo clique em IDD_MAINDIALOG 100 dlg2. Como resultado, aparece uma janela de edição de recursos com a caixa de diálogo.

Recursos

Clique [T↓] - o primeiro botão da barra de ferramentas - para mostrar todos os controles disponíveis. Lá você vai encontrar campo de edição, check box, botão rádio, etc. Clique no campo de edição "Edit field" e o cursor indicará a seleção. Coloque o cursor na posição desejada dentro da caixa de diálogo e clique novamente para inserir o controle. Ele aparece como selecionado, o que é indicado pelos quadradinhos vermelhos ao redor do campo de edição.

Controle inserido

No campo de edição do aplicativo, "Name", acima da barra de ferramentas, digite ID_EDICAO. Este será o apelido do nosso campo de edição e o editor de recursos deve lhe atribuir a ID 101 no arquivo dlg2res.h (você poderá trocar o número se quiser, contanto que não conflite com outra ID). A seguir, redimensione o campo de edição clicando e arrastando um dos quadradinhos. Clique também no título da janela dlg2 para selecioná-la e a redimensione também.

Para conferir o resultado, clique no botão de teste (o que possui um ícone de interruptor, o penúltimo da barra de ferramentas). Você pode digitar qualquer texto no campo e depois clicar em [OK], em [Cancel] ou no botão com o interruptor para fechar a janela. Deu tudo certo e você está satisfeito? Eu não! Quero que o botão com "Cancel" mostre "Cancela" e que o título da janela seja Diálogo Personalizado. Então vamos lá...

Nome

Tendo voltado ao modo de edição, clique no botão com o texto "Cancel" para selecioná-lo - o que faz os quadradinhos vermelhos aparecerem. Clique no último botão da barra de ferramentas (o que parece ter uma patente de sargento) para abrir a janela de propriedades referentes ao controle selecionado. No campo "Text" ponha Cancela. A seguir, clique no título da caixa de diálogo - aparecem as propriedades da mesma. No campo "Caption text" escreva Diálogo Personalizado e depois feche a janela de propriedades.

Teste novamente com o botão do interruptor. Ah... agora está bem melhor! Como por enquanto é só, feche a janela de edição de recursos e clique em [Yes] para salvar as alterações no arquivo dlg2res.h, em [Yes] para salvar as alterações no arquivo dlg2.rc e novamente em [Yes] para atualizar o arquivo tmpres????.res.

Interagindo com o usuário

Na verdade, o que queremos é interagir com o usuário do nosso programa. Seria muita gentileza da nossa parte se o cursor já estivesse colocado no campo de edição quando a janela fosse apresentada (economiza um clique de mouse wink. No Windows, existe sempre apenas uma janela que esteja em foco e que recebe todas as entradas do teclado e do mouse.

Podemos forçar o foco numa janela com a função da API SetFocus e, como queremos determinar o foco ANTES da janela ser apresentada, é claro que vamos colocar esta informação na função InitializeApp do nosso programa - mesmo porque, ela foi feita para isto mesmo.

static int InitializeApp(HWND hDlg,WPARAM wParam, LPARAM lParam) { SetFocus(GetDlgItem(hDlg,ID_EDICAO)); return 1; }

Beleza pura! Compile e teste o programa para verificar que... NÃO FUNCIONOU sad. Que mistério é esse? Será que nossa central de mensagens não está sabendo enviar nossas solicitações ao sistemão? Veja:

static BOOL CALLBACK DialogFunc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: InitializeApp(hwndDlg,wParam,lParam); return TRUE; ...

Na nossa central de mensagens, quando recebemos a mensagem WM_INITDIALOG para avisar que nossa janela está pronta para ser mostrada na tela, antes de mostrá-la chamamos a função InitializeApp e enviamos como resposta TRUE. Se você tiver instalado o help das APIs do Windows (faça o download - 12.8 MB), coloque o cursor sobre a mensagem WM_INITDIALOG e digite F1. A parte importante é "The dialog box procedure should return TRUE to direct Windows to set the keyboard focus to the control given by hwndFocus. Otherwise, it should return FALSE to prevent Windows from setting the default keyboard focus". Resumindo, para que o Windows não acione o foco padrão (que é o teclado), a resposta precisa ser FALSE! Como o foco padrão não nos convém...

Taí! Troque o return TRUE; por return FALSE;. Salve a alteração com |File/Save| e dá-lhe testar novamente. Na mosca! O foco está no campo de edição.

Voltando para a função SetFocus, é preciso dizer que ela pede um parâmetro: o manipulador (handle) da janela (ou elemento da interface) que deve receber o foco. Temos o campo de edição de ID_EDICAO, mas desconhecemos seu manipulador. Então, o jeito é apelar novamente para a API e usar a função GetDlgItem. Esta função pede dois parâmetros - o manipulador da caixa de diálogo e o apelido do item - e retorna o manipulador do item indicado. O manipulador da caixa de diálogo vem pronto como parâmetro da função InitializeApp - é o hDlg. Pois bem, é possível obter o manipulador do item de diálogo com GetDlgItem que, por sua vez, é enviado como parâmetro da função SetFocus. É o famoso sanduiche de funções smile

Observações da vó

Tudo muito bem, tudo muito bom, mas... sempre precisa ter um mas para justificar o próximo módulo deste tutorial: do que adianta solicitar uma string do usuário se não pudermos identificá-la e usá-la para alguma coisa?

Se você ainda tiver fôlego, prossiga com o próximo tutorial, Caçando informações. Se tiver dúvidas, é melhor reler o texto e dirimi-las (gostou do dirimir???) antes de prosseguir. Se estiver num mato sem cachorro, faça contato que terei prazer em ajudar.

Abraço da vovo

лучшие игроки в покермагазин керамической посудыхарьков никас официальный сайтвидеокамера 3gdoctor2.ruпорядок выплатыполигон ооо