[HowTo] Transparente GUI; GuiOnEventMode

03/15/2013 17:47 Achat#1
Hi epvp!

In diesem HowTo möchte ich euch zeigen, wie ihr eine
  • transparente
  • teilweise durchsichtige
  • verschiebbare
  • dauerhaft auf dem Desktop anzeigbare
  • Pop-Up

GUI erstellen könnt.

Zuerst suchen wir uns ein schönes Bild.gif:
[Only registered and activated users can see links. Click Here To Register...]

Ich habe dort schon den Hintergrund eingefärbt. Eine Farbe wird nämlich nachher transparent gemacht.
Die Farbe hier ist 0x0CFF00. Bei jpg ändert sich aufgrund der Kompression der Farbwert, den wir für die Transparenz gesetzt haben. Deshalb verwenden wir *.gif.

Falls ihr in eurem Bild keine Farbe findet, die noch nicht benutzt wird, müsst ihr eine beliebige Farbe einfach um einen Farbwert verschieben, damit später nicht Teile des Bildes transparent werden (löchrig).

[Only registered and activated users can see links. Click Here To Register...] (Standard) vs [Only registered and activated users can see links. Click Here To Register...]
Kommen wir nun zum GUIOnEventMode.

Beispiel-Source

Ohne den GUIOnEventMode sieht es etwa so aus:

Code:
$GUI=GuiCreate(...
$Control1=GuiCtrlCreate(...
$Control2=GuiCtrlCreate(...
;...
$ControlN=Guictrlcreate(...

While 1
[COLOR="Green"][B]	$nMsg = GUIGetMsg()
	Switch $nMsg[/B][/COLOR]
		Case $Control1
			_Action1()
		Case $Control2
			_Action2()
		Case $Control3
			_Action3()
		Case $Control4
			_Action4()
		Case $Control5
			_Action5()
WEnd
Mit dem GUIOnEventMode sieht es z.B. so aus:

Code:
$GUI=GuiCreate(...
$Control1=GuiCtrlCreate(...
$Control2=GuiCtrlCreate(...
;...
$ControlN=Guictrlcreate(...
[COLOR="Green"][B]
For $i = $Control1 To $ControlN
	GUICtrlSetOnEvent($i, '_Control_EVENT')
Next[/B][/COLOR]

While 1
	sleep(10)
Wend

Func _Control_Event()
[COLOR="Green"]	[B]Switch @GUI_CtrlId[/B][/COLOR]
		Case $Control1
			_Action1()
		Case $Control2
			_Action2()
		Case $Control3
			_Action3()
		Case $Control4
			_Action4()
		Case $Control5
			_Action5()
		Case $Control6, $Control7, $Control8, $ControlN
			_ActionN()
	Endswitch
Endfunc
Die Codes sind im Aufbau fast genau gleich. Es kann für jedes Control eine eigene Funktion registriert werden, wie im Beispiel oben kann man aber auch für jedes Control dieselbe Funktion registrieren. Das spart uns sehr viel Platz und bewahrt die Übersichtlichkeit im Script.
Weitere Informationen dazu findet ihr [Only registered and activated users can see links. Click Here To Register...]

Erstellen wir uns jetzt eine GUI mit ein paar Buttons.
Das Bild ist 510px breit und 450px hoch, es wird zuerst erstellt, direkt nach GuiCreate. Andernfalls überdeckt es später Controls, die davor erstellt wurden. Das Bild dann noch deaktivieren.
Ein paar Buttons hinzufügen, ...

[Only registered and activated users can see links. Click Here To Register...]

und den Code mit F9 exportieren.
Die GUI verwendet den Style $WS_POPUP (=kein Rand) und $WS_EX_LAYERED (=transparent)

Code:
$FormEPVP = GUICreate("EPVP", 510, 450, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
Die Größe der GUI sollte der Größe des Bildes entsprechen.

Die While Schleife bauen wir dann um, so wie oben beschrieben und registrieren die Controls.

Nach dem alle Controls erstellt wurden, machen wir den grünen Bildhintergrund transparent mit:
Code:
_WinAPI_SetLayeredWindowAttributes($FormEPVP,0x0CFF00)
[Only registered and activated users can see links. Click Here To Register...]

So. Jetzt steht das da in der Mitte vom Desktop. Wir wollen die GUI aber auch verschieben können!

Dazu benötigen wir diese Funktion ([Only registered and activated users can see links. Click Here To Register...]):
Code:
Func _GUIDrag()
	Local $hGUI = @GUI_WinHandle
	Local $aCurInfo = GUIGetCursorInfo($hGUI)
     If $aCurInfo[4] = 0 Then ; Mouse not over a control
	DllCall("user32.dll", "int", "ReleaseCapture")
	_SendMessage($hGUI, $WM_NCLBUTTONDOWN, $HTCAPTION, 0)
     EndIf
EndFunc   ;==>_GUIDrag
Code:
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, '_GUIDrag')
Bedeutet, wenn die linke Maustaste nach unten gedrückt wird (auf die GUI), wird die Funktion _GUIDrag aufgerufen. Diese Funktion sorgt dafür, dass wir die Popup GUI verschieben können.

Es funktioniert alles gut, aber wenn wir Windows+D (Desktop anzeigen) drücken, verschwindet unsere GUI.
Um das zu verhindern, prüfen wir mit _IsPressed, ob die beiden Tasten gedrückt wurden:

Code:
Func _RestoreOnDesktop()
	If _IsPressed('5B', $hUser32DLL) And _IsPressed(44, $hUser32DLL) Then
		GUISetState(@SW_HIDE, $FormEPVP)
		GUISetState(@SW_SHOW, $FormEPVP)
	EndIf
EndFunc   ;==>_RestoreOnDesktop
Die Funktion registrieren wir noch mit Adlibregister, damit alle 250ms auf diese Tastendrücke überprüft wird.

Fertig.

Das Script mit Kommentaren:

Code:
#cs ----------------------------------------------------------------------------

	AutoIt Version: 3.3.8.1
	Author:         Achat

	Script Function:
	Transparent GUI Example.

#ce ----------------------------------------------------------------------------

#RequireAdmin ; Damit wir ShellExecute benutzen können

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
#include <WinApi.au3>

Opt('GUIOnEventMode', 1) ;GUIOnEventMode aktivieren!

InetGet('http://i.epvpimg.com/gt6gd.gif',@ScriptDir&'\epvp.gif') ; Das Hintergrundbild herunterladen.

Global $hUser32DLL = DllOpen('user32.dll') ; DLL, die von _IsPressed benötigt wird, öffnen.

#region ### START Koda GUI section ### Form=
$FormEPVP = GUICreate("EPVP", 510, 450, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetFont(8, 400, 0, "Comic Sans MS")
$PicEPVP = GUICtrlCreatePic(@ScriptDir & "\epvp.gif", 0, 0, 510, 450)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button1 = GUICtrlCreateButton("OffTopic", 64, 96, 105, 25)
GUICtrlSetFont(-1, 10, 400, 0, "Arial Black")
$Button2 = GUICtrlCreateButton("News", 343, 96, 105, 25)
GUICtrlSetFont(-1, 10, 400, 0, "Arial Black")
$Button3 = GUICtrlCreateButton("AutoIt", 63, 163, 105, 25)
GUICtrlSetFont(-1, 10, 400, 0, "Arial Black")
$Button4 = GUICtrlCreateButton("UserCP", 343, 163, 105, 25)
GUICtrlSetFont(-1, 10, 400, 0, "Arial Black")
$Button5 = GUICtrlCreateButton("X", 488, 8, 17, 17)
GUISetState(@SW_SHOW)
#endregion ### END Koda GUI section ###

_WinAPI_SetLayeredWindowAttributes($FormEPVP, 0x0CFF00) ; Bildhintergrund transparent machen.

; GUI Events registrieren
GUISetOnEvent($GUI_EVENT_CLOSE, '_Exit') ; Wenn  Taskleiste -> Rechtsklick -> Fenster schließen -> Funktion _Exit.
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, '_GUIDrag') ; Wenn Linksklick auf die GUI -> Funktion _GUIDrag aufrufen.

; Control Events registrieren
For $i = $Button1 To $Button5
	GUICtrlSetOnEvent($i, '_Control_Event')
Next

AdlibRegister('_RestoreOnDesktop') ; Ruft die Funktion _RestoreOnDesktop alle 0.25 Sekunden auf. Falls wir Win+D drücken (Desktop anzeigen), stellt sich die GUI automatisch wieder in den Vordergrund.

; Nichts tun, damit Programm nicht ausgeht.
While 1
	Sleep(10)
WEnd

;Funktion, die beim Klick auf ein Control eine Aktion ausführt.
Func _Control_Event()
	Switch @GUI_CtrlId ;@GUI_CtrlId = ID des zuletzt geklickten Controls.
		Case $Button5
			Exit
		Case $Button1
			ShellExecute('http://www.elitepvpers.com/forum/off-topic/')
		Case $Button2
			ShellExecute('http://www.elitepvpers.com/forum/gaming-news/')
		Case $Button3
			ShellExecute('http://www.elitepvpers.com/forum/autoit/')
		Case $Button4
			ShellExecute('http://www.elitepvpers.com/forum/usercp.php')
	EndSwitch
EndFunc   ;==>_Control_Event

;Verschiebt unsere GUI
Func _GUIDrag()
	Local $hGUI = @GUI_WinHandle
	Local $aCurInfo = GUIGetCursorInfo($hGUI)
	If $aCurInfo[4] = 0 Or $aCurInfo[4] = $PicEPVP Then ; Maus nicht über einem Control / Maus über dem Bild (auch transparenter Bereich).
		DllCall("user32.dll", "int", "ReleaseCapture")
		_SendMessage($hGUI, $WM_NCLBUTTONDOWN, $HTCAPTION, 0)
	EndIf
EndFunc   ;==>_GUIDrag

;Falls wir Win+D drücken, um zum Desktop zu wechseln, verhindert diese Funktion, dass die GUI versteckt wird.
Func _RestoreOnDesktop()
	If _IsPressed('5B', $hUser32DLL) And _IsPressed(44, $hUser32DLL) Then ; Wenn die Taste Windows und D gedrückt ist.
		GUISetState(@SW_HIDE, $FormEPVP)
		GUISetState(@SW_SHOW, $FormEPVP)
	EndIf
EndFunc   ;==>_RestoreOnDesktop

;Beenden
Func _Exit()
	DllClose($hUser32DLL) ; DLL, die von _IsPressed benötigt wird, schließen.
	Exit
EndFunc   ;==>_Exit
Fragen/Anregungen/Lob/Kritik/etc. sind immer willkommen. ;)

MfG
03/15/2013 17:53 Croco™#2
Vielen dank hab schon lange auf so etwas gewartet ;)
Aber mal ne Frage. Irre ich mich oder könnte man das Popup nicht einfach mit $WS_EX_CONTROLPARENT bewegen ?
03/15/2013 17:56 Achat#3
Bitte sehr ;)

Quote:
Originally Posted by Croco™ View Post
$WS_EX_CONTROLPARENT
Dein Fenster muss dann ein Child sein. Außerdem würde diese Lösung bestimmt im autoit wiki stehen (link im 1. Post), wenn es funktionieren würde.

MfG
03/15/2013 18:01 Croco™#4
Edit:Es funktioniert auch wie ich es gesagt habe:
03/15/2013 18:09 Achat#5
Code:
$FormEPVP = GUICreate("EPVP", 510, 450, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED,$WS_EX_CONTROLPARENT))
Funktioniert :)

Du kannst dort aber nicht die Maustaste wählen
Code:
$GUI_EVENT_PRIMARYDOWN
$GUI_EVENT_PRIMARYUP
$GUI_EVENT_SECONDARYDOWN
$GUI_EVENT_SECONDARYUP
MfG
03/15/2013 18:15 Croco™#6
Ein Nachteil muss es ja geben ;)
Aber wenn es einem wichtig ist hat er ja dein Tutorial !