Tutoriais e Programação
Linguagem C - Projeto Espião III
Dom 30 Nov 2008 21:20 |
- Detalhes
- Categoria: Linguagem C
- Atualização: Domingo, 30 Novembro 2008 22:14
- Autor: vovó Vicki
- Acessos: 10702
Se você seguiu os tutoriais anteriores, então seu programa espião.exe já deve estar funcionando. Mas está meio tímido, porque não fala com o usuário - só mostra o menu e, quando solicitado, a árvore com as janelas abertas no momento da solicitação. Calado demais, este nosso espião. Neste tutorial vamos fazer com que entregue e ouro
Quem é quem no pedaço
Nosso projeto inicial incluía informações sobre as janelas na barra de status. Uma das formas de pedir informações é clicando num dos itens da árvore. Mas, como saber quando o usuário clica um item?
O controle de árvore, assim como muitos outros controles, envia mensagens do tipo WM_NOTIFY para nossa central de mensagens toda vez que um evento acontece, ou seja, com qualquer coisinha o controle grita. É justamente esta mensagem que precisamos interceptar com o auxílio do caso WM_NOTIFY (linhas 11 e 12):
Fiéis ao estilo "top-down", chamamos a função TrataWmNotify, a qual deverá fazer o serviço final de espionagem: obter informações precisas sobre a janela indicada pelo usuário.
Catando gritos
O código da função é um tantinho mais complicado que os anteriores, mas não é nada que assuste. Veja abaixo:
De todos os gritos que o controle de árvore possa dar, o único que nos interessa é o NM_CLICK. Como este controle é muito nervoso (por ser muito complexo), a quantidade de gritos que ele é capaz de dar é muito grande. O tipo de grito dado é sempre armazenado no parâmetro lParam da mensagem WM_NOTIFY. Este parâmetro nada mais é do que um ponteiro indicando o endereço de memória de uma estrutura chamada de NMHDR:
O campo HWND hwndFrom contém o manipulador da janela que está gritando (ou enviando a mensagem, como queira), o campo UINT idFrom contém o identificador do controle e o campo UINT code contém o código do grito. Existem oito tipos de grito:
- NM_CLICK: o controle foi clicado com o botão esquerdo do mouse
- NM_DBLCLK: o controle recebeu um duplo clique com o botão esquerdo do mouse
- NM_KILLFOCUS: o controle perdeu o foco de entrada
- NM_OUTOFMEMORY: o controle não pode completar uma operação por falta de memória (dá-lhe gynko biloba )
- NM_RCLICK: o controle recebeu um clique com o botão direito do mouse
- NM_RDCLICK: o controle recebeu um duplo clique com o botão direito do mouse
- NM_RETURN: o controle tem o foco e o usuário digitou a tecla Enter
- NM_SETFOCUS: o controle recebeu o foco
Selecionando gritos
Como já disse, o único grito que nos interessa é o NM_CLICK, mas não todos os NM_CLICKs. Se o usuário clicar sobre um item, sim; se clicar na janela do controle, mas não sobre um item, não! Então, vamos por partes:
- Sabendo que vamos precisar de um ponteiro que nos indique o endereço da estrutura NMHDR, manisfestamos a variável *apontaGrito do tipo NMHDR. Mais abaixo, definimos apontaGrito como o ponteiro para a estrutura do tipo MNHDR do parâmetro lParam (apontaGrito = (NMHDR *)lParam;).
- Tendo como acessar a estrutura NMHDR, usamos um switch apontando para o campo code da estrutura para interceptar o caso NM_CLICK (lembre-se que ponteiros usam -> para referenciar um campo, e não um ponto, por isso switch (apontaGrito->code) ).
- No caso do switch interceptar um NM_CLICK, a primeira providência é limpar a área de memória reservada para a estrutura testaClique, do tipo TV_HITTESTINFO, que foi previamente manifestada.
Antes de prosseguir, vamos dar uma olhada na definição da estrutura TV_HITTESTINFO, usada para determinar a localização de um ponto relativo a um controle de árvore:
POINT pt contém as coordenadas-cliente do ponto testado, UINT flags recebe as informações do resultado do ponto que foi testado e HTREEITEM hItem contém o manipulador (handle) do item que ocupa o ponto. Agora podemos continuar com a análise:
- Chamando a função da API GetCursorPos, colocamos as coordenadas do ponto clicado na estrutura testaClique. Como precisamos passar como parâmetro o endereço do campo pt da estrutura, a chamada é feita com &testaClique.pt.
- A função MapWindowPoints transforma (mapeia) um conjunto de pontos de um espaço de coordenadas relativos a uma janela para um espaço de coordenadas relativos a outra janela. Se o primeiro parâmetro for NULL ou HWND_DESKTOP, os pontos serão mapeados como coordenadas de tela. O segundo parâmetro (htree) indica a janela para os quais os pontos serão mapeados. O terceiro parâmetro é o endereço onde se encontram os pontos que devem ser mapeados e o último indica quantos conjuntos de pontos existem (no caso, temos apenas 1 conjunto de coordenadas).
- Mapeadas as coordenadas de tela do clique, usamos a macro TreeView_HitTest que determina a localização do ponto especificado em relação à área cliente de um controle de árvore. Esta macro retorna o item ao qual o ponto pertence ou NULL se o ponto não estiver em um dos itens. Este valor de retorno é armazenado na variável hti, do tipo HTREEITEM, anteriormente manifestada.
- Se o valor de hti for 0 (zero), é sinal que o clique foi dado fora da área de um item da árvore. Neste caso interrompe-se o caso com break. Se hti contiver um item da árvore, então o grito do controle nos interessa.
- Com um NM_CLICK válido, chamamos duas funções, a PegaItemInfo e a PoeTextoStatus, das quais falaremos adiante.
- Finalmente passamos todas as mensagens para o procedimento padrão da janela chamando o procedimento DefWindowProc com todos os parâmetros iniciais. Isto é uma atitude não invasiva, altamente aconselhável porque o controle pode precisar das mensagens e porque queremos manter os distúrbios no menor nível possível para não afetar negativamente o ambiente.
- Anterior
- Próximo >>