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 - Caçando informações

Qui

27

Nov

2008


14:02

(11 votos, média 4.00 de 5) 


C

A esta altura do campeonato já deu para perceber que o grande lance na programação Windows está diretamente relacionado à troca de mensagens entre o sistemão (o sistema operacional Windows) e a central de mensagens do nosso programa. Conforme prometido no final do módulo anterior, o Diálogo Personalizado, vamos rastrear as informações fornecidas pelo usuário. Se você não leu o tutorial anterior, sugiro que o faça, pois este é apenas a continuação do assunto. Além do mais vamos expandir o programa dlg2.c, também criado no módulo anterior.

Definindo os objetivos

Se o usuário clicar no botão [OK], queremos saber o teor do texto digitado. Esta operação tem dois aspectos:

  1. Saber se o botão [OK] foi clicado (se o usuário clicar em [Cancela] ou fechar a janela, é sinal de que não quer revelar o conteúdo digitado).
  2. Obter o texto do campo de edição.

Interceptando um clique no botão [OK]

Lá vamos nós para a central de mensagens do programa. Vou mostrá-la novamente para não dar margem a dúvidas:

static BOOL CALLBACK DialogFunc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: InitializeApp(hwndDlg,wParam,lParam); return FALSE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: EndDialog(hwndDlg,1); return 1; case IDCANCEL: EndDialog(hwndDlg,0); return 1; } break; case WM_CLOSE: EndDialog(hwndDlg,0); return TRUE; } return FALSE; }

O ponto para interceptar um clique no botão [OK] já está definido: é quando nossa central de mensagens receber uma mensagem do tipo WM_COMMAND trazendo no parâmetro wParam o valor IDOK. O que precisamos, além de fechar a caixa de diálogo com EndDialog, é obter o texto que foi digitado (ou não) no campo de edição. Chegou finalmente a hora de botar a mão na massa - vamos escrever uma função que realize o trabalho desejado.

Caçando o texto

Sabemos que o texto que queremos se encontra no campo de edição de apelido ID_EDICAO. Para capturá-lo, mais uma vez existe uma função da API, a GetDlgItemText. Acontece que esta função extrai o texto da janela-filha ID_EDICAO e transfere os caracteres para uma área de memória. Áreas de memória reservadas para armazenarem dados são chamadas de buffer, cuja tradução literal é pára-choque. Só Deus sabe porque escolheram este termo; pra mim, não tem nada a ver, preferia algo como cesta ou balaio wink

É claro que o balaio... perdão, o buffer precisa ter um tamanho suficientemente grande para conter todos os caracteres que pretendemos transferir. Além disso, é uma exclusividade da casa e não precisa cair no domínio público, ou seja, outros programas ou módulos não precisam saber da sua existência. Chamamos isto de buffer estático.

Por uma questão de ordem, colocamos a definição desta variável estática no início do programa, logo depois dos includes e da declaração do protótipo da função DialogFunc (aliás, ainda não expliquei a razão de protótipos de funções. Aguarde mais um pouco que a gente chega lá). Então, a coisa fica assim se chamarmos a variável estática de balaio e determinarmos que possa conter até 1024 caracteres:

... #include "testedlgres.h" static BOOL CALLBACK DialogFunc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); static char balaio[1024]; ...

Também, por uma questão de ordem, deixamos que a primeira função do programa seja a da entrada, a WinMain, seguida pela função de inicialização, a InitializeApp. Bem, então logo após, podemos escrever a seguinte função:

int PegaTexto(HWND hwnd) { memset(balaio,0,sizeof(balaio)); if (GetDlgItemText(hwnd, ID_EDICAO, balaio, sizeof(balaio))) { return 1; } return 0; }

A função de nome PegaTexto exige como parâmetro um manipulador (handle) e retorna um inteiro (int). Agora vamos por partes:

  1. A função memset preenche a área de memória reservada para a variável balaio com 1024 zeros. A função sizeof dá o tamanho do balaio (1024 caracteres). O que queremos é enviado através dos parâmetros e o resultado é que o buffer é zerado - o mesmo que dizer "o balaio é esvaziado".
  2. Segue-se uma diretiva if (cuja tradução é se). Então, SE GetDlgItemText conseguir transferir o conteúdo do campo de edição para o balaio, retorne 1 (o mesmo que TRUE); caso contrário, retorne 0 (o mesmo que FALSE).

Falta destrinchar a função GetDlgItemText. Esta função precisa dos seguintes parâmetros:

  • hwnd: o manipulador da janela-mãe, nossa caixa de diálogo.
  • ID_EDICAO: o apelido do campo de edição, a janela-filha da qual se quer extrair o texto.
  • balaio: o buffer onde devem ser colocados os caracteres.
  • sizeof(balaio): o tamanho do buffer, ou seja, o número máximo de caracteres que podem ser transferidos.

Tudo bem, mas o que é que o if faz com a função GetDlgItemText? SE o que? É que GetDlgItemText retorna o número de caracteres transferidos. Se for 1 ou mais caracteres, é o mesmo que dizer if TRUE, a condição é preenchida e o valor de retorno é 1; caso contrário o valor de retorno é 0. Tudo em riba, só falta chamar nossa função quando o usuário clicar o botão [OK]:

static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: InitializeApp(hwndDlg,wParam,lParam); return FALSE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: PegaTexto(hwndDlg); EndDialog(hwndDlg,1); return 1; ...

Informações adicionais