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 - Projeto Espião II

Sab

29

Nov

2008


18:55

(4 votos, média 5.00 de 5) 


Farejando as janelas

Agora é a hora de rastrear as janelas-filhas e janelas-irmãs. Como o desktop é a janela raiz de todas as janelas e não possui janelas-irmãs, toca achar as janelas-filhas. A função GetWindow é perfeita, retornando (dou-lhe uma, dou-lhe duas...) o manipulador da primeira janela-filha. Depois a coisa fica um pouco mais elaborada e merece novamente uma função própria. Chamei-a de Scan porque ela vai "escanear" e povoar nossa árvore com dados:

void Scan(HWND hTree,HTREEITEM hNoPai,HWND Inicio) { HWND hwnd = Inicio, hwnd1; TV_INSERTSTRUCT novoItemTree; HTREEITEM htiNovoNo; char bufTxt[256],NomeClasseBuf[256],Saida[1024]; while (hwnd != NULL) { SendMessage(hwnd,WM_GETTEXT,250,(LPARAM) bufTxt); GetClassName(hwnd,NomeClasseBuf,250); wsprintf(Saida,"\"%s\" %s",bufTxt,NomeClasseBuf); memset(&novoItemTree,0,sizeof(novoItemTree)); novoItemTree.hParent = hNoPai; novoItemTree.hInsertAfter = TVI_LAST; novoItemTree.item.mask = TVIF_TEXT | TVIF_PARAM; novoItemTree.item.pszText = (LPSTR) Saida; novoItemTree.item.lParam = (LPARAM) hwnd; htiNovoNo = TreeView_InsertItem(hTree,&novoItemTree); if((hwnd1=GetWindow(hwnd,GW_CHILD))!=NULL) Scan(hTree,htiNovoNo,hwnd1); hwnd=GetWindow(hwnd,GW_HWNDNEXT); } }

Analisando o loop criado com while (hwnd != NULL), que diz "enquanto(hwnd não for NULL)", verificamos que a função Scan é chamada recursivamente enquanto existirem janelas-irmãs. Os passos são:

  1. Enviamos a mensagem WM_GETTEXT (pegue o texto) através da chamada à função SendMessage para obter o texto da janela em questão. O texto é armazenado no array de caracteres bufTxt manifestado acima.
  2. Obtemos o nome da classe da janela com GetClassName. O nome da classe é armazenado no array de caracteres NomeClasseBuf manifestado acima.
  3. Formatamos o texto da janela e o nome da classe com a função da linguagem C wsprintf e colocamos o resultado na variável Saida, também um array de caracteres manifestado acima.
  4. Limpamos a área de memória reservada para a estrutura novoItemTree, do tipo TV_INSERTSTRUCT.
  5. Atribuímos valores a determinados campos da estrutura TV_INSERTSTRUCT, da mesma forma como foi descrito para a janela do desktop.
  6. Criamos um novo nó na árvore contendo as informações da estrutura.
  7. Neste ponto, verificamos se a janela em questão possui janelas-filhas com GetWindow e GW_CHILD. Se possuir, chamamos recursivamente a função Scan para popular a árvore com esta(s) janela(s).
  8. Obtemos o manipulador da próxima janela-irmã com GetWindow e GW_HWNDNEXT. Se houver uma nova janela, o loop é repetido, caso contrário, é encerrado.

Mostrando os troféus

Salve o código fonte. Compile e execute o projeto espião. Clique em |Farejar| para mostrar o resultado da caça. Espantoso! Só que, se clicarmos algumas vezes em |Farejar|, uma porção de nós repetidos vão aparecer. É melhor dar uma conferida sad

Analisando melhor a função criaTree percebemos que sempre adicionamos nós no fim da lista mas... nunca limpamos a árvore. Taí. É preciso começar a popular uma árvore "zerada". Além disto, a árvore é redesenhada a cada novo nó adicionado. Soma-se ao trabalho desnecessário uma imagem que fica tremendo. Mas é tudo coisa pouca, fácil de corrigir (linhas 7, 8 e 17):

geshi lang="c" lines="true">int criaTree(HWND mae) { HWND Inicio = GetDesktopWindow(); HWND hTree = GetDlgItem(mae,IDJANELATREE); TV_INSERTSTRUCT itemTree; HTREEITEM hNovoNo; SendMessage(hTree,WM_SETREDRAW,0,0); TreeView_DeleteAllItems(hTree); memset(&itemTree,0,sizeof(itemTree)); itemTree.hParent = TVI_ROOT; itemTree.hInsertAfter = TVI_LAST; itemTree.item.mask = TVIF_TEXT | TVIF_PARAM; itemTree.item.pszText = "Desktop"; hNovoNo = TreeView_InsertItem(hTree,&itemTree); Inicio = GetWindow(Inicio,GW_CHILD); Scan(hTree,hNovoNo,Inicio); SendMessage(hTree,WM_SETREDRAW,1,0); return 1; }

A função SendMessage com os parâmetros WM_SETREDRAW e 0 (zero) desliga a atualização de tela, ou seja, a imagem fica "congelada". A seguir, a macro TreeView_DeleteAllItems apaga todos os nós da árvore - o usuário não percebe nada porque ele continua vendo a imagem anterior (que foi congelada). Se é assim, podemos continuar populando a árvore tranquilamente sem que a imagem seja redesenhada toda santa vez que um novo nó for adicionado smile. Nos finalmentes, ativamos novamente a atualização de tela com a mesma função SendMessage, só que com os parâmetros WM_SETREDRAW e 1.

Yeeees. Você já sabe, é salvar, compilar e executar. O resultado deve ser algo parecido com

Janelas

Observações da vó

O programa espião não é uma obra perfeitamente acabada, mas até que está legal. Mais legal ainda é ter servido de exemplo para dar uma idéia do potencial da programação com a linguagem C para o sistema operacional Windows. C é uma linguagem especialmente robusta e flexível, ideal para se programar qualquer tipo de sistema operacional. E o Linux está precisando de bons programadores...

Bão, filosofias à parte, esta seqüência de tutoriais ainda tem um para reforçar os conceitos de eventos e mensagens. Vamos colocar informações referentes às janelas "caçadas" na barra de status. Quer saber como? Vá para Linguagem C - Projeto Espião III.

Вадим Логофет Москвадля грилялобановский классрейтинг розничныхдтп за сегодня в харьковеkontur-yamal.ru полигон ооо

Informações adicionais