Aldeia Numaboa
Um portal diferente em Português do Brasil
Informática da Aldeia

Tutoriais
Home Informática Tutoriais e Programação Linguagem C Linguagem C - Projeto Espião III

Na Aldeia

Há 94 visitantes online

3304 registros
0 hoje
9 nesta semana
41 neste mês

Boas vindas: Xico

Estatística

Artigos: 1063
Leituras: 6036445
Arquivados: 21
Downloads: 533
Baixados: 172236
Glossário: 1208
Bibliografia: 25
Links: 90

Visitas de onde

Top 5:
Brasil flag 73%Brasil (47535)
Portugal flag 5%Portugal (3069)
EUA flag 3%EUA (2132)
Rússia flag 0%Rússia (259)
Holanda flag 0%Holanda (239)
65127 visitas de 100 países

Hoje:135
Ontem:2587
No mês:39312
Mês passado:25815
Total:65127
Recorde:3037
No dia:04.03.10
Leituras hoje:19006
Leituras Total:280558
Bots hoje:60
Dados desde:16.02.2010

Login



Kanji da hora




Faça contato






Dom

30

Nov

2008


20:20

Linguagem C - Projeto Espião III PDF Imprimir Indique esta página
(1 voto, média 5.0 de 5)
Escrito por vovó Vicki   


Índice do Artigo
Linguagem C - Projeto Espião III
Identificando a janela
Observações
Todas as páginas
C

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 piscada

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):

  1. LRESULT CALLBACK MainWndProc(
  2. HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3. {
  4. static HWND hwndTree;
  5. RECT rc, rcStatus;
  6.  
  7. switch (msg) {
  8. case WM_CREATE:
  9. hwndTree = janelaTree(hwnd,IDJANELATREE);
  10. break;
  11. case WM_NOTIFY:
  12. return TrataWmNotify(hwnd,wParam,lParam);
  13. ...

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:

LRESULT TrataWmNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
   NMHDR *apontaGrito;
   TV_HITTESTINFO testaClique;
   HWND hTree = GetDlgItem(hwnd,IDJANELATREE);
   HTREEITEM hti;
   HWND hwndAlvo;
 
   apontaGrito = (NMHDR *)lParam;
   switch (apontaGrito->code) {
   case NM_CLICK:
      memset(&testaClique,0,sizeof(TV_HITTESTINFO));
      GetCursorPos(&testaClique.pt);
      MapWindowPoints(HWND_DESKTOP,hTree,&testaClique.pt,1);
      hti = TreeView_HitTest(hTree,&testaClique);
      if (hti == (HTREEITEM)0) break;
      hwndAlvo = PegaItemInfo(hTree,hti);
      PoeTextoStatus(hwnd,hwndAlvo);
      break;
   }
   return DefWindowProc(hwnd,WM_NOTIFY,wParam,lParam);
}

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:

typedef struct tagNMHDR { 
      HWND hwndFrom; 
      UINT idFrom; 
      UINT code; 
   } 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 sorriso )
  • 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:

  1. 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;).
  2. 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) ).
  3. 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:

typedef struct _TVHITTESTINFO {
      POINT     pt;
      UINT      <a class="mosinfopop" style="cursor:help;border-bottom:1px dotted #000000;" href="javascript:void(0)" onmouseover="return overlib('<p>Bandeiras de sinalização ou bits de indicação de estado. Muito usadas na linguagem assembly.</p>&amp;nbsp;<br />', CAPTION, 'flags',BELOW,RIGHT, WIDTH, 300, FGCOLOR, '#CCCCFF', BGCOLOR, '#333399', TEXTCOLOR, '#000000', CAPCOLOR, '#FFFFFF', OFFSETX, 10, OFFSETY, 10);" onmouseout="return nd();" > flags</a>;
      HTREEITEM hItem;
   } TV_HITTESTINFO, FAR *LPTV_HITTESTINFO;

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:

  1. 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.
  2. 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).
  3. 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.
  4. 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.
  5. Com um NM_CLICK válido, chamamos duas funções, a PegaItemInfo e a PoeTextoStatus, das quais falaremos adiante.
  6. 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.


Última atualização ( Dom, 30.11.2008 21:14 )
 

Topo

Topo

Exceto onde especificamente citado, todo material deste site está sob Licença Creative Commons