Hallo zusammen,
ich versuche zur Zeit eine kleine GUI zum wechseln zwischen geöffneten Fenstern zu erstellen (wie Alt+TAB).
Hintergrund:
Das ganze soll auf einer fünf Meter breiten, interaktiven Wand laufen, welche leider nur über single Touch verfügt.. Alt+TAB geht also nicht und Flip3D über Win+TAB ist auch nicht wirklich befriedigend.
Vielleicht hat ja der ein oder andere hier ein paar Verbesserungsvorschläge für mich? Falls es möglich ist, die Vorschaubilder der Fenster oder die Programmicons für die Buttons zu bekommen wäre das super!
Hier mein Code:
Ist noch sehr frisch, aber man bekommt eine Vorstellung... Haltet euch
nicht zurück, fall das alles Mist ist und es sinnvollere Ansätze gibt
Grüße,
notna
Edit: Script läuft mittlerweile wie gewünscht Vielen Dank an Raupi und name22 für die großartige Unterstützung! Hier also die optiierte, wohl endgültige Version:
Spoiler anzeigen
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <Process.au3>
_Singleton("switch", 0)
Opt("GUICoordMode", 0)
Opt("TrayIconHide", 1)
Global Const $GCL_CBCLSEXTRA = -20
Global Const $GCL_CBWNDEXTRA = -18
Global Const $GCL_HBRBACKGROUND = -10
Global Const $GCL_HCURSOR = -12
Global Const $GCL_HICON = -14
Global Const $GCL_HICONSM = -34
Global Const $GCL_HMODULE = -16
Global Const $GCL_MENUNAME = -8
Global Const $GCL_STYLE = -26
Global Const $GCL_WNDPROC = -24
$allwindows = WinList()
$count = $allwindows[0][0]
Global $relatedwindows[$count][$count]
$rows = 1
$colums = 0
$cnt = 1
$j = 1
$mouseX = MouseGetPos(0)
Global $thirdW = @DesktopWidth / 3
$third2 = (2 * $thirdW)
$third3 = @DesktopWidth
$x1 = ($thirdW / 2 - 332)
$x2 = ($thirdW + $x1)
$x3 = ($thirdW + $x2)
Global $winH = @DesktopHeight
Global $2thirdW = 2 * @DesktopWidth / 3
Global $maxW = @DesktopWidth
Global $m1X = 0
Global $m2X = @DesktopWidth / 3
Global $m3X = 2 * @DesktopWidth / 3
;;
Global $guiW, $guiH; auf jeden Fall deklarieren, sonst mault AutoIt
;---> Positionsbestimmung
If $mouseX <= $thirdW Then
$guiX = $x1
ElseIf $mouseX <= $third2 Then
$guiX = $x2
ElseIf $mouseX <= $third3 Then
$guiX = $x3
EndIf
;---> Fenster sammeln & Filtern. Anzahl von Zeilen & Spalten bestimmen.
For $i = 1 To $count
If (BitAND(WinGetState($allwindows[$i][1]), 16) Or WinGetState($allwindows[$i][1]) = 7) And $allwindows[$i][0] <> "Start" And $allwindows[$i][0] <> "Program Manager" And $allwindows[$i][0] <> "DWM Notification Window" And $allwindows[$i][0] <> "AMD:CCC-AEMCapturingWindow" And $allwindows[$i][0] <> "2. Client Starten" And $allwindows[$i][0] <> "SBSDKInstance" And $allwindows[$i][0] <> "" Then
$relatedwindows[$j][0] = $allwindows[$i][0]
$relatedwindows[$j][1] = $allwindows[$i][1]
$colums = $colums + 1
$j = $j + 1
If $colums > 4 Then
$colums = 1
$rows = $rows + 1
EndIf
EndIf
Next
;---> Maße der GUI gemäß Zeilen & Spalten
If $j == 1 Then
$guiW = 260
ElseIf $j <= 4 Then
$guiW = $j * 115
Else
$guiW = 550
EndIf
$guiH = ($rows * 90)
$ygap = 80
;---> semitransparenter Hintergrund
$background = GUICreate("", $guiW, $guiH, $guiX, -1, $WS_POPUP, $WS_EX_TOPMOST)
GUISetBkColor(0x01)
_Gui_RoundCorners($background, 0, 0, 50, 50)
WinSetTrans($background, "", 100)
GUISetState()
;---> transparente GUI mit "Kacheln" für die Fenster
$winswitch = GUICreate("Switch", $guiW, $guiH, $guiX, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST), $background)
GUISetBkColor(0x01)
$hDC_Window = _WinAPI_GetDC($winswitch) ;---> DC für Icon extract...
;---> Meldung, falls keine Fenster geunden wurden...
If $j == 1 Then
GUICtrlCreateLabel("", 20, 40, 215, 35)
GUICtrlSetBkColor(-1, 0x757273)
GUICtrlCreateLabel("sorry, there are no windows...", 5, 5, 230, 25)
GUICtrlSetFont(-1, 12, 500, 0, "Segoe UI")
GUICtrlSetColor(-1, 0xffffff)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Else
For $i = 1 To $j - 1
If $i = 1 Then ; Erster Button
$relatedwindows[1][2] = GUICtrlCreateButton($relatedwindows[1][0], 25, 25, 110, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE))
ElseIf $cnt = 4 Then; 4. Button in der Zeile
$relatedwindows[$i][2] = GUICtrlCreateButton("", -388, -1 + $ygap, 110, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE))
$cnt = 1
Else
$relatedwindows[$i][2] = GUICtrlCreateButton("", -1 + 130, -1, 110, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE))
$cnt = $cnt + 1
EndIf
;Hier ist die Deklaration zu Ende, der übrige Code bleibt gleich
$hIcon = _SendMessage($relatedwindows[$i][1], $WM_GETICON, 2, 0, 0, Default, Default, "HANDLE")
If Not $hIcon Then $hIcon = GetIconfromExe($relatedwindows[$i][0])
If Not $hIcon Then $hIcon = _SendMessage($relatedwindows[$i][1], $WM_GETICON, 0, 0, 0, Default, Default, "HANDLE")
If Not $hIcon Then $hIcon = _WinAPI_GetClassLongEx($relatedwindows[$i][1], $GCL_HICON)
If Not $hIcon Then $hIcon = _WinAPI_GetClassLongEx($relatedwindows[$i][1], $GCL_HICONSM)
GUICtrlSetData($relatedwindows[$i][2], StringLeft($relatedwindows[$i][0], 10));Buttontext einfügen, egal ob es ein Icon gibt !!!!
GUICtrlSetFont($relatedwindows[$i][2], 10, 400, 0, "Segoe UI")
If $hIcon Then
Local $hOldImage = _SendMessage(GUICtrlGetHandle($relatedwindows[$i][2]), $BM_SETIMAGE, 1, $hIcon)
_SendMessage($winswitch, $WM_ERASEBKGND, $hDC_Window)
_WinAPI_DestroyIcon($hOldImage);Altes ButtonIcon zerstören
_WinAPI_DestroyIcon($hIcon)
EndIf
Next
EndIf
GUISetState()
_WinAPI_SetLayeredWindowAttributes($winswitch, 0x01, 255)
;---> Falls keine Fester gefunden: Meldung für 3sec zeigen und dann beenden.
If $j == 1 Then
Sleep(3000)
Exit
EndIf
While 1
$msg = GUIGetMsg()
WinSetOnTop($winswitch, "", 1)
Switch $msg
Case $GUI_EVENT_CLOSE
Exit
Case Else
;---> Auf Buttons lauschen
For $i = 1 To $j - 1
If $msg = ($relatedwindows[$i][2]) Then
__PopUp($relatedwindows[$i][0])
Exit
EndIf
Next
EndSwitch
WEnd
;---> PoUp mit Aktionen für gewähltes Fenster
Func __PopUp($window)
$position = GUICreate("", 338, 280, $guiX, -1, $WS_POPUP, $WS_EX_TOPMOST, $background);Wenn diese Gui als vorderste liegen soll und die HauptGui nicht mehr anklickbar sein soll, Parent als letzten Parameter setzen.
GUISetBkColor(0x01)
;==> Positions
GUICtrlCreateGroup("", 25, 25, 290, 160)
GUICtrlSetColor(-1, 0xffffff)
GUICtrlCreateLabel(" Action ", 15, -8, 63, 25)
GUICtrlSetFont(-1, 12, 500, 0, "Segoe UI")
GUICtrlSetColor(-1, 0xffffff)
$m1 = GUICtrlCreateButton("", -1, 30, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\m1-gui.ico")
$m2 = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\m2-gui.ico")
$m3 = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\m3-gui.ico")
$m12 = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\m12-gui.ico")
$m23 = GUICtrlCreateButton("", -210, 70, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\m23-gui.ico")
$max = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\maximize-gui.ico")
$min = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\minimize-gui.ico")
$close = GUICtrlCreateButton("", 70, 0, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetImage(-1, @ScriptDir & "\GUI\close-gui.ico")
$esc = GUICtrlCreateButton("cancel", -105, 90, 50, 50, BitOR($BS_MULTILINE, $BS_PUSHLIKE, $BS_ICON))
GUICtrlSetFont(-1, 12, 400, 0, "Segoe UI")
_Gui_RoundCorners($position, 0, 0, 50, 50)
GUISetState(@SW_SHOW)
While 1
$button = GUIGetMsg()
Switch $button
Case $GUI_EVENT_CLOSE
Exit
Case $m1
WinActivate($window, "")
$positionX = $m1X
$positionW = $thirdW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $m2
WinActivate($window, "")
$positionX = $m2X
$positionW = $thirdW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $m3
WinActivate($window, "")
$positionX = $m3X
$positionW = $thirdW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $m12
WinActivate($window, "")
$positionX = $m1X
$positionW = $2thirdW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $m23
WinActivate($window, "")
$positionX = $m1X
$positionW = $2thirdW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $max
WinActivate($window, "")
$positionX = $m1X
$positionW = $maxW
WinMove($window, "", $positionX, 0, $positionW, $winH, 3)
Exit
Case $min
WinSetState($window, "", @SW_MINIMIZE)
Exit
Case $close
WinClose($window, "")
Exit
Case $esc
Return
EndSwitch
WEnd
EndFunc ;==>__PopUp
Func _Gui_RoundCorners($h_win, $i_x1, $i_y1, $i_x3, $i_y3)
Local $XS_pos, $XS_ret, $XS_ret2
$XS_pos = WinGetPos($h_win)
$XS_ret = DllCall("gdi32.dll", "long", "CreateRoundRectRgn", "long", $i_x1, "long", $i_y1, "long", $XS_pos[2], "long", $XS_pos[3], "long", $i_x3, "long", $i_y3)
If $XS_ret[0] Then
$XS_ret2 = DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $XS_ret[0], "int", 1)
EndIf
EndFunc ;==>_Gui_RoundCorners
Func _WinAPI_GetClassLongEx($hWnd, $iIndex)
[/autoit] [autoit][/autoit] [autoit]Local $Ret
[/autoit] [autoit][/autoit] [autoit]If @AutoItX64 Then
$Ret = DllCall('user32.dll', 'ulong_ptr', 'GetClassLongPtrW', 'hwnd', $hWnd, 'int', $iIndex)
Else
$Ret = DllCall('user32.dll', 'ulong', 'GetClassLongW', 'hwnd', $hWnd, 'int', $iIndex)
EndIf
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, 0)
EndIf
Return $Ret[0]
EndFunc ;==>_WinAPI_GetClassLongEx
Func GetIconfromExe($Title)
Local $iIcons = 1; 1
Local $t_ahIcons = DllStructCreate("HWND[" & $iIcons & "]") ;HWND Array um die Icons zu erhalten
Local $p_ahIcons = DllStructGetPtr($t_ahIcons)
Local $PID = WinGetProcess($Title)
Local $Prozessname = _ProcessGetName($PID)
Local $AndwendungsPfad = _GetPathByPid($PID)
If $Prozessname <> "explorer.exe" Then
_WinAPI_ExtractIconEx($AndwendungsPfad, 0, 0, $p_ahIcons, $iIcons)
If Not @error Then Return DllStructGetData($t_ahIcons, 1, 1)
Return 0
Else; Fenster gehört zu Explorer.exe geladen wird dabei das 202. ICon aus der imageres.dll. ggF. kann auch ein anderes verwendet werde.
_WinAPI_ExtractIconEx(@SystemDir & "\imageres.dll", 202, 0, $p_ahIcons, $iIcons)
If Not @error Then Return DllStructGetData($t_ahIcons, 1, 1)
Return 0
EndIf
EndFunc ;==>GetIconfromExe
Func _GetPathByPid($iPID); gefunden im Englischen Forum , verfasser nicht bekannt.
Local $aProc = DllCall('kernel32.dll', 'hwnd', 'OpenProcess', 'int', 0x0410, 'int', 0, 'int', $iPID)
If $aProc[0] = 0 Then Return SetError(1, 0, '')
Local $vStruct = DllStructCreate('int[1024]')
DllCall('psapi.dll', 'int', 'EnumProcessModules', 'hwnd', $aProc[0], 'ptr', DllStructGetPtr($vStruct), 'int', DllStructGetSize($vStruct), 'int_ptr', 0)
Local $aReturn = DllCall('psapi.dll', 'int', 'GetModuleFileNameExW', 'hwnd', $aProc[0], 'int', DllStructGetData($vStruct, 1), 'wstr', '', 'int', 2048)
If $aReturn[0] = 0 Then Return SetError(2, 0, '')
Return $aReturn[3]
EndFunc ;==>_GetPathByPid