Estoy intentando capturar el conmutador de ventanas tanto con Alt-tab como con Alt-shift-tab.
La captura con Alt-tab, está solucionada gracias a Chefito y Ximorro en este post que puse hace ya un tiempo, que lo suyo les costó dar con la mejor forma de filtrar ventanas, etc etc:
http://www.emesn.com/autoitforum/viewto ... f=3&t=1757
La cosa está ahora, en hacer lo mismo, pero a la inversa; cuando se pulsa Alt-shift-tab, que el desplazamiento por el conmutador de ventanas es en el sentido contrario.
Imaginé, que no sería muy complicado, pero la verdad es que no acaba de funcionarme.
Creí, que básicamente para cambiar el sentido del desplazamiento por el conmutador, tendría que tocar únicamente la llamada a la función _WinAPI_GetWindow(), cambiando el segundo parámetro.
Por ejemplo, - $GW_HWNDNEXT por $GW_HWNDPREV o $GW_HWNDFIRST por $GW_HWNDLAST, como he hecho en el siguiente código.
(El código es el de Chefito, solo con las modificaciones que creí que bastarían):
Código: Seleccionar todo
#include <GUIConstantsEx.au3>
#Include <WinAPI.au3>
#include<Constants.au3>
#include <WindowsConstants.au3>
Global $Codigo=0
Global $NumWin
Global $ProgramManager
Global $Hwnd
Global $EmpezarSegundo
Global $AuxOnTop
Global $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_HWNDLAST) ;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_HWNDPREV)
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_HWNDPREV)
;doy el handle de la siguiente ventana.
ExitLoop
Else
$EmpezarSegundo=True
$Hwnd=_WinAPI_GetWindow($Hwnd, $GW_HWNDPREV)
EndIf
EndIf
ElseIf $Hwnd=$ProgramManager Then
$NumWin=0
$Hwnd=_WinAPI_GetWindow($ProgramManager, $GW_HWNDLAST)
Else
$Hwnd=_WinAPI_GetWindow($Hwnd, $GW_HWNDPREV)
EndIf
Else
$Hwnd=_WinAPI_GetWindow($Hwnd, $GW_HWNDPREV)
EndIf
WEnd
EndIf
EndIf
Return _WinAPI_CallNextHookEx($hHook, $NCode, $WParam, $LParam)
EndFunc
Func OnAutoItExit()
DllClose($Dll)
DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hHook[0])
DllCallbackFree($HStub_KeyProc)
EndFunc
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
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
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
¿Se os ocurre donde está el fallo?.
Acias,
Salu2!