Ayuda con trabajo de varias ventanas

Pregunta Sin Miedo no te cortes cualquier cosa para empezar - Autoit se comienza facilmente.Para Ordenes o Comandos sueltos. Ver nota como preguntar.
Responder
Turczyk
Mensajes: 10
Registrado: 26 Jun 2010, 04:37

Ayuda con trabajo de varias ventanas

Mensaje por Turczyk »

Hola, estuve leyendo la documentación online del Autoit y revisando las funciones para ver si conseguía algo que me oriente en como resolver mi problema pero no lo he conseguido. La idea seria la siguiente, crear una aplicación a travez de la cual al usar el hotkeyset llamar a una función y poder detenerla, lo cual es muy sencillo, el problema surge dentro de la función: La función tiene que enviar "algo" (Todavia no se que, se me ocurre que una tecla) a varias aplicaciones de Autoit para que las mismas segun lo recibido actuen de alguna manera u otra. Por si no se entiendió lo explico de una manera más ejemplificativa:
Aplicación 1: Ejecuta una función, que envia un valor a ==> Aplicación 2 y Aplicacion 3 . Para ser más preciso no se como capturar un valor con una aplicacion de Autoit y poder usarlo.
Desde ya muchas gracias.
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

Si explicaras también el objetivo del problema, y no sólo el proceso, también podríamos orientarte si se nos ocurre otra forma de solucionarlo. Como estamos un poco a ciegas es más difícil responder.

¿Cómo comunicar varios programas entre sí? Bueno, seguro que se pueden registrar mensajes de Windows pero no controlo mucho el tema y tendría que investigarlo, pero hay otras maneras de mandar mensajes...

a) Por ejemplo puedes escribir en un fichero. Los receptores lo leen de vez en cuando para ver qué ocurre. En realidad si no hay que dar diferentes mensajes, sino avisar en plan ¡YA! puede servir simplemente crear el archivo, los receptores sólo tienen que comprobar si el archivo existe, no hace falta ni leerlo.

b) También puedes cambiar algo en el estado del programa avisador, y los demás que lo comprueben, con AutoIT esas cosas se hacen muy fácilmente (por ejemplo cambiar el título de la ventana, el color de una etiqueta, activar un checkbox...

c) Otra sería al revés, que el "avisador" haga algo en las ventanas de los demás, es un poco lo que decías, puedes por ejemplo apretar botones, activarles chechboxes, etc... También puedes enviarles teclas, como tú mismo comentas, y leerlas en plan hotkey locales con GUISetAccelerators, tal como explico aquí:
http://www.emesn.com/autoitforum/viewto ... ca9c#p8259

Y habrá más maneras, todo es ir pensándolo... Qué sea aplicable depende de la naturaleza de los programas, si tienen GUI o no, de lo que tienen que estar haciendo, de la información que tiene que ir en los mensajes...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Turczyk
Mensajes: 10
Registrado: 26 Jun 2010, 04:37

Re: Ayuda con trabajo de varias ventanas

Mensaje por Turczyk »

Antes que nada muchas gracias por haberte tomado el trabajo de leer y responderme.
Ximorro escribió:Si explicaras también el objetivo del problema, y no sólo el proceso, también podríamos orientarte si se nos ocurre otra forma de solucionarlo. Como estamos un poco a ciegas es más difícil responder.

El objetivo es controlar varias aplicaciones de AutoIt atravez de una aplicación de AutoIt.
Ximorro escribió: b) También puedes cambiar algo en el estado del programa avisador, y los demás que lo comprueben, con AutoIT esas cosas se hacen muy fácilmente (por ejemplo cambiar el título de la ventana, el color de una etiqueta, activar un checkbox...
Esta opcion puede ser viable, pero lo que no se es como puedo comprobar estos cambios de estado en la aplicacion principal desde las otras aplicaciones, agradeceria si tenes informacion sobre esto para que pueda leer.
Ximorro escribió: c) Otra sería al revés, que el "avisador" haga algo en las ventanas de los demás, es un poco lo que decías, puedes por ejemplo apretar botones, activarles chechboxes, etc... También puedes enviarles teclas, como tú mismo comentas, y leerlas en plan hotkey locales con GUISetAccelerators, tal como explico aquí:
http://www.emesn.com/autoitforum/viewto ... ca9c#p8259
Ese último link que dejaste es muy interesante, por lo que estuve leyendo podría solucionar mi problema utilizando ese metodo. Voy a intentarlo y te comento como me fué. Nuevamente gracias

EDIT: Probe con lo ultimo pero no consigo que ande, aver si me podes dar una mano

Acá esta el codigo del programa que envia teclas al otro programa

Código: Seleccionar todo

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.1
 Author:         Turczyk

 Script Function:
	Not declared yet

#ce ----------------------------------------------------------------------------
#include <GUIConstantsEx.au3>
GUICreate("Manda teclast", 300, 100)
GUICtrlCreateLabel("Key", 8, 10)
$key1 = GUICtrlCreateInput("", 35, 8, 120)
GUICtrlCreateLabel("Time", 8, 44)
$time1 = GUICtrlCreateInput("", 35, 40, 120)
$startbutton = GUICtrlCreateButton("Start", 190, 8, 60)
$closebutton = GUICtrlCreateButton("Close", 190, 42, 60)


GUISetState(@SW_SHOW)

Global $Paused

HotKeySet("{F10}", "Terminate")

While 1
	$msg = GUIGetMsg()
	
	Select
		
		Case $msg = $startbutton
				
             
					ControlSend ("Soporte","","", "{F1}")
                    Sleep(1000)

            
			        Case $msg = $closebutton
					ControlSend ("Soporte","","", "{F2}")
                    Sleep(1000)
			
			
	EndSelect
		
	WEnd
	
Func Terminate()
Exit 0
EndFunc

Este es el codigo del programa receptor

Código: Seleccionar todo

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.1
 Author:         Turczyk

 Script Function:
	Not declared yet

#ce ----------------------------------------------------------------------------
#include <GUIConstantsEx.au3>
GUICreate("Soporte", 300, 100)
GUICtrlCreateLabel("Key", 8, 10)
$key1 = GUICtrlCreateInput("", 35, 8, 120)
GUICtrlCreateLabel("Time", 8, 44)
$time1 = GUICtrlCreateInput("", 35, 40, 120)
$newbutton = GUICtrlCreateButton("Nuevo", 190, 8, 60)
$seguirbutton = GUICtrlCreateButton("Seguir", 190, 42, 60)


GUISetState(@SW_SHOW)


Global $AccelKeys[1][2] = [["{F1}", $newbutton]]
GUISetAccelerators($AccelKeys)

Global $AccelKeys[1][2] = [["{F2}", $seguirbutton]]
GUISetAccelerators($AccelKeys)

Global $Paused

HotKeySet("{F12}", "Terminate")

While 1
	$msg = GUIGetMsg()
	
	Select
		
		Case $msg = $newbutton
				While 1
					iniciar() ;todavia no la hice
				WEnd
			
		Case $msg = $seguirbutton
				
				pararyseguir()
				
		Case $msg = $GUI_EVENT_CLOSE

			GUIDelete()
			ExitLoop
			
	EndSelect
		
	WEnd
	
Func Terminate()
Exit 0
EndFunc

Func pararyseguir()
$Paused = NOT $Paused
While $Paused
seguir()
sleep(100)
ToolTip('Siguiendo"',0,0)
WEnd
ToolTip("")
EndFunc
Gracias de antemano
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con trabajo de varias ventanas

Mensaje por Chefito »

Una forma muy facilona de comunicarse entre varias ventanas es con un botón oculto, con GUICtrlCreateButton y la función GUICtrlSetState($nombre_del_control_boton,$GUI_HIDE) para tenerlo oculto.
Cuando quieras pasarle algún valor, se lo pasas poniendolo en su caption (el texto del botón) con la función ControlSetText, y pulsándolo desde la otra aplicación con la función ControlClick. Pones que cuando se pulse este botón recoja el caption (el valor que le has pasado) con la función GUICtrlRead y lo tratas como quieras dentro de esta pulsación.

Muy facil.

Si lo quieres hacer algo más profesional y un poquitín más complicado, puedes utilizar un edit oculto y pasarle los valores a este edit casi del mismo modo que la forma anterior. Podrías controlar la acción de cambiar el texto cada vez que le pasases un valor gracias a la captura de mensajes que realiza wm_command. Te interesaría el mensaje $EN_CHANGE.
Si quieres ver un ejemplo de esto, mira en la ayuda la función _GUICtrlEdit_Create.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

Lo de acceder a las características de los controles de otras ventanas de programas AutoIT se hace exactamente igual que con cualquier programa Windows, para ver el título con WinGetTitle, para acceder a un control miras su "nombre Windows" con la utilidad Au3WindowInfo, obtienes su manejador con ControlGetHandle y a partir de ahí puedes leer sus características.

Bueno, en el ejemplo que pones para enviar teclas, las mandas con ControlSend, pero no pones ningún control. Eso no sé si correcto. A lo mejor resulta que lo envía al formulario pero desde luego en la ayuda no dice nada de eso, y además no pone ese parámetro como opcional.
Como comento GUISetAccelerators es como hotkeys a nivel local, tienes que activar la ventana y después haces un Send normal. Es como cuando haces F1 y te sale la ayuda de un programa, y sólo de ese, ¿por qué? pues porque es el que está activo...
GUISetAccelerators es para ese tipo de cosas.

En el cliente tienes que cambiar la forma de crear $AccelKeys, estás cargándote la asignación de F1 al poner F2, tienes que hacerlo a la vez:

Código: Seleccionar todo

Global $AccelKeys[2][2]=[["{F1}", $newbutton], ["{F2}", $seguirbutton]]
GUISetAccelerators($AccelKeys)

¿Se pueden enviar ControlClick a controles ocultos? También puedes probar esa idea de Chefito. También conviene que la ventana a la que mandes ControlClick esté activa, tal como pone en la ayuda, ¡y como mínimo que no esté oculta!. Para empezar con el botón te será más fácil que con el edittext, por la gestión más sencilla de eventos. También se pueden usar etiquetas, en AutoIt también son "clicables".
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

Curioso, estaba mirando lo de mirar características de controles de otras ventanas... y he acabado desarrollando la idea de Chefito :smt005

El caso es que no es tan directo por ejemplo leer el color de una etiqueta de otra ventana, desgraciadamente las funciones GuiCtrl... (por ejemplo GUICtrlSetColor) sólo funcionan con handlers de AutoIt generados con GuiCtrlCreate..., no para controles en otras ventanas. Para eso habrá que funcionar a base de enviar mensajes de Windows, que no es tan directo.

Para comunicar con controles en otras ventanas con funciones propias de AutoIT se usan las del grupo Control... (como ControlSetText, ControlFocus, etc, incluyendo la genérica ControlCommand, que permite enviar algunos mensajes).

Así que en vez de cambiar el color lo que he hecho es cambiar el texto de una etiqueta... pero realmente sólo faltaba hacerle click para que desarrollar la idea de Chefito, y eso es lo que he hecho. Como había empezado con una etiqueta pues así se ha quedado, pero por supuesto también se puede hacer con un botón.

He comprobado que funciona perfectamente con el receptor desactivado, incluso minimizado, y con el control oculto, o sea, perfecto. En el ejemplo comento lo de ocultar el control para que se vea cómo cambia el mensaje en el GUI, pero puedes probarlo oculto para ver que no hace falta:

Este es el programa que recibe los mensajes:

Código: Seleccionar todo

#include <GUIConstantsEx.au3>

Global $miGUI, $lblMensaje
$miGUI = GuiCreate("Mi GUI Receptor", 220, 100, -1, 100)
$lblMensaje = GUICtrlCreateLabel("Sin mensaje.", 20, 30, 200, 27)
GUICtrlSetFont(-1, 12)
;GUICtrlSetState(-1, $GUI_HIDE) ;Descomentar esta línea para ocultar el texto del mensaje, igual funciona
GUISetState(@SW_SHOW)
While 1
	Switch GUIGetMsg()
		Case $lblMensaje
			MsgBox(0, "Mi GUI RECEPTOR", "¡Me han enviado este mensaje! -> " & GuiCtrlRead($lblMensaje))
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd
Este es un programa que envía un mensaje, ¡es bien sencillo!:

Código: Seleccionar todo

Global $tit = "Mi GUI Receptor", $msgControl = "Static1" ;"Static1" lo he averiguado con Au3Info
ControlSetText($tit, "", $msgControl, "¡ADELANTE!")
ControlClick($tit, "", $msgControl)
Espero que sirva de ayuda :smt002
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Turczyk
Mensajes: 10
Registrado: 26 Jun 2010, 04:37

Re: Ayuda con trabajo de varias ventanas

Mensaje por Turczyk »

Gracias a ambos por responder, he probado lo último que pusiste Ximorro y como bien dices anda perfecto, es precisamente lo que estoy buscando pero ahora me he encontrado con otro problema.

Me gustaría poder usar el texto que cambia en el label para poder compararlo con una string y en base a eso elegir que hacer se me ocurrió algo como esto :

Código: Seleccionar todo

 if GuiCtrlRead($lblMensaje)) = "ADELANTE!" then
   MsgBox(0, "Mi GUI RECEPTOR", "hola")
 else
   MsgBox(0, "Mi GUI RECEPTOR", "chau")
endif
Pero no anda : <

Otra cuestión, probé de enviar pero a 2 aplicaciones diferentes de esta manera:

Código: Seleccionar todo

 Global $tit = "Soporte1", $msgControl = "Static1" ;"Static1" lo he averiguado con Au3Info
ControlSetText($tit, "", $msgControl, "¡ADELANTE!")
ControlClick($tit, "", $msgControl)

Global $tit2 = "Soporte2", $msgControl = "Static1" ;"Static1" lo he averiguado con Au3Info
ControlSetText($tit2, "", $msgControl, "no")
ControlClick($tit2, "", $msgControl)
Para Soporte1 anda bien, es decir siempre recibe solamente el mensaje destinado a Soporte1
Pero para Soporte2 no anda bien, a veces recibe los 2 mensajes, es decir el "¡ADELANTE!" y el "no" .
Si Soporte1 está cerrada Soporte 2 recibe siempre los 2 mensajes.
Si ambas aplicaciones están minimizadas cada una recibe como corresponde su mensaje

Tengo que cambiar algo más aparte del nombre de la GUI en cada uno de los programas? Es decir yo lo único que hice en cada programa fué cambiar el nombre las GUI y algo del mensaje para identificar de que programa provenian:

Programa1:

Código: Seleccionar todo

$miGUI = GuiCreate("Soporte1", 220, 100, -1, 100)
MsgBox(0, "Mi GUI RECEPTOR", "¡Me han enviado este mensaje! -> " & GuiCtrlRead($lblMensaje))
Programa2:

Código: Seleccionar todo

$miGUI = GuiCreate("Soporte2", 220, 100, -1, 100)
MsgBox(0, "Mi GUI RECEPTOR", "¡y a mi este -> " & GuiCtrlRead($lblMensaje))
Otra cosa, que es el "Static1"? no lo encontré en la documentación online = /

Perdón si tardo en responder pasa que es un lenguaje nuevo para mi, gracias nuevamente por tomarse el tiempo de leer y ayudarme realmente lo aprecio. Un saludo
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

¿Cómo que no anda la comparación de cadenas? ¿Realmente has probado ese código? Lo digo porque no compila, en la primera línea te sobra un paréntesis.
Además no estás comparando la cadena que yo envío, yo ponía los dos signos de admiración y tú sólo uno, así que cuando compile tal como está ahora te saldrá "chau"...

Y sí, puedes hacerlo así, con cadenas If Then ElseIf..., también puedes usar Switch, si son muchas cadenas quizás sea esto último más cómodo.
También puedes meter todas las cadenas a comprobar en un Array y luego ir mirándolas con bucle, de esta manera aún es más fácil meter nuevas cadenas, sólo habrá que añadirlas al Array y el código que comprueba las cadenas no cambia.

En el segundo ejemplo no redefinas las variables, pon Global sólo la primera vez que aparecen las variables, después debes modificar las originales, no crear nuevas, supongo que se está liando porque supuestamente tienes dos variables diferentes con el mismo nombre...
Bueno al principio no había visto que la segunda era $tit2, de todas maneras no vuelvas a poner $msgControl, especialmente si vale lo mismo.
Puedes reutilizar las variables si les cambias el valor, pero como te digo en ese caso no vuelvas a poner el Global.
Es un comportamiento un poco extraño, habrá que mirarlo con más detenimiento. ¿Los receptores son dos programas diferentes o has creado dos GUI en el mismo programa? Tal como lo comentas entiendo que son dos programas cada uno compilado a su EXE (que es lo que tiene que ser), pero por asegurarnos.


Efectivamente, sólo cambiando el título del GUI tiene que reconocerlas independientemente, mira a ver si es lo de las globales y si no es eso seguiremos investigando...

Lo de Static1 es el nombre interno de Windows para ese control, no nos sirve $lblMensaje porque eso es algo sólo reconocido en su propio programa.
Para averiguarlo tenemos la inestimable ayuda de una herramienta genial que ha creado el equipo de AutoIT y distribuye con el mismo. Desde el editor Scite se ejecuta desde el menú Tools->AU3Info (o con las teclas CTRL+F6).
Desde la instalación busca el archivo Au3Info.exe en la carpeta base de la instalación (yo por ejemplo lo tengo en C:\Archivos de programa\AutoIt3
En esa ventana te da los datos de lo que tengas bajo el ratón, como título y clase de la ventana en la que estás (primer grupo Basic Window Info) o la clase e instancia del control (que es lo que aquí nos hace falta) en el segundo grupo Basic Control Info, y abajo hay pestañas con mogollón de detalles. Si te pones sobre la etiqueta ves que la clase es Static y Instance vale 1. Así que para acceder a ese control se usa en AutoIt:
"[CLASS:Static; INSTANCE:1]", como esto se usa mucho también se puede comprimir como
"[CLASSNN:Static1]", y por lo visto les parecía poco y tambies es equivalente simplemente
"Static1", así que es lo que he usado, aunque el primero es el más aclaratorio, éste es el más simple.

Por cierto, en la pestaña Control de Au3Info tienes todas esas maneras en los primeros datos: Class, Instance, ClassNameNN y Advanced (Class)
En tu "Soporte2" has tenido suerte de que se llamara así ;-), bueno la clase es necesariamente Static (una etiqueta) pero la instancia podría haber cambiado...

No pasa nada si tardas en responder si es porque estás probando cosas ¡eso es lo que esperamos que hagas!
Tampoco esperes que respondamos siempre enseguida, ya sabes que esto lo hacemos por amor al arte.

Ale espero que te sirva el rollo que te he puesto.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

Es raro eso que dices que con dos receptores se lía, lo estoy probando y va a las mil maravillas.
La única manera que he conseguido que se líe es llamando a uno "Soporte" y al otro "Soporte2" (el primero no tiene numerito).

Lo que ocurre es que por defecto AutoIT busca títulos de ventana QUE EMPIEZAN por lo que le dices, no busca la cadena exacta, así que en ese caso "Soporte2" también es encontrada cuando buscas "Soporte". Si sólo esta segunda está abierta recibe los dos mensajes, si están las dos abiertas a veces va bien y a veces no.

Así que ten cuidado con los nombres, aunque tal como lo has puesto, cada uno con su numerito, no debe liarse, y de hecho yo no he conseguido que se líe...

Lo de que busque el principio del título se pueden cambiar con la opción WinTitleMatchMode
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Turczyk
Mensajes: 10
Registrado: 26 Jun 2010, 04:37

Re: Ayuda con trabajo de varias ventanas

Mensaje por Turczyk »

Ximorro gracias nuevamente por responder, ya conseguí hacer que funcione. Paso a responderte así de paso te sirve para comprobar tus conocimientos

Respecto a lo de los receptores es como bien dices busca la coincidencia de la cadena, es decir si pongo Soporte en el nombre de la ventana a enviar, y tengo otra ventana con Soporte2 esta podria también recibir el mensaje dependiendo de la existencia de Soporte pero si le pones que envie a Soporte1 no hay problema. Así que estabas totalmente en lo cierto.

Respecto a lo de la comparación y el string, era por que tenía un parentesis de más como bien dices, se me ha pasado por apurado quizas :smt017 haha.

Lo de la Global te refieres a que ponga algo así no?

Código: Seleccionar todo

Global $tit = "Soporte 1", $msgControl = "Static1" , $tit2 = "Soporte2"
Bueno muchisimas gracias a ambos por responder me ha sido de valiosisima ayuda, con gente tan servicial da más gusto aprender. Un saludo y que anden muy bien.
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con trabajo de varias ventanas

Mensaje por Ximorro »

Ah, que esto es "para que compruebe mis conocimientos". No, si yo no tenía dudas, pero gracias... :smt005

Lo de Global puedes hacerlo así en una línea, pero lo importante que te decía es que no pongas
Global $msgControl = "Static1"
dos veces.
El primer Global lo puedes dejar como está, del segundo hay que quitar esa variable.
Para empezar no le cambias el valor, así que no hay que volver a asignarle nada, pero si le cambiaras el valor, tampoco debes ponerle el Global, pues eso sólo es para cuando se declara la variable por primera vez, cambiando el valor se haría:

Código: Seleccionar todo

Global $tit = "Soporte1", $msgControl = "Static1"
[lo del medio]
Global $tit2 = "Soporte2"
$msgControl = "Static2"
Y sí, tampoco es mala idea declarar todas las variables juntas al principio del programa, es cosa de gustos, yo normalmente las pongo al principio (no todas en una línea, sino agrupadas según su uso) así les sigo mejor el rastro. Pero como digo es cosa de gustos, lo importante es que el código no quede difícil de leer, que cuando vuelves a él 3 meses después no lo entiende ni el que lo ha escrito ;-)
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Turczyk
Mensajes: 10
Registrado: 26 Jun 2010, 04:37

Re: Ayuda con trabajo de varias ventanas

Mensaje por Turczyk »

Si es verdad eso que concierne a la lectura cuando hay que reveer el codigo es mucho más comodo, igualmente por ahora como soy bastante nuevo comento bastante para irme familiarizando :smt003
Responder