Página 1 de 1

Capturar tooltips

Publicado: 26 Oct 2010, 18:07
por Jonny
Hola

¿Como puedo capturar los tooltips que aparezcan en pantalla (en cualquier lugar) y de cualquier programa?.

Creo que había algo de Chefito por el foro sobre los tooltips, pero no se si valía para los que creara cualquier aplicación o sólo la que estuviéramos tratando en autoit, pues en el código que recuerdo se tocaban funciones GUI...

Quisiera comprobar si aparece un tooltip. Si es así, capturar el texto que contiene y la posición...

Salu2!

Re: Capturar tooltips

Publicado: 27 Oct 2010, 07:58
por Ximorro
Jo macho, te metes siempre en unos programas más raros...
Bueno, pues por lo que puedo ver los tooltip que salen por ejemplo en algunos iconos de la bandeja del sistema, esos que incluso pueden tener un aspa para cerrarlos, son de tipo tooltips_class32, así que esos buscando ventanas de esa clase los encuentras.

No sé si los más sencillos, esos simplemente cuadraditos que se cierran antes de poner el cursor encima son del mismo tipo. Como no puedo posicionarme encima no puedo verlos con Au3Info. Quizás con un programa que me suena había por aquí que te listaba todas las ventanas existentes puedas ver de qué tipo es.

Re: Capturar tooltips

Publicado: 27 Oct 2010, 12:33
por Jonny
Hum....

Pensé, que sería algo más sencillo... con alguna función de autoit (nativa o de UDF) o quizá con apis...

No me suena el programa que dices...
¿el código que hicísteis tú y Chefito, que mostraba la ventana seleccionada en el conmutador de ventanas (alt+tab)?

Salu2!

Re: Capturar tooltips

Publicado: 27 Oct 2010, 19:40
por Chefito
Mmmmmm......esto se ve dificil. No imposible, pero muy dificil :smt021 .
Para capturar un tooltips, una de las maneras que veo es intentar leer los mensajes adecuados que manda el windows cuando se llame a un tooltips y se haga visible. Luego vendrá el rollo de localizar de que control viene este mensaje.
Esto parece bastante complicado :smt024 .

Puede que otra forma sea ir revisando todos los controles que contengan tooltips y ver si en un momento determinado es visible :smt017 . Puede que esto sea lento y carge mucho a la cpu.

Información suplementaria:
Hay que recordar que un tooltip es un tipo de ventana con unas propiedades especiales.
Los tooltip suelen mostrarse cuando el ratón (y rara vez el foco del teclado) está encima de ese control o icono un tiempo determinado. Esto quiere decir que el ratón debe estar justo encima del control que muestra el tooltip. Puede que sea interesante saber esto para poder localizar el control antes.
No se si actuará algún mensaje del ratón, al estar ligado al tiempo que debe de estar encima del control o icono. Se podría investigar.
Existe en AutoIt una udf para el tratamiento de tooltips. Son las funciones que empiezan por _GUItooltip_...... . Puede que haya algo que puedas utilizar, como _GUIToolTip_GetText para recuperar el texto, _GUIToolTip_ToolExists, y otras que dan mucha información sobre el control y su tooltip. No he visto nada para indicar si está visible un tooltip de un control determinado, pero tengo la impresión de que debe de haber algo :smt001 .
Jonny escribió:Creo que había algo de Chefito por el foro sobre los tooltips
Sí, hice alguna cosa. Creo recordar que fue con los tooltip de los iconos de la barra de windows, pero no estoy seguro. Apenas lo recuerdo. Además, si fue así, eso es más facil, ya que sabía con que control tenía que trabajar.
Ese código no lo he encontrado en el foro. Será también otro código desaparecido? Seguro :smt010 . Lo he buscado en mi disco duro y no lo he encontrado.
Ximorro escribió:Quizás con un programa que me suena había por aquí que te listaba todas las ventanas existentes puedas ver de qué tipo es.
Sí, ese script es mío :smt016 . Lo hice cuando todo el lío del conmutador de ventanas. Por fortuna aun está en el foro :smt005 :
http://www.emesn.com/autoitforum/viewto ... f=4&t=1816

Saludos.

Re: Capturar tooltips

Publicado: 03 Nov 2010, 07:33
por Jonny
Hola

¿Los tooltips, no tienen todos la misma clase de ventana?.
Porque de ser así, podría buscarlos con WinList() (algo así como sugería Ximorro) ¿No?...

Lo de capturar los mensajes de Windows para los tooltips, también parece buena idea, pero no he encontrado nada aún sobre estos mensajes.

Salu2!

Re: Capturar tooltips

Publicado: 03 Nov 2010, 09:51
por Ximorro
Los modernos (tipo baloon, que dicen) son de tipo tooltips_class32, pero los clásicos de toda la vida me parece que son de otro tipo.
Pero bueno, haz un programa que te liste todas las ventanas (o usa el de Chefito o lo modificas) y mira a ver qué aparece cuando haya un tooltip de esos.

Re: Capturar tooltips

Publicado: 03 Nov 2010, 12:39
por Jonny
Hola

Pues algo así haré. Si solo hay dos tipos, no puede ser muy difícil buscarlos por clase de ventana...

Es que, pensé que podrían haber muchos tipos con diferentes clases y ahí sí hubiera sido más complicado.

Por cierto, está muyyy bien el programa de chefito!

Salu2!

Re: Capturar tooltips

Publicado: 17 Feb 2011, 08:11
por Jonny
Hola

Hace unos días he vuelto a meterme con esto de los tooltips, porque desde que posteé el tema no he encontrado nada.

Harto de buscar y buscar por google, se me ocurrió buscar en el foro inglés de AutoIt, pensando que algo tenía que haber, y efectivamente, encontré esto:

http://www.autoitscript.com/forum/topic ... stray-udf/

¿Conoceis esta UDF?

Parece, que es para los globos de texto esos, que se ponen en la bandeja del sistema ¿no? que creo, que no es lo mismo que un tooltip.

¿que diferencia hay entre un tooltip y los iconos esos que se ponen en la barra de herramientas?. Aunque, también he visto algo de tooltip en esa UDF mirando el código por encima. También he visto funciones para ver si el tooltip está visible, que comentaba Chefito y Ximorro, no se si será a lo que se referían y con eso valdrá. También he visto que la librería trata mensajes de Windows en algunas funciones, que comentaba Chefito.

Total, que parece que la UDF tiene todo lo que se dijo por aquí que podía hacer falta para capturar un tooltip, ¡espero que la librería sirva!.

¿Qué os parece?.

Salu2!

Re: Capturar tooltips

Publicado: 17 Feb 2011, 09:39
por Ximorro
Que yo vea esa librería no trabaja con los tooltips de los iconos de la bandeja, sino con los propios iconos. Lo único que hace es tener una función para ver el texto del tooltip de uno de esos iconos, pero no lo hace mirando el tooltip directamente, sino que está en una propiedad del icono (por ejemplo ni siquiera ve si el tooltip está visible o no, sólo ve el texto).

Eso sí que son tooltips, bastante avanzados que pueden aceptar título, aspa de cerrado, bordes redondeados, etc. Simplemente son otra clase difetente a los tooltips tradicionales. Como te comenté en su momento tendrás que capturar con Au3Info la clase de cada ventana que parezca un tooltip para gestionarlo. Como ejemplo te comprobé que estos modernos son de tipo tooltips_class32, ve mirando los demás, te sugerimos que los buscaras con algún programa que liste ventanas visibles. ¿Lo has hecho?

Re: Capturar tooltips

Publicado: 16 Mar 2011, 21:20
por Jonny
Hola

Casi tenía este tema resuelto, gracias a una UDF que casi tengo terminada.

Detecta los tooltips de tipo tooltips_class32 y obtiene datos de los tooltips mediante varias funciones, como el texto, título, tamaño, posición...

Pero falla en una cosa. Resulta, que si hacemos un script con el siguiente código:

Código: Seleccionar todo

tooltip("mostrando tooltip de prueba", 125, 95, "Tooltip de prueba", 0, 1)
Exit
Como según la ayuda de Tooltip() el tooltip se mantiene visible durante la ejecución del script, o hasta que se elimine con:

Código: Seleccionar todo

Tooltip("")
y en el código anterior el programa se cierra nada más lanzar el tooltip, parece que con WinList("[class:tooltips_class32]") no se puede capturar el tooltip ni con un timer que se ejecute cada 0 milisegundos.

Así pues, como dijo Chefito, además esto tiene que sobrecargar mucho la cpu, me he puesto a mirar como capturar los mensajes de Windows, para capturar los mensajes que tengan que ver con tooltips.

La única forma que he visto de hacer esto, es con hooks. Así pues, tirando del código de Chefito que crea ganchos de teclado y comprueba las teclas pulsadas, que hay en varios post y leyendo la documentación de SetWindowsHooksEx en la msdn, he hecho un script que crea un gancho para capturar los mensajes que Windows envía a las aplicaciones (a las ventanas, según la msdn).

No se que habrá mal, pero no funciona bien. Al cerrar el programa con Escape, aparece un error de Windows de prevención de ejecución de datos; al darle a cerrar en ese mensaje, aparece el informe de errores de rundll32.exe un montón de veces... Parece, que sí recibe bien los códigos de mensajes que se van generando, pero no termina de ir.

Pongo el código, a ver si sabeis por qué puede ser que falle:

Código: Seleccionar todo

#Include <WinAPI.au3>

Global $WMsgProcRegister
Global $HMod
Global $WMsgHook
Global $Kernel32DLL
Global $User32DLL

HotKeySet("{esc}", "Esc_Function")

$Kernel32DLL=DllOpen("Kernel32.dll")
$User32DLL=DllOpen("User32.dll")
If ($Kernel32DLL==-1 Or $User32DLL==-1) Then
Msgbox(0, "", "Error al iniciar dlls")
Exit
EndIf

If WinMessagesHooksStart()==0 Then
Msgbox(0, "", "Error al iniciar la captura de mensajes de Windows")
Exit
Else
Msgbox(0, "", "Capturando mensajes de Windows."&@CRLF&"Pulsar escape para cerrar el programa.")
EndIf

Func WinMessagesHooksStart()
MsgProcRegister=DllCallbackRegister("_WMsgProc", "long", "int;wparam;lparam")
If $WMsgProcRegister==0 Then Return 0
$HMod=DllCall($Kernel32DLL, "hwnd", "GetModuleHandle", "ptr", 0)
If (Not IsArray($HMod) Or @Error<>0) Then Return 0
$WMsgHook=DllCall($User32DLL, "hwnd", "SetWindowsHookEx", "int", $WH_CALLWNDPROC, "ptr", DllCallbackGetPtr($WMsgProcRegister), "hwnd", $HMod[0], "dword", 0)
If (Not IsArray($WMsgHook) Or @Error<>0) Then Return 0
Return 1
EndFunc

Func WinMessagesHooksQuit()
If IsArray($WMsgHook) Then
$WMsgHook=DllCall($User32DLL, "int", "UnhookWindowsHookEx", "hwnd", $WMsgHook[0])
If @Error<>0 Then Return 0
Else
Return 0
EndIf
DllCallbackFree($WMsgProcRegister)
Return 1
EndFunc

Func _WMsgProc($NCode, $WParam, $LParam)
Local $WMsgHookStruct, $Msg_Code
Local $Aditional_Param_0_Code, $Aditional_Param_1_Code
Local $Hwnd_Message
$WMsgHookStruct=DllStructCreate("lparam;wparam;uint;hwnd", $LParam)
If ($WMsgHookStruct==0 And @Error<>0) Then Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
$Aditional_Param_0_Code=DllStructGetData($WMsgHookStruct, 1)
If ($Aditional_Param_0_Code==0 And @Error<>0) Then Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
$Aditional_Param_1_Code=DllStructGetData($WMsgHookStruct, 2)
If ($Aditional_Param_1_Code==0 And @Error<>0) Then Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
$Msg_Code=DllStructGetData($WMsgHookStruct, 3)
If ($Msg_Code==0 And @Error<>0) Then Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
$Hwnd_Message=DllStructGetData($WMsgHookStruct, 4)
If ($Hwnd_Message==0 And @Error<>0) Then Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
ConsoleWrite($Msg_Code)
Return _WinAPI_CallNextHookEx($WMsgHook, $NCode, $WParam, $LParam)
EndFunc

Func Esc_Function()
WinMessagesHooksQuit()
Exit
EndFunc

While 1
Sleep(10)
Wend
De paso, a ver si sabéis decirme si es esta la forma que hay de capturar los mensajes de Windows. Con GetMessage() vi en la msdn que solo se pueden capturar mensajes en el mismo hilo que se ejecuta el programa que llama a la api, y no he visto más formas de hacerlo (deberían de capturarse los mensajes de todo el sistema) para poder capturar todos los tooltips.

Acias,

Salu2!

Re: Capturar tooltips

Publicado: 17 Mar 2011, 00:33
por Chefito
Lo que intentas hacer es bastante complicado.

Yo cuando programaba en vb6 utilizaba el spy++, un programa complemento que traía microsoft visual studio. Monitorizaba practicamente todo lo que hacía el ordenador. Entre esas cosas, los eventos de windows, ventanam, control, etc. Podías aislar eventos (solamente teclado, ratón, usuario, etc) o poner varios o todos juntos. Estaba muy bien. No se si ahora se llama spyxx o es que el archivo se llamaba así (no estoy seguro).

Lo malo es que no es gratuíto (que yo sepa), ya que va con las versiones de microsoft visual studio de pago.

Saludos.

Re: Capturar tooltips

Publicado: 17 Mar 2011, 21:50
por Jonny
Hola

Spyxx, no me suena de nada ...

Pero, en principio debería funcionar con la api setwindowshooksex ¿no?. Al menos, según la msdn, tal como lo hice en el código que puse ayer, capturaría los mensajes igual que las pulsaciones de teclado... Creo (según he entendido de la documentación de esa api), que con ese código hecho, solo faltaría conocer los mensajes que necesito y procesarlos. Los mensajes los encontré aquí:

http://msdn.microsoft.com/en-us/library ... em_defined

(están todos los). Habría que ver los relacionados con los tooltips, que he visto algo por ahí, y tratarlos... Pero no se por qué, no funciona bien el código que hice.

Este es el método que he visto en la msdn y en otras páginas que hablan de ganchos... He visto alguna otra api, como CallWindowsProc (creo que era), pero no he entendido muy bien que hace.

Por cierto, que con la UDF que estaba haciendo para tratar los tooltips, me pasa una cosa muy curiosa.

He hecho una función, para obtener el título del tooltip. Pues bien, obtengo como título, el texto que contiene el tooltip. Lo he probado de varias maneras: con WinGetTitle(), WinList(), con apis y con la UDF de tooltips que lleva el autoit y siempre obtengo el mismo resultado...

¿Se os ocurre por qué?.

Salu2!

Re: Capturar tooltips

Publicado: 18 Mar 2011, 08:17
por Jonny
Hola

Leyendo en el foro inglés, creo que he encontrado el problema del código que puse anteayer.

Lo leí en la msdn, pero como para capturar el teclado funcionaba, no le hice demasiado caso...

Resulta, que por lo visto, quitando los hooks de teclado y ratón, para el resto, el callback que recibe los mensajes que le envía Windows, debe estar en una dll. Evidentemente, yo no lo he hecho así :P...

No se si será ese el problema (diría que sí), porque he visto códigos en el foro inglés casi iguales que el mio, donde dicen que tampoco funciona.

Lo de que el callback debe estar en una dll lo he leído en al menos dos hilos del foro. Uno de ellos este:

http://www.autoitscript.com/forum/topic ... ntry539986

La pregunta entonces, es:

¿puedo hacer una dll en Vb6 por ejemplo con el callback y en vez de meterme en mucho código en la dll de alguna manera obtener lo que recibe el callback con autoit?...

Salu2!