Ir para conteúdo
Fórum Script Brasil
  • 0

Ponteiro Se Movimentando Sozinho. Como Fazer?


Paulo Nobre

Pergunta

Eu de novo!

Tenho um programa que quando é aberto pela primeira vez mostra uma messagebox dizendo que o ícone do programa está na área de notificação (ex-tray) em fim ao lado do relógio.

A messagebox está no centro com um botão ok.

Gostaria de saber como fazer para quando clicar no ok o ponteiro do mouse se movimente,obviamente sozinho, até o ícone do programa que se encontra na área de notificação, .

Alguém sabe o código para fazer isto?

Link para o comentário
Compartilhar em outros sites

Posts Recomendados

  • 0

Micheus,

Você já compilou o exemplo1.

Achei ele interessante, mais ainda pelo botão novo criado ao lado do minimizar, porém ele não aparece, quando compilo o projeto e o executo.

Clicando no espaço ao lado do minimizar onde ele deveria estar a ação é executada.

Na unit em questão o autor queria que o programa fosse para a área de notificação.

Isto acontece, porém sem o botão aparecer.

Você poderia dar uma olhada?

O projeto compila, mas aparecem as seguintes mensagens:

[Warning] Unit1.pas(204): Symbol 'AllocateHWnd' is deprecated

[Warning] Unit1.pas(238): Symbol 'DeallocateHWnd' is deprecated

[Warning] Unit1.pas(316): Variable 'bmap' might not have been initialized

[Warning] Unit1.pas(403): Return value of function 'TformBotonTitulo.GetVerInfo' might be undefined

O meu Delphi é o 7.

Link para o comentário
Compartilhar em outros sites

  • 0
Churc, esse WinDowse faz mais ou menos o que fazia o WinSight que vinha com o Delphi3?

opa Micheus, isso exatamente...

Porém o WinDowse é um pouco mais fácil de usar, assim a interface melhor... e pega mais informações também...

muito bom os exemplos Micheus valeu :D

po o cara do ajpdsoft podia ter facilitado e colocado um download do source ashusahu :P

abraçao

Link para o comentário
Compartilhar em outros sites

  • 0

Andei fazendo alguns testes com os ícones da bandeja e aparentemente no XP está funcionando:

uses CommCtrl;
var HTray,HPid,HTray_Proc:Thandle; i,iBt,xLeft,yTop:Integer; pMem:Pointer;
    rC:array[0..255] of Char; Bytes_Read:DWord; R:array[0..1] of TPoint;
begin
  HTray := FindWindow('Shell_TrayWnd', nil);
  HTray := FindWindowEx(HTray, 0, 'TrayNotifyWnd', nil);
  HTray := FindWindowEx(HTray, 0, 'SysPager', nil);
  HTray := FindWindowEx(HTray, 0, 'ToolbarWindow32', nil);
  GetWindowThreadProcessId(HTray, HPid);
  HTray_Proc := OpenProcess(Process_All_Access, false, HPid);
  pMem       := VirtualAllocEx(HTray_Proc, nil, 512, Mem_Commit, Page_ReadWrite);
  try
    iBt := SendMessage(HTray, TB_ButtonCount, 0, 0);
    for i := 0 to iBt-1 do
    begin
      FillChar(rC[0], 256, 0);
      SendMessage(HTray, TB_GetButtonText, i, LParam(pMem));
      ReadProcessMemory(HTray_Proc, pMem, @rC[0], 255, Bytes_Read);
      if not SameText('Hint do Ícone', StrPas(@rC[0])) then
        Continue;
      SendMessage(HTray, TB_GetRect, i, LParam(pMem));
      ReadProcessMemory(HTray_Proc, pMem, @R[0], SizeOf(R), Bytes_Read);
      MapWindowPoints(HTray, 0, R, 2);
      xLeft := R[0].X + (R[1].X - R[0].X) div 2;
      yTop  := R[0].Y + (R[1].Y - R[0].Y) div 2;
      SetCursorPos(xLeft, yTop);
      Break;
    end;
  finally
    VirtualFreeEx(HTray_Proc, pMem, 0, Mem_Release);
    CloseHandle(HTray_Proc);
  end;
end;

Modifique o 'Hint do Ícone' pela descrição do hint na taskbar.

Link para o comentário
Compartilhar em outros sites

  • 0
Modifique o 'Hint do Ícone' pela descrição do hint na taskbar.

Muito fera esse código. O cara é fera mesmo.

Paulo, coloque a prorpiedade hint do seu ícone para alguma coisa e faça assim->

uses CommCtrl;
Procedure MoveToTray(IconHint : String);
var HTray,HPid,HTray_Proc:Thandle; i,iBt,xLeft,yTop:Integer; pMem:Pointer;
    rC:array[0..255] of Char; Bytes_Read:DWord; R:array[0..1] of TPoint;
begin
  HTray := FindWindow('Shell_TrayWnd', nil);
  HTray := FindWindowEx(HTray, 0, 'TrayNotifyWnd', nil);
  HTray := FindWindowEx(HTray, 0, 'SysPager', nil);
  HTray := FindWindowEx(HTray, 0, 'ToolbarWindow32', nil);
  GetWindowThreadProcessId(HTray, HPid);
  HTray_Proc := OpenProcess(Process_All_Access, false, HPid);
  pMem       := VirtualAllocEx(HTray_Proc, nil, 512, Mem_Commit, Page_ReadWrite);
  try
    iBt := SendMessage(HTray, TB_ButtonCount, 0, 0);
    for i := 0 to iBt-1 do
    begin
      FillChar(rC[0], 256, 0);
      SendMessage(HTray, TB_GetButtonText, i, LParam(pMem));
      ReadProcessMemory(HTray_Proc, pMem, @rC[0], 255, Bytes_Read);
      if not SameText(IconHint, StrPas(@rC[0])) then
        Continue;
      SendMessage(HTray, TB_GetRect, i, LParam(pMem));
      ReadProcessMemory(HTray_Proc, pMem, @R[0], SizeOf(R), Bytes_Read);
      MapWindowPoints(HTray, 0, R, 2);
      xLeft := R[0].X + (R[1].X - R[0].X) div 2;
      yTop  := R[0].Y + (R[1].Y - R[0].Y) div 2;
      SetCursorPos(xLeft, yTop);
      Break;
    end;
  finally
    VirtualFreeEx(HTray_Proc, pMem, 0, Mem_Release);
    CloseHandle(HTray_Proc);
  end;
end;
Aí é só chamar
MoveToTray(TrayIcon.Hint);

Acho que é isso.

Link para o comentário
Compartilhar em outros sites

  • 0

Conclusão:

Depois que a anta aqui percebeu que o código que o Churc postou primeiro funcionava, eu fiz um projeto e mandei pro Paulo. Já estava pegando o retangulo dos ícones certinho e indo direitinho pra cima do primeiro ícone do Tray, que 99% das vezes era o Ícone do próprio programa. Agora com esse último código do s3c matou de vez. 100%.

Veja como uma pergunta tão simples como mover o mouse para cima de um ícone pode gerar uma discussão tão grande e envolver tantos conceitos como os presentes no código do s3c. Tem que alocar Handle, alocar memória, abrir processo...

Link para o comentário
Compartilhar em outros sites

  • 0

Na verdade, queria entender mais desse código.

Pelo que pude entender, você tem que ter acesso à memória do processo que controla a tray porque os retornos dos SendMessages dados ao Handle da tray vão para o processo.

Então o GetWindowThreadProcessId com o Handle da tray, retorna o PID do processo, que se você ver no task é o explorer.exe

Depois pelo OpenProcess com esse PID, você obtem o Handle do processo.

Como você não tem acesso à memória direta dele, o VirtualAllocEx se é que entendí bem, devolve um novo ponteiro de memória, mas com a caracterísitica de que tudo que é jogado na real memória fisica, é também espelhado nesse novo ponteiro.

É por isso que o retorno dos SendMessages é lido pelo ReadProcessMemory nesse ponteiro (pMem), que na verdade é feito o espelhamento do ponteiro original.

Acho que é ± isso, só queria ter certeza. Porque se alocar memória simplesmente sem ser pelo VirtualAllocEx, o ReadProcessMemory falha.

Se alguém souber mais detalhes ou erros que cometí nesse entendimento, por favor comentem.

Link para o comentário
Compartilhar em outros sites

  • 0

Eu acho que o VirtualAllocEx é para ter acesso a memória mesmo sem ter direitos de leitura ao processo, já que os dados vão ser lidos para dentro da própria memória do processo aberto. Meio difícil de entender mesmo.

Link para o comentário
Compartilhar em outros sites

  • 0

s3c, só uma pergunta: você traduziu esse código de C para Pascal? Digo aquele link que você postou tava em C, a idéia do código é a mesma?

Churc, o que aconteceu com o Joey? Tava maneiro.

Paulo Nobre, você mencionou o ícone de minimizar para o Tray que tem no link que o Micheus postou->

Achei ele interessante, mais ainda pelo botão novo criado ao lado do minimizar, porém ele não aparece, quando compilo o projeto e o executo.

Esse negócio do botão é interessante. Impressionante o windows não ter uma opção de acrescentar um botão na barra de título. Aí os programas tem que fazer gambiarra. Todo programa que tem um botão desses faz gambiarra. O que que ele faz: Ele tem que pegar o DC da janela incluindo barra de título GetWindowDC(form1.handle), pegar o tamanho dos botões da barra de título GetSystemMetrics(SM_CYSIZE), ter todos os bitmaps dos botões em cada situação e tema do windows XP(vai ver foi por isso que não apareceu, você não tem os bitmaps), desenhar o botão na posição calculada no DC obtido, ter um procedimento que receba a mensagem WM_NCHITTEST para desenhar o bitmap correspondente quando o botão está aceso, pressionado, apagado..., e também nessa mensagem processar as coordenadas do mouse para ver quando o ponteiro está em cima do botão, e verificar quando é clicado para disparar o evento correto. Além de ter que usar API's complicadas do windows para saber se se está usando o estilo XP_THEMES, e se estiver, identificar qual: azul, verde ou prateado. Só é necessário os bitmaps caso esteje usando XP_THEMES, senão usa-se a função DrawButtonFace para se desenhar um botão normal. E o efeito não fica 100% porque quando você aumenta a barra de títulos dá pra ver que se trata de um bitmap redimensionado, diferentemente do outros.

No código fonte do emule tem uma unit que faz isso, e tem os bitmaps também.

E esse link do Micheus, suporta XP_THEMES?

Pergunto isso porque se não suportar fica bem ridículo, um botão cinza normal na barra de título.

Link para o comentário
Compartilhar em outros sites

  • 0
s3c, só uma pergunta: você traduziu esse código de C para Pascal? Digo aquele link que você postou tava em C, a idéia do código é a mesma?
Sim, aquele link me deu uma luz quanto às funções VirtualAllocEx e ReadProcessMemory, daí testei os diversos parâmetros do SendMessage relativo aos botões e cheguei no TB_GetButtonText e TB_GetRect.

Link para o comentário
Compartilhar em outros sites

  • 0
E esse link do Micheus, suporta XP_THEMES?

Pergunto isso porque se não suportar fica bem ridículo, um botão cinza normal na barra de título.

Se você der uma olhada no código, verá que ele desenha o "botão" (desenha o bitmap do botão conforme o estado). Do mesmo modo como o windows faz (também utiliza bitmaps para os Themes - link). Mas, fazendo uso da API para Themes (em UxTheme), acredito que seja possível contornar este "problema".

Se você observar, ao mexer com o tamanho da barra de títulos (nas configurações de vídeo), dá para perceber que exitem apenas 4 imagens de cada ícone (ajuda, minimizar, maximizar e fechar), cada uma de um tamanho. A menor de todas utilizadas quando a altura da barra é <=20, a próxima quando é >20 e <=26, a seguinte quando é >26 e <=30 e por último, a maior, quando é >30. A partir dai, não há mais alteração - pode colocar a altura da barra em 100 que o X, por ex., ficará pequeno no meio do botão.

[]s

p.s. para quem quizer mexer nos bitmap's dos temas: Alterando a cor do botão Iniciar

Link para o comentário
Compartilhar em outros sites

  • 0

Esse link seu disse que eu não estou autorizado a ver a página. :P .

Se você observar, ao mexer com o tamanho da barra de títulos (nas configurações de vídeo), dá para perceber que exitem apenas 4 imagens de cada ícone (ajuda, minimizar, maximizar e fechar), cada uma de um tamanho. A menor de todas utilizadas quando a altura da barra é <=20, a próxima quando é >20 e <=26, a seguinte quando é >26 e <=30 e por último, a maior, quando é >30. A partir dai, não há mais alteração - pode colocar a altura da barra em 100 que o X, por ex., ficará pequeno no meio do botão.
Isso você está falando de como o componente faz ou como o windows faz? Porque se for como o windows faz: O windows desenha os botões em qaulquer tamanho utilizando linhas(você pode observar que as linhas tem sempre a mesma espessura em qualquer tamanho), e o X ou janelinha ou desenho no meio pode ter qualquer tamanho porque depende do tamanho da fonte, não é bitmap.

Eu estava pensando em escrever um coponente desses sem utilizar os bitmap, apenas desenhando com linhas e fonte, você acha que é possível?

Acho que o difícil é fazer ele acender ou apagar... Porque aí vai requerer rotinas que vão além das que estão no GDI. Talvez tivéssemos que utilizar o GDIPluss, nesse sim tem essas rotinas. Será que não existem API's pra desenhar esses botões assim como existe a função DrawBottonFace para desenhar botões normais?

Link para o comentário
Compartilhar em outros sites

  • 0
Esse link seu disse que eu não estou autorizado a ver a página. tongue.gif .
Qual deles?

Isso você está falando de como o componente faz ou como o windows faz?Porque se for como o windows faz: O windows desenha os botões em qaulquer tamanho utilizando linhas(você pode observar que as linhas tem sempre a mesma espessura em qualquer tamanho), e o X ou janelinha ou desenho no meio pode ter qualquer tamanho porque depende do tamanho da fonte, não é bitmap.
Sim, falo de como o Windows faz, pelo menos no meu XP, que era foco de seu questionamento (Themes). Faça o teste você mesmo.

Já nas outras versões do Windos as imagens dos botões realmente não são bitmaps.

Eu estava pensando em escrever um coponente desses sem utilizar os bitmap, apenas desenhando com linhas e fonte, você acha que é possível?
Sim, mas para não nos alongarmos neste assunto e desviarmos do tópico original, acho que seria mais adequado abrir um novo tópico para discutir este assunto. beleza?!

[]s

Link para o comentário
Compartilhar em outros sites

  • 0
Sim, falo de como o Windows faz, pelo menos no meu XP, que era foco de seu questionamento (Themes). Faça o teste você mesmo.

Já nas outras versões do Windos as imagens dos botões realmente não são bitmaps.

É tem razão, são bitmaps mesmo, eu é que tive a forte impressão de não serem.

Sim, mas para não nos alongarmos neste assunto e desviarmos do tópico original, acho que seria mais adequado abrir um novo tópico para discutir este assunto. beleza?!
Tudo bem. O link qua não está funcionando é o primeiro do seu penúltimo post Startbutton_blue1.gif. Interessante aquele link sobre o Resource Explorer, então acho que o meu componente tem que fazer é achar esses recursos que aí meu botão vai ficar igualzinho o do Windows, não é? Tem que estudar.

Falou.

Link para o comentário
Compartilhar em outros sites

  • 0

Thales, se você acessou o link que postei no finalzinho (p.s.), então você já viu a imagem que o link problemático mostraria (é a 1ª imagem, que tem a tela do Resource Hacker).

então acho que o meu componente tem que fazer é achar esses recursos que aí meu botão vai ficar igualzinho o do Windows, não é? Tem que estudar.
Acho que seria mais ou menos isto, também pretendo estudar esta questão.

Apenas a título de informação, já que alguns leitores podem não ter conhecimento, é possível fazer a aplicação utilizar o tema no Windows XP apenas incluindo um arquivo .res. Funciona muito bem. Link sobre como criar este arquivo (WinXP.res)

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...