Página 2 de 3

Re: Ayuda con Winlist()

Publicado: 23 Sep 2009, 08:54
por Ximorro
Me refería a ayudarse con el programa de Chefito que te dice las ventanas que tienes abiertas con el mismo orden que lo dice la ventana alt+tab.

Si tienes ese orden, la cosa es mirarlo cada vez que se activa ALT+TAB (ahí ya ves la primera seleccionada) y luego ir pasando a la siguiente cada vez que se pulsa TAB mientras no se suelte ALT. Cuando se suelta ALT la última ventana seleccionada es a la que va a pasar.

La próxima vez que se active ALT+TAB el orden de las ventanas efectivamente habrá cambiado, pero la cosa es invocar cada vez que eso ocurre la rutina de Chefito que te da el nuevo orden, y ya está :smt003

Ahora "sólo" te hace falta el programa de Chefito, no sé de dónde saca esa información... ¿está en el registro?

Re: Ayuda con Winlist()

Publicado: 23 Sep 2009, 13:00
por Chefito
Nas gente. Olvidar todo lo anterior :smt005 :smt005 . Todos los códigos que hemos puesto para hacer esto generan fallos (algunos más graves que otros) y acaban desorganizando la selección de las ventanas.
El código que puse para recuperar el nombre de los botones que se encuentran en la barra de tareas también falla. Fallaba al intentar secuperar los nombres de las ventanas agrupadas. Pero eso lo solucioné. Pero como siempre, de pura casualidad ví otro fallo, y era que no reconocía dos o más ventanas llamadas de la misma forma. Solo me ponía una.
Al ver todo esto, me cansé de este método y cambié el rumbo del código. Tengo hecho ya dos códigos, uno te muestra junto a la ventana alt+tab una ventana mía, la cual te dice el título de la ventana que señalas con el tab y te muestra su icono. El otro código es igual que el anterior pero no te muestra la ventana de win alt+tab, la bloquea.
Ayer creía que lo había conseguido, pero ...... como no! se me presentó otro problema por casualidad!!!. Resulta que cuando tienes una o varias ventanas con la propiedad topmost, la cual le dice a una ventana que se quede siempre visible (la primera en el orden Z, que es el orden que sigue la ventana de win alt+tab, la cual vamos a llamar WinSwitch o WinSwitcher) pues las pone siempre al principio y se las salta si seleccionas otra que no tenga esta propiedad.
Por ejemplo, si tenemos una ventana con esta propiedad y tenemos una ventana activa que no sea esta, al darle al alt+tab no pasaría a la segunda, sino que pasaría a seleccionar el icono de la 3º ventana :smt024 :smt024 :smt024 :smt024 .
Pero no contentos con esto, tenemos que programar otra condición. Y es que si se selecciona una ventana con la propiedad topmost, pues no se salta las demás con esta propiedad.....vamos......que pasa a la siguiente como lo haría normalmente :smt024 :smt024 :smt024 :smt021 :smt021 .
Y lo malo de todo esto, es que el método que utilizo, al mantener pulsadas las teclas, pues lee continuamente el código, y esto muchas veces es malo si quieres que varias condiciones se cumplan solamente una vez en determinados casos :smt024 :smt024 . Por eso estoy poniendo un motón de variables auxiliares para evitar esta situación y me estoy mareando, porque no logro hacer que funcione totalmente bien (por ahora :smt003 ).
Lo que he conseguido por ahora, es que en el que se muestra la ventana WinSwitch junto a la mía, que vaya bien si no hay ventanas topmost; y con el código que te bloquea dicha ventana, he conseguido que vaya bien estando una sola ventana de este tipo. Si hay más, se fastidia la cosa. Aquí estoy más cerca. Lo que pasa que los ojos ya me hacen chirivitas y el coco está sobrecalentado :smt001 .
Si en unos días no encuentro una buena solución cuelgo el código a ver si alguien consigue algo más que yo.....aunque aviso que es un poco caótico y no es muy facil entenderlo.
Paciencia :smt023 .

Saludos.

Re: Ayuda con Winlist()

Publicado: 23 Sep 2009, 16:18
por Jonny
Hola

¡Puffff!. Si que tiene que ser complicado ... Para resistírsele a Chefito jejeje.
Bueno, otra cosa que aprendí. No conocía esa propiedad de las ventanas.
Esperaremos a ver si se puede conseguir.

Salu2!

Detector del conmutador de tareas (WinSwitch)

Publicado: 24 Sep 2009, 20:46
por Chefito
Nas....bueno bueno. Parece que ya he conseguido algo medio decente. Ayer solucioné el tema de las ventanas con la propiedad topmost :smt023 . Al final era que me faltaba una simple condición con una variable auxiliar jajajaja :smt005 . Como dije el otro día, estaba ya mareado, y cuando descansé e hice otras cosas, me puse y lo ví :smt024 .
Parece que lo que es el título de la ventana te lo indica perfectamente (seguro que alguien encuentra algún fallo de esos extraños :smt005 ).
Este es el código donde además de mi ventana se ve la ventana de win alt+tab. He puesto la ventana del script con la propiedad topmost para que siempre esté arriba y podais ver que efectivamente la ventana que se selecciona con el tab corresponde a la que indica mi script.
Pero, pero, pero..........casi siempre hay un pero :smt005 ........he visto el tema de los iconos y no he podido hacerlo del todo bien. Parece increible pero no lo he conseguido (por lo menos de la forma que yo quería :smt009 ). Se ven los iconos que están enlazados a los archivos, no a las ventanas, y éstos no se corresponden siempre con el de las ventanas. Incluso a veces nisiquiera muestra un icono.
He estado investigando (sobretodo en el foro de habla inglesa), y lo máximo que he conseguido es sacar el icono de la ventana en tamaño pequeño (16x16). Cuando lo he aumentado a 32x32 se ha visto mal (los pixeles muy grandes).
Por lo que he visto, según parece se pueden sacar los iconos grandes, pero he probado de todo y no he podido :smt021 .
Si ha alguien le interesa investigar este tema le voy a guiar un poquito:
http://www.autoitscript.com/forum/index ... ntry303365 , este ejemplo está chulo. Es una pena que lo encontrase cuando ya tenía casi todo el código hecho.
Buscar cosas como: WM_GETICON, Sendmessage, WM_SETICON.
Os dejo el script: (CÓDIGO EDITADO. FALLABA CON VENTANAS QUE NO TENÍAN TÍTULOS)

Código: Seleccionar todo

#include <GUIConstantsEx.au3>

#Include <WinAPI.au3>

#include<Constants.au3>

#include <WindowsConstants.au3>

Global $codigo=0,$numWin,$ProgramManager,$hwnd,$EmpezarSegundo,$auxOnTop

$ProgramManager=WinGetHandle("Program Manager")

Global $dll = DllOpen("user32.dll")

Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")

Global $hmod = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)

Global $hHook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_KEYBOARD_LL, "ptr", DllCallbackGetPtr($hStub_KeyProc), "hwnd", $hmod[0], "dword", 0)

Global $gui=GUICreate("My GUI Button",400,100,10,10,-1,$WS_EX_TOPMOST)

Global $label=GUICtrlCreateLabel("",10,60,380,30)

Global $icon = GUICtrlCreateIcon("", 0, 40, 10)     ;necesario que haya al menos un control antes que él, sino no aparece (no refresca bien).



GUISetState()

While 1

   Sleep(10)

        $msg = GUIGetMsg()

        Select

            Case $msg = $GUI_EVENT_CLOSE

                ExitLoop

        EndSelect

WEnd

Func _KeyProc($nCode, $wParam, $lParam)

        If $wparam=260 Then     ;entra al pulsar la tecla alt.

            $KEYHOOKSTRUCT = DllStructCreate("dword;dword;dword;dword;ptr", $lParam)

            $codigo=DllStructGetData($KEYHOOKSTRUCT, 1)

                If Not(WinExists("[CLASS:#32771]")) Then

                    $numWin=1   ;un contador que te indica el número de la ventana señalada.

                    ;con esto comprobamos al principio si la ventana activa es topmost o no para seleccionar la buena.

                    If _WinIsOnTop(WinGetHandle("[active]")) Then

                        $auxOnTop=False

                    Else

                        $auxOnTop=True

                    EndIf

                    $hwnd=_WinAPI_GetWindow($ProgramManager,$GW_HWNDFIRST)  ;cogo el handle de la primera ventana a partir de la "Program Manager"

                    $EmpezarSegundo=False   ;Con esta variable hago que se salte la primera ventana buena que encuentra y que señale la 2º.

                EndIf

            If $codigo=9 Then   ;entra al pulsar la tecla tab.

                While 1

                    $tituloWin=_WinAPI_GetWindowText($hWnd)     ;capturo el título de la ventana.

                    ;pongo todas estas condiciones para encontrar las ventanas válidas. Digo que el título no puede ser vacio, que la ventana tiene

                    ;que ser visible, que tiene que tener un handle, y que tiene que tener alguna médida.

                    ;condiciones alternativas válidas:

                    ;bitand(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE),$WS_CAPTION)=$ws_caption

                    ;bitand(_WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE),$WS_EX_TOOLWINDOW)<>$WS_EX_TOOLWINDOW And _WinAPI_GetWindowHeight($hwnd)>0 And _WinAPI_GetWindowWidth($hwnd)>0

                    If _WinAPI_IsWindowVisible($hwnd) And $hwnd<>0 Then

                        If bitand(_WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE),$WS_EX_TOOLWINDOW)<>$WS_EX_TOOLWINDOW Then

                            $WinOnTop=_WinIsOnTop($hwnd)

                            If $WinOnTop And $auxOnTop Then

                                $numWin+=1

                                $hwnd=_WinAPI_GetWindow($hwnd,$GW_HWNDNEXT)

                            Else

                                $auxOnTop=False

                                If $EmpezarSegundo Then

                                        $numWin+=1

                                        ;ConsoleWrite($numWin&" - "&$tituloWin&@CR)

                                        $hwndanterior=$hwnd

                                        GUICtrlSetData($label,$numWin&" - "&$tituloWin)

                                        $proceso=WinGetProcess($hwnd)   ;averiguo el proceso de la ventana.

                                        $pathfile=_WinAPI_GetModuleFileNameEx($proceso)     ;con el proceso, averiguo el camino completo más el nombre del archivo del programa que ha cargado la ventana.

                                        GUICtrlSetImage($icon,$pathfile,0)      ;inserto la imagen del icono del programa.

                                        $hwnd=_WinAPI_GetWindow($hwnd,$GW_HWNDNEXT)     ;doy el handle de la siguiente ventana.

                                        ExitLoop

                                Else

                                    $EmpezarSegundo=True

                                    $hwnd=_WinAPI_GetWindow($hwnd,$GW_HWNDNEXT)

                                EndIf

                            EndIf

                        ElseIf $hwnd=$ProgramManager Then

                                $numWin=0

                                $hwnd=_WinAPI_GetWindow($ProgramManager,$GW_HWNDFIRST)

                            Else

                                $hwnd=_WinAPI_GetWindow($hwnd,$GW_HWNDNEXT)

                        EndIf

                    Else

                        $hwnd=_WinAPI_GetWindow($hwnd,$GW_HWNDNEXT)

                    EndIf

                WEnd

            EndIf

        EndIf

    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)

EndFunc  ;==>_KeyProc

Func OnAutoItExit()

    DllClose($dll)

    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hHook[0])

    DllCallbackFree($hStub_KeyProc)

EndFunc  ;==>OnAutoItExitm



; #FUNCTION# ====================================================================================================================

; Name...........: _WinAPI_GetModuleFileNameEx

; Description....: Retrieves the fully-qualified path for the file associated with the process.

; Syntax.........: _WinAPI_GetModuleFileNameEx ( [$PID] )

; Parameters.....: $PID    - The PID of the process. Default (0) is the current process.

; Return values..: Success - The fully-qualified path to the file.

;                  Failure - Empty string and sets the @error flag to non-zero.

; Author.........: Yashied

; Modified.......:

; Remarks........: None

; Related........:

; Link...........: @@MsdnLink@@ GetModuleFileNameEx

; Example........: Yes

; ===============================================================================================================================



Func _WinAPI_GetModuleFileNameEx($PID = 0)

    If $PID = 0 Then

        $PID = _WinAPI_GetCurrentProcessID()

    EndIf

    Local $hProc = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'dword', 0x00000410, 'int', 0, 'dword', $PID)

    If (@error) Or ($hProc[0] = 0) Then

        Return SetError(1, 0, '')

    EndIf

    $hProc = $hProc[0]

    Local $tPath = DllStructCreate('wchar[1024]')

    Local $Ret = DllCall('psapi.dll', 'int', 'GetModuleFileNameExW', 'ptr', $hProc, 'ptr', 0, 'ptr', DllStructGetPtr($tPath), 'int', 1024)

    If (@error) Or ($Ret[0] = 0) Then

        $Ret = 0

    EndIf

    _WinAPI_FreeHandle($hProc)

    If Not IsArray($Ret) Then

        Return SetError(1, 0, '')

    EndIf

    Return SetError(0, 0, DllStructGetData($tPath, 1))

EndFunc   ;==>_WinAPI_GetModuleFileNameEx



; #FUNCTION# ====================================================================================================================

; Name...........: _WinAPI_FreeHandle

; Description....: Closes an open object handle.

; Syntax.........: _WinAPI_FreeHandle ( $hObject )

; Parameters.....: $hObject - Handle to an open object.

; Return values..: Success  - 1.

;                  Failure  - 0 and sets the @error flag to non-zero.

; Author.........: Yashied

; Modified.......:

; Remarks........: The _WinAPI_FreeHandle() function closes handles to the following objects:

;

;                  Access token

;                  Communications device

;                  Console input

;                  Console screen buffer

;                  Event

;                  File

;                  File mapping

;                  I/O completion port

;                  Job

;                  Mailslot

;                  Memory resource notification

;                  Mutex

;                  Named pipe

;                  Pipe

;                  Process

;                  Semaphore

;                  Thread

;                  Transaction

;                  Waitable timer

;

; Related........:

; Link...........: @@MsdnLink@@ CloseHandle

; Example........: Yes

; ===============================================================================================================================



Func _WinAPI_FreeHandle($hObject)

    Local $Ret = DllCall('kernel32.dll', 'int', 'CloseHandle', 'ptr', $hObject)

    If (@error) Or ($Ret[0] = 0) Then

        Return SetError(1, 0, 0)

    EndIf

    Return 1

EndFunc   ;==>_WinAPI_FreeHandle



;===============================================================================

;

; Function Name:   _WinIsOnTop

; Description::    Gets the OnTop State of a window

; Parameter(s):    $WindowHandle : Handle or Title of Window

; Requirement(s):  WinAPI.au3

; Return Value(s): Window OnTop: True, otherwise False

; Author(s):       Prog@ndy

;

;===============================================================================

;

Func _WinIsOnTop($WindowHandle)

    Local $long = DllCall("User32.dll", "int", "GetWindowLong", "hwnd", WinGetHandle($WindowHandle), "int", -20)

    Return BitAND($long[0],8)=8 ; $WS_EX_TOPMOST = 8

EndFunc

 
Y nada......a calentarse la cabeza con apis que a lo mejor conseguis más que yo. Yo ya estoy cansado de este tema. Me ha costado bastante.
A ver si me quedan ganas de solucionar el mismo script que además bloquea la ventana alt+tab. La verdad, pocas me quedan....jajajajaja :smt016 .

Saludos.

Re: Ayuda con Winlist()

Publicado: 25 Sep 2009, 06:58
por Jonny
Hola

¡IMPRESIONANTE!

Como dige, no necesito mostrar el icono de la aplicación seleccionada (en cualquier caso está bien tener el como hacerlo), por lo que ´para mí no supone ningún problema.

Un par de curiosidades
¿Es necesario capturar el alt y el tabulador con esas apis, o podría (supongo que sí) hacerse con _IsPressed y/o la api getkeystate?

Dices en alguna parte del código, que es necesario que la ventana tenga título y tamaño.
Si Un programa hiciera algo como:

Código: Seleccionar todo


MsgBox(0, "", "Hola mundo")

 
¿No sería detectada por éste script?

Gracias,
¡BUEN TRABAJO!

Salu2!

Re: Ayuda con Winlist()

Publicado: 25 Sep 2009, 17:33
por Chefito
Jonny escribió:¿Es necesario capturar el alt y el tabulador con esas apis, o podría (supongo que sí) hacerse con _IsPressed y/o la api getkeystate?
Preferiblemente sí, por varias razones.
_IsPressed no se debería utilizar porque ejecutaría muchas veces el bucles. Puede que se pudiese hacer, pero seguro que es complicado.
Ventajas de mi script: ejecuta el script solamente cuando debe ejecutarlos, al pulsar primero alt y luego tab, que es cuando aparece la ventana de win. Con _IsPressed aparecería siempre, pulsando alt o tab primero.
También piensa que mi script no depende del bucle while, detecta las pulsaciones independientemente. En cambio _IsPressed en un principio sí.
No veo lógico utilizar _IsPressed, daría muchos problemas. Por eso dije que os olvidaseis de los códigos anteriores.
Jonny escribió:¿No sería detectada por éste script?
Acabas de descubrir un fallo gordo del script :smt005 . Por culpa de esta situación no creo que sirva este script, ya que veo dificil solucionar este fallo. Quien sabe, a lo mejor se puede sustituir estas condiciones por otras o que se yo, pero por ahora no se me ocurre ninguna. Y al quitar la condición de que no vea las ventanas que no tengan títulos, se cuelan algunas que no deberían verse :smt021 .
Aunque ya teniendo todo este código, podeis intentar vosotros algo a ver si encontrais alguna otra solución mejor, o alguna condición mejor para que detecte las ventanas.
Y no, no lo vería, cosa que no debería ocurrir, ya que descuarinja todo el orden de ventanas.
Puede que la solución fuese la de los botones de la barra de tareas. Quien sabe. Si tengo ganas intento acabar el de los botones.

Saludos.

Detector del conmutador de tareas (WinSwitch)

Publicado: 26 Sep 2009, 03:10
por Chefito
Bueno bueno....me fastidiaba que un código que me ha costado tanto en hacerlo no funcionase del todo bien, asique le he pegado un repaso y he intentado buscar otra solución (EL CÓDIGO ES EL QUE ESTÁ DOS POST MÁS ARRIBA).
He estado mirando las propiedades de las ventanas y parece que he podido filtrar las que me interesaban con la propiedad $WS_EX_TOOLWINDOW. Como siempre al poner esto apareció un nuevo problema (comooooo noooooo :smt021 ), y era que también filtraba la ventana final que utilizo para volver a empezar el recorrido (Program Manager). Pero por fortuna para esto hay varias soluciones. Varié un poco el código y ya está solucionado (espero :smt005 ). Ahora también detecta las ventanas sin títulos.
He quitado las condiciones de filtro de ventanas sin título (que era la que daba problemas) y también las de las medidas de la ventana mayor que 0 (con la nueva condición parece ser que no hacen falta, ya las filtra ella).

Espero que el asunto se acabe aquí, porque si no me pego un tiro :smt021 (o se lo pego a Jonny mejor :smt005 :smt005 ).
No, en serio, probarlo y si encontrais algún otro problema, decirmelo que lo intentaré solucionar.

Saludos :smt026 .

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 08:18
por Ximorro
Impresionante documento, de aquí podremos aprender mucho, si es que somos capaces de entenderlo ;-)

Creo que con IsPressed sí se podría hacer, haces un bucle que espere ALT y cuando lo detecte haces otro que espere ALT+TAB. De todas maneras ya lo tienes hecho, aunque la verdad es que no lo entiendo mucho, parece que KeyProc te da unas teclas en wparam y otras en lparam, ¿cómo funciona eso?

Por cierto, me parece que las ventanas que no saca ALT+TAB son las que tienen como estilo extendido $WS_EX_TOOLWINDOW. Esas seguro que no las saca (ver la explicación de ese flag en la ayuda de GUICreate). A lo mejor mirando sólo ese flag para ver qué ventanas sacar o cuáles no...
Creo que sí lo miras pero está comentado, ¿es algo que has descartado luego?

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 15:19
por Chefito
Ximorro escribió:Impresionante documento, de aquí podremos aprender mucho, si es que somos capaces de entenderlo
Jejejeje....gracias :smt002 . Tranquilo, que si os fijais bien, más o menos se puede entender todo, o por lo menos saber que hace. Os podeís liar un poco con lo que es todas las condiciones que hay dentro de la función _KeyProc para la captura del alt+tab. Me lio hasta yo!!!! Y porque lo he hecho yo que si no..... :smt005 .
Si no entendeis algo no dudeis en preguntar, que si está en mi mano os lo intentaré explicar.
Ximorro escribió:Creo que con IsPressed sí se podría hacer, haces un bucle que espere ALT y cuando lo detecte haces otro que espere ALT+TAB.
Tienes razón, ahí me canteé un poco (fallo técnico :smt003 ). Sí se puede hacer que detecte solamente el alt+ tab con dos condiciones. Lo siento....cosas del directo jajajaja. Pero como ya os comenté, el _ispressed es síncrono (ya que utiliza una api síncrona), y esto hace que se tenga que meter en el bucle while principal, con las consiguientes consecuencias si se para este bucle o se producen retrasos; o hacer alguna triquiñuela con algún timer asíncrono o alguna otra cosa (dolores de cabeza jajajaja). Al actuar así, tiene el gran problema de que cuando pulsas, se suele ejecutar el código de dentro a mucha más velocidad de los teclazos que realmente estás dando.
Por ejemplo: haz tu mismo la prueba con alguna condición de una tecla utilizando _ispressed y mete dentro de esta condición un consolewrite con un contador. Verás que cuando tu pulsas una vez (una pulsación), se te va a disparar el contador. No te quiero ni contrar como se dispara este contador si dejas pulsada la tecla :smt005 . Este método daría muchisimas más pulsaciones que las que realmente das (según el tamaño del código, pausas, potencia del micro, etc que tengas en el bucle while). En este caso esto no interesa. Se podría solucionar? Puede que sí, pero tendrías que tirar de muchisimo más código y más dolores de cabeza :smt021 . Igualmente, si ves que lo puedes hacer, te animo a que lo intentes y lo cuelges.

Nos interesa que capture solamente el número real de teclas pulsadas. Y esto lo hace el código que puse, y encima de forma asíncrona! :smt003 .
Además, te cuento otro secretillo :smt005 :smt005 . Este método hace un hook (gancho) al teclado. Para que nos entendamos, cuando el win manda las pulsaciónes, este código recibe y puede tratar este mensaje (pulsación) antes de que llege :smt002 . Que otro beneficio tiene esto??? El siguiente código que pronto colgaré: se puede anular la pulsación de alt+tab antes de que win lo reciba para tratarlo y gracias a esto no mostraría la ventanita alt+tab. Podríamos hacer nuestro propio conmutador de tareas!!! jajajaja.
Ximorro escribió:parece que KeyProc te da unas teclas en wparam y otras en lparam, ¿cómo funciona eso?
Creo recordar que el parámetro wparam te decía si has pulsado cualquier tecla (valor 256), excepto la tecla alt o alt gr la cual trataba a parte (te da otro valor....260 como pongo en el código). También te dice cuando has dejado de presionar una tecla con el valor 257. Lo podía haber filtrado con la función bitand y haberlo dejado más claro, pero al final pasé :smt025 .
lparam te da el valor de la tecla pulsada.
Ximorro escribió:Por cierto, me parece que las ventanas que no saca ALT+TAB son las que tienen como estilo extendido $WS_EX_TOOLWINDOW. Esas seguro que no las saca (ver la explicación de ese flag en la ayuda de GUICreate). A lo mejor mirando sólo ese flag para ver qué ventanas sacar o cuáles no...
Creo que sí lo miras pero está comentado, ¿es algo que has descartado luego?
Sí sí.....tienes razón. Fue la primera propiedad de ventana que miré, y la más adecuada para hacer un filtrado más selectivo. Lo tengo comentado junto a otra propiedad que también es válida ($WS_CAPTION), y como utilizarlas en los IF. Pero te has equivocado. Mira unas líneas más abajo y verás que la utilizo en la 2º comparación.
Con ninguna de estas propiedades es suficiente. Es necesario hacer un filtrado previo de las ventana que tengan la propiedad visible a true. Yo he utilizado la api _WinAPI_IsWindowVisible, pero hay muchas formas de saber eso.
No digo que no se puedan filtrar de alguna otra forma (segurísimo que sí). Pero como fue la primera que encontré, ahí lo deje.
Por cierto, lo que descarté son unas comparaciones iniciales las cuales se encontraban en el código inicial que colgé. Como lo edité no debiste verlo. No filtraba con la propiedad $WS_EX_TOOLWINDOW. Filtraba con _WinAPI_IsWindowVisible junto a que la ventana no tubiese título y no tuviese ni anchura ni altura. Pero en ese momento no se me ocurrió que una ventana puede hacerse sin título :smt005 .

Saludos.

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 16:50
por Jonny
Hola

Bueno bueno, yo me pierdo en eso de las propiedades de ventana etc...

Pero digo yo
En todo el lío de hacerlo con _IsPressed o los hooks que utiliza Chefito en su código
¿No podría solucionarse el problema con _IsPressed y una variable (flag) que controlara el estado del tabulador?
Almenos en el programa que estoy haciendo (en menudos verengenales me meto) acabé utilizando esta función de la que hablamos en otro post, comparándola con la api GetKeyState.

A mí parece funcionarme bien con una variable que controla el estado del tabulador.

Lo hice así:

Si (Alt==Pulsada y Tab==Pulsada) ;Compruebo si se han pulsado las teclas alt y tabulador.
Si $IsAltTab==0 ;Compruebo que el hotkey no estubiera pulsado anteriormente.
$IsAltTab=1 ;Marco el Hotkey como pulsado, para que no se produzcan más eventos de los deseados.
;Ejecutar instrucciones aquí

Si ((Alt==Liverada y Tab==Liverada) o (Alt==Pulsada y Tab==liverada)) ;Compruebo si se han liverado las teclas Alt y Tabulador o solo la tecla tabulador y se deja pulsada la tecla alt para conmutar entre las distintas aplicaciones.
Si $IsAltTab==1 ;Compruebo que el hotkey estubiera activo anteriormente.
$IsAltTab=0 ;Marco el hotkey como liverado para que pueda volverse a activar pulsando Alt+Tab o tabulador (si se dejó la tecla alt plsada).

Esto lo he escrito ahora de cabeza, pero básicamente es algo así. Esto, lo metí en un timer que constantemente hace estas comprobaciones y en principio, funciona correctamente. Al pulsar Alt+Tab se activa el hotkey (se notifica al programa mediante $IsAltTab=1) y se ejecutan las instrucciones que hayan en esa condición. Hasta que no se liveren ambas teclas o únicamente el tabulador, no ocurrirá nada más. Si volvemos a pulsar el hotkey o el tabulador volverá a ejecutarse el código de la condición anterior.

Salu2!

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 17:12
por Chefito
Mmmmmm......estamos en las mismas. Hay que controlar la velocidad de pulsación que realmente tenemos al pulsar. No creo que ese código lo haga.....pero sin ver el código funcional no puedo asegurar nada, ya que lo que has puesto es una explicación muy muy pobre :smt012 .

Piensa que además de tener que ir a la misma velocidad de pulsación que la ventana conmutador de tareas de win, también hay casos especiales que debes tratar, los cuales comenté arriba (topmost).

Cuando puedas pon tu código y lo analizamos.

Saludos.

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 18:58
por Jonny
Hola

Bueno... Yo en cuestiones tan técnicas me pierdo un poco.

Aquí está el código que llevo hecho.

http://www.sendspace.com/file/caxmtf

Se trata de una aplicación que lee la pantalla.

Hay poco hecho (este tema me ha llevado un montón de días) De echo, no lee nada más que la ventana que está activa, el bloqueo de mayúsculas y poco más, además de pausar la síntesis de voz pulsando el control (derecho) y verbalizar lo que en este caso nos ocupa. Al pulsar Alt+Tab, la síntesis de voz dice "Alt tab". si no soltamos ninguna de las dos teclas, no ocurre nada. Si soltamos ambas y pulsamos Alt+Tab nuevamente la síntesis vuelve a decir "Alt Tab".
Si en cambio pulsamos Alt+Tab y soltamos el tabulador, al volver a pulsarlo la síntesis dice igualmente "Alt Tab"...
Mejor probadlo jeje.

Debeis descomprimir Ivermedia.rar en c:\archivos de programa\Ivermedia\

Salu2!

Re: Ayuda con Winlist()

Publicado: 28 Sep 2009, 21:00
por Chefito
Mmmmm....solamente te pedía el código del tema que estamos tratando en este post, y si pudiese ser funcional mejor (sin tener que hacer movidas......como casi siempre que dejas algo :smt016 ).
He abierto los script que hay dentro y tienen muy poquito código (no te has equivocado???). Si quieres hacer algo bueno te falta muchiiiiiisiiiiimo :smt024 . Además da fallos por todos lados, ya que hay direccionamientos estáticos, faltan librerías, etc.
Pero a lo que vamos, aquí no he visto nada de lo que dices del alt+tab. Nada de nada.
Jonny escribió:Al pulsar Alt+Tab, la síntesis de voz dice "Alt tab". si no soltamos ninguna de las dos teclas, no ocurre nada. Si soltamos ambas y pulsamos Alt+Tab nuevamente la síntesis vuelve a decir "Alt Tab".
Si en cambio pulsamos Alt+Tab y soltamos el tabulador, al volver a pulsarlo la síntesis dice igualmente "Alt Tab"...
Con todos mis respetos ese funcionamiento del que hablas se hace con la gorra :smt002 . La detección de las teclas es algo sencillo en AutoIt. Lo dificil es conseguir el mismo título de ventana que señala el conmutador de tareas. Una vez que lo has conseguido, hacer que lo diga está chupado :smt003 .

Saludos :smt026 .

Re: Ayuda con Winlist()

Publicado: 29 Sep 2009, 06:56
por Jonny
Hola

La cosa, es que no me dió tiempo a incluir tu código en la detección de Alt+Tab, poreso lo puse al principio a modo de esquema y ´no el código.
Sorry, lo de que faltan librerías es cierto... Es, la maldita manía de tener librerías que no incluye el autoit aparte...

De todas maneras, para comprobar si funciona bien con _IsPressed o no, basta con un ConsoleWrite aunque sea ¿No?
Si lo que queremos es ver la velocidad a la que se ejecuta...

Salu2!

Re: Ayuda con Winlist()

Publicado: 29 Sep 2009, 09:54
por Ximorro
Pues mira Chefito, la parte de las teclas con IsPressed se podría hacer así como pongo abajo.
Para simplificar en vez de lo de las ventanas escribo en la consola lo que va pasando con las teclas, si lo ejecutas desde Scite es muy cómodo, si no tendrás que ejecutarlo desde una ventana DOS. :smt003

Como ves sólo ejecuta el proceso cada vez que se pulsa TAB una sola vez, por supuesto mientras ALT esté también presionado. Además se espera a que ALT se presione primero.

El programita sólo se ejecuta una ciclo de ALT (con varios posibles TAB), pero simplemente metiéndolo en un bucle pues lo haces todas las veces que quieras. No consume recursos, con ese Sleep(10) se me mantiene la CPU al 0%-1%, y 10ms es un tiempo muy bajo, como para no perder teclas. Lo que sí es cierto es que hay que comprobar activamente, con tu sistema usando mensajes de Windows está muy bien porque te avisa cuando ocurre, aunque de todas maneras tienes que esperar en un bucle que hace "nada" (vaya, otro Sleep(10) :smt002 ).

Código: Seleccionar todo

#include <Misc.au3>



Local $User32DLL = DllOpen("user32.dll")

Local $ALT = "A4", $TAB = "09", $n=0, $TabLiberado = False



;Esperamos que primero se pulse ALT

While Not _IsPressed($ALT, $User32DLL)

    Sleep(10)

WEnd

ConsoleWrite("ALT pulsado, esperando pulsaciones de TAB" & @CRLF)



;Ahora mientras se mantiene ALT, actuamos cada vez que se pulsa TAB, acabamos cuando se suelta ALT

;"actuar" es por ejemplo lo de sacar el texto e icono de la ventana, yo sólo pongo un mensaje en la consola

While _IsPressed($ALT, $User32DLL)

    If _IsPressed($TAB, $User32DLL) Then

        If $TabLiberado Then ;Actuamos si antes estaba liberado, así no ejecutamos constantemente mientras se pulsa

            $TabLiberado = False

            $n+=1

            ConsoleWrite("ALT+TAB pulsado, veces: " & $n & @CRLF)

        EndIf

    Else

        $TabLiberado = True

    EndIf

    Sleep(10)

WEnd



ConsoleWrite("ALT soltado, proceso finalizado." & @CRLF)

DllClose($User32DLL)
Ahora me tengo que estudiar tu código a ver si lo entiendo mejor. A parte de lo de AutoIt está el tema "conocimiento Windows", como que el orden de las ventanas ALT+TAB se consigue con la propiedad "ventana siguiente" empezando con la siguiente al Program Manager... Y lo mismo para conocer el funcionamiendo de KeyProc, ¿dónde podemos ver los códigos que toman los parámetros cuando se pulsan las teclas?

Lo que no veo por qué no estás impidiendo que Windows vea las teclas, esto me parece muy parecido al control de mensajes de Windows a través de AutoIT, y leí que había que devolver algo así como $GUI_RUNDEFMSG para que el mensaje sea rebotado al Windows y también lo procese. ¿O eso sólo es cuando cazas el mensaje con GUIRegisterMsg? ¿Cómo impedirías con tu método que Windows no capture ALT+TAB?... ¡pero sí las demás teclas!

Re: Ayuda con Winlist()

Publicado: 29 Sep 2009, 13:50
por Chefito
Respecto a la forma que intentas hacer esto, pufffff.....os recomiendo que lo olvideis :smt003 . No creo que sea una forma viable.
Para empezar, sigues sin poder controlar (ni lo vas ha hacer de esta forma) el tiempo al que se le pasan las pulsaciones.
Sí, muy bien, pulsas alt+tab y da una pulsación en su momento, ya que has puesto una variable auxiliar para parar la ejecución del código hasta que no sueltes la combinación de teclas y las vuelvas a pulsar. Pero resulta que esto no es simplemente una pulsación y ya está. Tienes que detectar las pulsaciones que genera win cuando mantienes apretada esa combinación, y tu código no lo hace.
Además, sigues dependiendo del bucle while inicial. Si metes un retardo grande, o simplemente salta un msgbox o cualquier otra cosa que te pare la aplicación, esto deja de funcionar. Seguramente este problema si tenga alguna solución, como meterlo en un timer asíncrono en vez de en el bucle.
Pero repito, yo creo que no vas a poder controlar en la vida la velocidad exacta de las pulsaciones sin capturarlas por mensajes de win :smt009 . Y ese es un grandísimo problema para este caso.
Prueba todo lo que te he dicho en mi código y verás que sigue su funcionamiento normal, ya que lo hace de forma asíncrona. Lo único que fallaría sería todo lo que está metido en el while, como cerrar la ventana, pero esto podría solucionarse con un timer asíncrono que detectase este evento :smt016 .

Aaahhh, y otra cosa. Si por alguna casualidad se consiguiese hacer lo de la velocidad así por las buenas (lo dudo), luego tendrías el problema de ir metiendo todas las condiciones que he tenído que encajar.....que es lo que más me ha costado :smt021 .
Ximorro escribió:Lo que sí es cierto es que hay que comprobar activamente, con tu sistema usando mensajes de Windows está muy bien porque te avisa cuando ocurre, aunque de todas maneras tienes que esperar en un bucle que hace "nada" (vaya, otro Sleep(10) ).
Aquí si que no te entiendo. Que tengo que esperar en un bucle que no hace nada? Solamente espero en el while principal, para que no se cierre la aplicación, pero eso es normal en todos los programas.
Si te refieres al while interno de la función _KeyProc, no afecta para nada al funcionamiento del programa, ya que se supone que mientras tengas apretadas atl+tab, no vas a poder hacer otra cosa que conmutar las ventanas (y si no mira win :smt016 ).
Y si por casualidad quieres hacer otra cosa, metelo dentro de ese while o dentro de un timer :smt016 .
Ximorro escribió:Y lo mismo para conocer el funcionamiendo de KeyProc, ¿dónde podemos ver los códigos que toman los parámetros cuando se pulsan las teclas?
Los códigos de las teclas son los keycode.....los mismos que utiliza la función _IsPressed :smt002 . Te los devuelve la variable $codigo. Puedes hacer un consolewrite($codigo&@cr) y verás los códigos al pulsar las teclas.
Ximorro escribió:Lo que no veo por qué no estás impidiendo que Windows vea las teclas, esto me parece muy parecido al control de mensajes de Windows a través de AutoIT, y leí que había que devolver algo así como $GUI_RUNDEFMSG para que el mensaje sea rebotado al Windows y también lo procese. ¿O eso sólo es cuando cazas el mensaje con GUIRegisterMsg?
Jajajaja....pues mira, me acabas de enseñar algo nuevo. No tenía ni idea de que hacía la devolución de esa variable. Creía que no era importante y yo siempre la quitaba :smt005 . Habrá que ponerla al final por si acaso alguna vez genera algún error no deseado el no ponerla :smt002 .
Me has hecho leer en función GUIRegisterMsg en la ayuda. Puffffff....mi ingles es muy limitado y no lo entiendo muy bien. Y el google a veces traduce peor que yo :smt005 . Es como si dijese que para retornar a los mensajes internos de autoit se debe hacer esto :smt017 (que traducción más mala por mi parte :smt003 ). No se no se.....estaría bien que alguno lo tradujese bien o que algún gurú de autoit no lo explicase.
Pero como tu bien dices parece que solo es cuando utilizas la funcion GUIRegisterMsg (que tampoco lo se a ciencia cierta. Ya te he dicho que ni papa de esta variable).
Pero pero pero.....jajajaja.....me has hecho pensar y me has recordado que si me dejaba algo por el camino. Así que me he ido al foro de habla inglesa y he buscado la función. Parece que al final devuelven el proximo gancho del teclado. Al no devolver yo nada, puede que el mensaje llege sin ninguna variación, pero por si acaso voy a editar el código y voy a meter esa devolución.

Código: Seleccionar todo

Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)

 
Ximorro escribió:¿Cómo impedirías con tu método que Windows no capture ALT+TAB?... ¡pero sí las demás teclas!
No retornando nada o un valor nulo a esta función (por ejemplo con un simple Return, Return -1, Return 1, etc :smt005 :smt005 :smt005 :smt005 ).
Tenías que haber buscado en el foro, que no es la única vez que utilizo esta función. Por ejemplo: http://www.emesn.com/autoitforum/viewto ... Proc#p3059
Con este script verás mejor el funcionamiento del código.
Por curiosidad acabo de buscar en la ayuda y me ha aparecido un ejemplo que utiliza esto :smt005 . Ignoraba que estuviese ahí. A lo mejor en la antigua ayuda no aparecía. Como puedes ver el ejemplo del post anterior es bastante antiguo.
Mira en la ayuda el ejemplo de por ejemplo la función _WinAPI_CallNextHookEx.

Y probando mi script del conmutador de tareas, tenía abierta una ventana que me ha dado problemas y resulta que no me filtra una ventana oculta que pertenece a este programa!!!!! jajajaja.....me caguen en tooooo lo que se meneeeaaaa.
Solucionado. He sustituído el filtro que utiliza la propiedad $WS_EX_TOOLWINDOW por otro que utiliza $WS_CAPTION (parece que filtra mejor) y he dejado otros en comentarios por si fallase este también. CODIGO DEL POST DE ARRIBA EDITADO (OTRA VEZ).

Re: Ayuda con Winlist()

Publicado: 29 Sep 2009, 13:59
por Ximorro
He estado simplificando un poco la función de Chefito. Ya entiendo mejor algunas cosas, creía que _KeyProc era una función ya definida en Windows, pero en realidad es una función de usuario que se engancha a los eventos de teclado. Al fin y al cabo todo trata de ejecutar funciones cuando saltan ciertos mensajes de Windows, probablemente todo esto también se puede hacer capturando el mensaje WM_KEYDOWN (o uno similar) con GUIRegisterMsg, y nos evitamos el follón de las llamadas a las dll.

Me gustaría simplificar el bucle principal porque la verdad es que uno se vuelve loco siguiéndolo ;-). Ya he hecho algo y postearé la versión final, pero me gustaría entender mejor algunas cosas, por ejemplo:
a) Cuando la variable $EmpezarSegundo es FALSE es cuando quieres que empiece por el segundo, es decir, el nombre de la variable sería lo inverso del significado ¿no? Es que lía un poco cuando lees el código. Si lo he entendido bien y no me dices lo contrario la llamaré $ProcesarPrimero, así cuando sea FALSE empezará por el segundo...
b) No entiendo muy bien el uso de $auxOnTop, ¿hay que saltarse la primera ventana si es topmost? ¿y las demás topmost no hay que saltarlas? ¿por qué sólo la primera?

Por complicar un poco la cosa, je, je. ¿Cómo se mira aquí si además de ALT se está pulsando "Mayús"? porque en ese caso el ALT+TAB va hacia atrás al recorrer las ventanas... :smt017

EDITADO:
ANDA estábamos escribiendo a la vez. Bueno, mañana veo tu último post que ahora no tengo tiempo...

Re: Ayuda con Winlist()

Publicado: 29 Sep 2009, 14:54
por Chefito
Ximorro escribió:a) Cuando la variable $EmpezarSegundo es FALSE es cuando quieres que empiece por el segundo, es decir, el nombre de la variable sería lo inverso del significado ¿no? Es que lía un poco cuando lees el código. Si lo he entendido bien y no me dices lo contrario la llamaré $ProcesarPrimero, así cuando sea FALSE empezará por el segundo...
Haz lo que quieras. Mi código está ahí para que hagaís lo que querais. Pero yo creo que no está tan mal definido su nombre.
Lo que hace es que cuando es falsa adelanta una posición (proxima ventana) a la 1º encontrada....vamos, que en una situación normal (sin ventanas con la propiedad topmost) empezaría mostrándote la segunda. Y cuando es true ya va incrementándose normalmente (una a una).
Ximorro escribió:b) No entiendo muy bien el uso de $auxOnTop, ¿hay que saltarse la primera ventana si es topmost? ¿y las demás topmost no hay que saltarlas? ¿por qué sólo la primera?
Haber. SauxOnTop es una variable auxiliar que gracias a ella se salta todas las ventanas con la propiedad topmost. Eso lo hace gracias a la condicion If $WinOnTop And $auxOnTop Then, la cual funciona así:
Comenzamos con otra condición muy importante, If _WinIsOnTop(WinGetHandle("[active]")) Then, la cual nos dice si la ventana activa cuando pulsamos alt+tab es ontop poner $auxOnTop=false. Esto quiere decir que si la ventana activa es ontop continua el script normalmente y saltate directamente la condición If $WinOnTop And $auxOnTop Then, ya que es una ventana normal y tienes que pasar a la siguiente ventana de la actual.
Si la ventana activa es ontop, entonces $auxOnTop=true. Con esto le decimos que tenemos que saltarnos las ventanas que hayan ontop, además de la activa. Entonces entramos en la condición If $WinOnTop And $auxOnTop Then, la cual es verdadera, ya que la ventana actual es ontop y $auxontop=true. Al entrar aquí, le decimos que pase a la siguiente ventana, la cual, gracias al bucle while, comprueba de nuevo si esta siguiente ventana es ontop. Si lo es misma operación. Así hasta que encuentre una ventana que no sea ontop y $winontop=false. Entonces entrará en el proceso normal de selección de ventanas.
Y porque pongo esta doble condición y luego cuando entra en el proceso normal pongo $auxOnTop=false? Pues porque al conmutar las tareas podemos llegar de nuevo a seleccionar las ventanas del principio (ontop), y $winontop sería de nuevo true. Si no tuviesemos $auxontop=false entraría en el código de saltarse las ventanas ontop y esto no es viable, ya que tienen que ir de una en una (estoy hablando de más de una vuelta recorrida con el tab en el conmutador de tareas). Por esa causa tuve que poner esa variable auxiliar, para que a partir de la segunda vuelta pasase todas las ventanas una a una incluyendo las ontop.

Pufffffffffffffff.....que rollo :smt005 . Espero haberlo dejado algo más claro y no haberte liado más :smt005 .
Por eso te digo que tengas cuidado con lo que tocas en el código, ya que puedes afectar a otras zonas del código y cargarte todo. Ademas, puede que toques alguna cosa y siga funcionando el programa, pero que en alguna ocasión te falle (por ejemplo si tienes o no ventanas ontop). Estos pequeños fallos son los que me han vuelto loco.

Y otra cosa. No subestimes el poder de las apis de win :smt040 . En más de una ocasión se ha demostrado (por ejemplo en este foro recuerdo algo) que utilizar apis de win es más rápido que comandos de AutoIt :smt005 .

Saludos.

Re: Ayuda con Winlist()

Publicado: 30 Sep 2009, 11:11
por Ximorro
Bueno, por partes :smt002

Que conste que no he dicho que era mejor con _IsPressed que con KeyProc, en realidad nunca he dudado que fuera mejor con KeyProc o algún otro sistema que mire los mensajes. Simplemente decía que era posible hacerlo con _IsPressed, y básicamente es que como el sistema del KeyProc no lo entiendo mucho (ahora más, pero no del todo) pues quería investigar la otra vía.

Ciertamente lo peor que tiene el _IsPressed es la falta de control de la repetición de tecla, en eso no había pensado, si bien se puede simular simplemente poniendo $TabLiberado a True cada cierto tiempo (tiempo que seguramente se puede sacar del registro para que sea exactamente el tiempo de repetición de tecla que tiene Windows).

Pero sí, es más cómodo con lo del KeyProc.

Respecto a los retardos... ¿quieres decir que tu sleep(10) es interrumpido cuando llega un evento de teclado? Si no es así es el mismo caso que mi bucle, si es así ¡ole por el sistema KeyProc! (Porque me refería al bucle principal del GUI, donde tienes el sleep, a eso me refería con "el bucle que no hace nada", vaya, lo que hace es esperar a ser interrumpido por el evento del teclado)

Lo de los códigos... si son los keycodes, ¿por qué no miras el TAB igual que el Mayús, ¿las teclas especiales tipo Mayús, Ctrl y tal se dan en $wparam?, ¿no se ven en $lparam junto con las otras?

Vale, he aquí traducción de GUIRegisterMsg, en negrita el meollo de $GUI_RUNDEFMSG:
Registra una función de usuario para un ID de mensaje conocido de Windows (WM_MSG).
GUIRegisterMsg ( msgID, "function" )

Parámetros:
msgID ID de mensaje de Windows (ver Apéndice: Windows Message Codes).
function Nombre de la función de usuario para ser llamada cuando el mensaje aparece, o cadena vacía "" para desregistrar un mensaje.

Valor de Retorno
Exito: 1
Fracaso: 0

Notas

¡¡¡ Para que la función de usuario funcione debes definirla con un máximo de 4 parámetros, de otra manera no será llamada!!!
p.ej.:
Func MyUserFunction($hWndGUI, $MsgID, $WParam, $LParam)
...
EndFunc

Or
Func MyUserFunction($hWndGUI, $MsgID)
...
EndFunc

Cuando la función de usuario es llamada los 4 parámetros tienen estos valores:
1 hWnd Manejador de la ventana del GUI en el que aparece el mensaje
2 Msg ID de mensaje de Windows
3 wParam Primer parámetro del mensaje como valor hexadecimal
4 lParam Segundo parámetro del mensaje como valor hexadecimal

Se pueden registrar hasta 256 funciones de usuario para ID's de mensaje.

Por defecto al finalizar la función de usuario el manejador de mensajes interno de AutoIt será procesado.
Esto no ocurrirá si devuelves un valor con Return (Ver WM_COMMAND en ejemplo) o si usas Return sin especificar algún valor.
¡Usando Return sin ningún valor de retorno el manejador de mensajes interno de AutoIt (si hay alguno para este mensaje) NO SERÁ procesado!

¡¡¡Si quieres que AutoIt ejecute su manejador interno para un mensajes, devuelve la variable $GUI_RUNDEFMSG (en GUIConstantsEx.au3) desde la función (ver también ejemplos)!!!
P.ej. Si quieres regresar antes de que la función de usuario termine y también procesar el manejador de mensajes interno de AutoIt.
Advertencia: bloquear la ejecución de funciones de usuario que ejecutan mensajes de Windows con comandos como "Msgbox()" pueden llevar a comprotamientos inesperados, ¡¡¡el retorno al sistema debería ser tan rápido como sea posible!!!

Algunos controles consumen internamente mensajes específicos de Windows, así que registrarlos no tendrá efecto, por ejemplo WM_CHAR, WM_KEYDOWN, WM_KEYUP son consumidos por un edit control.

-------------

Anda, entonces esto último me dice que registar WM_KEYDOWN para hacer esto del ALT+TAB no funcionaria si un EditControl tiene el foco, ¡pues vaya!.

Uf, voy a darme un descanso y luego sigo leyéndote ;-)

Re: Ayuda con Winlist()

Publicado: 30 Sep 2009, 11:42
por Ximorro
¡Pues sí!He comprobado que con lo de SetWindowsHookEx el Sleep del bucle principal es interrumpido cuando llega una tecla (he puesto sleep(10000) y seguía funcionando perfectamente, excepto que no podía cerrar el GUI, pero eso es por GUIGetMsg ejecutándose tan poco, lo de KeyProc iba de maravilla).

Me dices que devolviendo cualquier cosa en KeyProc impedirías que Windows viera las teclas, pero tú no devolvías nada, que es lo mismo que devolver 0 (cero), según he leído en la ayuda de AutoIt. Ahora sí devuelves eso del gancho siguiente pero antes no y funcionaba igual. Vale, he hecho unas comprobaciones, para bloquear el mensaje a Windows hay que devolver algo DIFERENTE de cero (teniendo en cuenta que "Return 0" es equivalente a "Return" o a no poner Return en absoluto).

Por cierto, que resulta que en WinAPI.au3 hay funciones que mapean GetModuleHandle, SetWindowsHookEx y UnhookWindowsHookEx, y quizás otras que te interesan, así que por ejemplo el churro:

Código: Seleccionar todo

Global $hHook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_KEYBOARD_LL, "ptr", DllCallbackGetPtr($hStub_KeyProc), "hwnd", $hmod[0], "dword", 0)
se puede escribir más cómodamente como:

Código: Seleccionar todo

Global $hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)

En el otro post veo que $wparam indica qué pasa con la tecla, si se presiona, si se suelta... interesante. Estooo, ¿por qué no lo haces aquí y funciona igualmente. Al no mirarlo también debería cambiar de ventana al SOLTAR tab, pero no es así, ¿por qué no entra en el bucle en esos casos? ¿O con wparam=260 estás mirando a la vez "con mayús y tecla pulsada?

Respecto a lo de $EmpezarSegundo, no pretendo decirte cómo debes llamar a tus variables, lo que pasa es que me hacía un lío porque la variable cuando vale false empieza por el segundo, entonces la lógica es:
Si $EmpezarSegundo Entonces
procesamos el primero
Sino
procesamos el segundo
Finsi

Como es lo contrario de lo que dice me estaba haciendo un lío, y lo he cambiado para entenderlo mejor.

Buf, me temo que no entiendo lo de la variable auxiliar $auxOnTop, parecería que simplemente ir mirando las ventanas que vas pasando e ignorando las ontop debería ser suficiente. Es decir, que debería valer con si $WinOnTop=true entonces la saltamos.
Es evidente que no es así pero no lo veo, eso lo seguiré investigando.

No me extraña que este código te haya dado dolores de cabeza, ¡quién iba a pensar que la ventana del ALT+TAB fuera tan complicada!

¡Ah, y para nada subestimo el poder de las APIs!. Al contrario, está claro que "tienen el poder" :smt003 No sé por qué lo dices, nunca he dicho lo contrario, si te refieres a mi empeño a probrar lo de _IsPressed hay que tener en cuenta que eso lo que hace es básicamente
DllCall('user32.dll', "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
tal como podemos ver en Misc.au3, o sea, otra llamada a la API, je, je, je.
Si AutoIt va de eso, de dejarnos meternos en las entrañas de Windows a través de un lenguaje sencillito de usar.