﻿#include-once
#include <AutoItConstants.au3>
#include <GDIPlus.au3>
#include <StructureConstants.au3>
#include <WinAPIConv.au3>
#include <WinAPIGdi.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPIGdiInternals.au3>
#include <WinAPISysInternals.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>
#include <WinAPIvkeysConstants.au3>

OnAutoItExitRegister('_GuiCtrlVolume_Exit')
#cs
	Array-Description: $__g_ahGuiCtrlVolume_Gui[index][column]
	index: Number of the Volume-Controls
	column:
	0 = hwnd
	1 = prev WindowProc
	2 = Volume/Mute (Bits0-6: 0...100%, Bit7: Mute true/false)
	3 = TextColor (RGB)
	4 = BkColor (RGB)
	5 = Function, that call by control changes
#ce
Global $__g_ahGuiCtrlVolume_Gui[0][6]
Global $__g_hGuiCtrlVolume_ProcNew = DllCallbackRegister('_GuiCtrlVolume_Proc', 'ptr', 'hwnd;uint;long;ptr')

Global Const $__g_iGuiCtrlVolume_AppDPI = RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'AppliedDPI')
Global Const $__g_sGuiCtrlVolume_Version = '1.1.0.0'
Global Const $__g_sGuiCtrlVolume_Date = '2018/07/19 17:30:00'

_GDIPlus_Startup()
; The both Mute-Images (PNG-Files), at the end of this script, are converted as Base64-String.
; These Images has been developed by "The Oxygen Team" under the "GNU Lesser General Public License".
Global $__g_ahGuiCtrlVolumeBitmap[2] = [ _
		_GDIPlus_BitmapCreateFromMemory(_GuiCtrlVolume_speaker2()), _
		_GDIPlus_BitmapCreateFromMemory(_GuiCtrlVolume_speaker1())]

; Hinweis!
; Die Beschreibungen der Funktionen sind auf deutsch, weil mein englisch dafuer zu schlecht ist!

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_Exit
; Description ...: Wird beim beenden des Scripts aufgerufen (zum freigeben der Ressourcen)
; Syntax ........: _GuiCtrlVolume_Exit()
; Parameters ....: None
; Return values .: None
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_Exit()
	Local $iCount = UBound($__g_ahGuiCtrlVolume_Gui)
	If $iCount > 0 Then
		For $i = 0 To $iCount - 1
			_WinAPI_SetWindowLong($__g_ahGuiCtrlVolume_Gui[$i][0], $GWL_WNDPROC, $__g_ahGuiCtrlVolume_Gui[$i][1])
		Next
	EndIf
	DllCallbackFree($__g_hGuiCtrlVolume_ProcNew)
	_GDIPlus_BitmapDispose($__g_ahGuiCtrlVolumeBitmap[0])
	_GDIPlus_BitmapDispose($__g_ahGuiCtrlVolumeBitmap[1])
	_GDIPlus_Shutdown()
EndFunc   ;==>_GuiCtrlVolume_Exit

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_Create
; Description ...: Hiermit wird das Volume-Control erstellt. Man kann die Parameter bereits hier mitgeben oder spaeter ueber
;                  die anderen Funktionen festlegen. Das Control ist immer 150x50 Pixel gross. Man kann lediglich die Position
;                  bestimmen, an der es erstellt wird.
; Syntax ........: _GuiCtrlVolume_Create($iLeft, $iTop[, $iVolume = 100[, $iColor = -1[, $iBkColor = -1[, $sFunction = '']]]])
; Parameters ....: $iLeft               - Position (links), an der das Volume-Control erstellt wird
;                  $iTop                - Position (oben), an der das Volume-Control erstellt wird
;                  $iVolume             - [optional] Lautstaerkewert  (Bits0-6 in Prozent und Bit7 Mute true/false). Default ist 100 und false.
;                  $iColor              - [optional] Textfarbe (RGB). Default ist -1 (invertierte Hintergrundfarbe).
;                  $iBkColor            - [optional] Hintergrundfarbe (RGB). Default ist -1 (Farbe des Fensters).
;                  $sFunction           - [optional] Funktion, die bei einer Aenderung aufgerufen wird. Default ist '' (Script-Lautstaerke).
; Return values .: Im Erfolgsfall wird die Control-ID des Pic-Controls zurueckgegeben (wird zum Aufruf der anderen Funktionen benoetigt),
;                  ansonsten ist @error = 1, wenn das Pic-Control nicht erstellt werden konnte
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_Create($iLeft, $iTop, $iVolume = 100, $iColor = -1, $iBkColor = -1, $sFunction = '')
	Local $iCount, $iColumns, $idPic, $hPic, $hWnd
	$iCount = UBound($__g_ahGuiCtrlVolume_Gui) + 1
	$iColumns = UBound($__g_ahGuiCtrlVolume_Gui, $UBOUND_COLUMNS)
	ReDim $__g_ahGuiCtrlVolume_Gui[$iCount][$iColumns]
	$idPic = GUICtrlCreatePic('', $iLeft, $iTop, 150, 50)
	If $idPic = 0 Then Return SetError(1, 0, False)
	$hWnd = GUICtrlGetHandle($idPic)
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][0] = $hWnd
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][1] = _WinAPI_SetWindowLong($hWnd, $GWL_WNDPROC, DllCallbackGetPtr($__g_hGuiCtrlVolume_ProcNew))
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][2] = $iVolume
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][3] = $iColor
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][4] = $iBkColor
	$__g_ahGuiCtrlVolume_Gui[$iCount - 1][5] = IsFunc($sFunction) ? $sFunction : Execute($sFunction)
	_GuiCtrlVolume_SetVolumeGraphic($iCount - 1)
	Return $idPic
EndFunc   ;==>_GuiCtrlVolume_Create

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_GetVolume
; Description ...: Liest den Lautstaerkewert des Volume-Controls aus
; Syntax ........: _GuiCtrlVolume_GetVolume($idVolume)
; Parameters ....: $idVolume            - die Control-ID von _GuiCtrlVolume_Create().
; Return values .: Im Erfolgsfall den Lautstaerkewert, ansonsten
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_GetVolume($idVolume)
	Local $hWnd, $iIndex
	$hWnd = GUICtrlGetHandle($idVolume)
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd)
	If @error Then Return SetError(@error, 0, False)
	Return $__g_ahGuiCtrlVolume_Gui[$iIndex][2]
EndFunc   ;==>_GuiCtrlVolume_GetVolume

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_SetColor
; Description ...: Hiermit kann man die Text- und/oder die Hintergrundfarbe festlegen
; Syntax ........: _GuiCtrlVolume_SetColor($idVolume[, $iColor = -1[, $iBkColor = -1]])
; Parameters ....: $idVolume            - die Control-ID von _GuiCtrlVolume_Create().
;                  $iColor              - [optional] Textfarbe (RGB). Default ist -1 (invertierte Hintergrundfarbe).
;                  $iBkColor            - [optional] Hintergrundfarbe (RGB). Default ist -1 (Farbe des Fensters).
; Return values .: Im Erfolgsfall "True", ansonsten "False" und
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_SetColor($idVolume, $iColor = -1, $iBkColor = -1)
	Local $hWnd, $iIndex
	$hWnd = GUICtrlGetHandle($idVolume)
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd)
	If @error Then Return SetError(@error, 0, False)
	$__g_ahGuiCtrlVolume_Gui[$iIndex][3] = $iColor
	$__g_ahGuiCtrlVolume_Gui[$iIndex][4] = $iBkColor
	_GuiCtrlVolume_SetVolumeGraphic($iIndex)
	Return SetError(0, 0, True)
EndFunc   ;==>_GuiCtrlVolume_SetColor

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_SetFunction
; Description ...: Hiermit kann man die Funktion festlegen, die bei einer Aenderung aufgerufen werden soll
; Syntax ........: _GuiCtrlVolume_SetFunction($idVolume[, $sFunction = ''])
; Parameters ....: $idVolume            - die Control-ID von _GuiCtrlVolume_Create().
;                  $sFunction           - [optional] Funktion, die bei einer Aenderung aufgerufen wird. Default ist '' (Script-Lautstaerke).
; Return values .: Im Erfolgsfall "True", ansonsten "False" und
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_SetFunction($idVolume, $sFunction = '')
	Local $hWnd, $iIndex
	$hWnd = GUICtrlGetHandle($idVolume)
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd)
	If @error Then Return SetError(@error, 0, False)
	$__g_ahGuiCtrlVolume_Gui[$iIndex][5] = IsFunc($sFunction) ? $sFunction : Execute($sFunction)
	Return SetError(0, 0, True)
EndFunc   ;==>_GuiCtrlVolume_SetFunction

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_SetVolume
; Description ...:
; Syntax ........: _GuiCtrlVolume_SetVolume($idVolume, $iVolume)
; Parameters ....: $idVolume            - die Control-ID von _GuiCtrlVolume_Create().
;                  $iVolume             - Lautstaerkewert (Bits0-6 in Prozent und Bit7 Mute true/false).
; Return values .: Im Erfolgsfall "True", ansonsten "False" und
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_SetVolume($idVolume, $iVolume)
	Local $hWnd, $iIndex
	$hWnd = GUICtrlGetHandle($idVolume)
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd)
	If @error Then Return SetError(@error, 0, False)
	$__g_ahGuiCtrlVolume_Gui[$iIndex][2] = $iVolume
	_GuiCtrlVolume_SetVolumeGraphic($iIndex)
	Return SetError(0, 0, True)
EndFunc   ;==>_GuiCtrlVolume_SetVolume

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_GetIndex
; Description ...: Wird nur intern verwendet, um anhand des Fensterhandle den Array-Index zu ermitteln
; Syntax ........: _GuiCtrlVolume_GetIndex($hWnd)
; Parameters ....: $hWnd                - das Handle vom Volume-Control.
; Return values .: Im Erfolgsfall den Array-Index, ansonsten
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_GetIndex($hWnd)
	If Not IsHWnd($hWnd) Then Return SetError(1)
	Local $iCount = UBound($__g_ahGuiCtrlVolume_Gui)
	If $iCount = 0 Then Return SetError(2)
	For $iIndex = 0 To $iCount - 1
		If $__g_ahGuiCtrlVolume_Gui[$iIndex][0] = $hWnd Then Return $iIndex
	Next
	Return SetError(3)
EndFunc   ;==>_GuiCtrlVolume_GetIndex

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_Remove
; Description ...: Wird nur intern verwendet, um bei einem GuiCtrlDelete aufzuraeumen
; Syntax ........: _GuiCtrlVolume_Remove($hWnd)
; Parameters ....: $hWnd                - das Handle vom Volume-Control.
; Return values .: Im Erfolgsfall "True", ansonsten "False" und
;                  @error: 1, wenn $hWnd kein Fensterhandle
;                          2, wenn im globalen Array keine Eintraege vorhanden sind
;                          3, wenn das Fensterhandle nicht im globalen Array vorhanden ist
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_Remove($hWnd)
	Local $iCount, $iColumns, $iIndex
	$iCount = UBound($__g_ahGuiCtrlVolume_Gui)
	$iColumns = UBound($__g_ahGuiCtrlVolume_Gui, $UBOUND_COLUMNS)
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd)
	If @error Then Return SetError(@error, 0, False)
	_WinAPI_SetWindowLong($__g_ahGuiCtrlVolume_Gui[$iIndex][0], $GWL_WNDPROC, $__g_ahGuiCtrlVolume_Gui[$iIndex][1])
	For $j = 0 To $iColumns - 1
		$__g_ahGuiCtrlVolume_Gui[$iIndex][$j] = $__g_ahGuiCtrlVolume_Gui[$iCount - 1][$j]
	Next
	ReDim $__g_ahGuiCtrlVolume_Gui[$iCount - 1][$iColumns]
	Return SetError(0, 0, True)
EndFunc   ;==>_GuiCtrlVolume_Remove

; #FUNCTION# ====================================================================================================================
; Name ..........: _WinAPI_MakePoint
; Description ...: Eine kleine Hilfsfunktion, um aus einem Longword (X/Y) eine POINT-Struktur zu erstellen
; Syntax ........: _WinAPI_MakePoint($iLong[, $iOut = 0])
; Parameters ....: $iLong               - Ein Longword mit X-/Y-Koordinaten (Low/High)
;                  $iOut                - [optional] 0 = POINT-Struktur, 1 = X (signed) und 2 = Y (signed)
; Return values .: Je nach $iOut-Wert eine POINT-Struktur oder ein Signed-Integer-Wert (X oder Y)
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _WinAPI_MakePoint($iLong, $iOut = 0)
	Local $tLong = DllStructCreate('long XY'), $tPoint = DllStructCreate($tagPOINT)
	Local $tShort = DllStructCreate('short X;short Y', DllStructGetPtr($tLong))
	$tLong.XY = $iLong
	$tPoint.X = $tShort.X
	$tPoint.Y = $tShort.Y
	Switch $iOut
		Case 0
			Return $tPoint
		Case 1
			Return $tShort.X
		Case 2
			Return $tShort.Y
	EndSwitch
EndFunc   ;==>_WinAPI_MakePoint

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_Proc
; Description ...: Die neue WindowProc, die dem Volume-Control bei "_GuiCtrlVolume_Create" zugewiesen wird.
; Syntax ........: _GuiCtrlVolume_Proc($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_Proc($hWnd, $iMsg, $wParam, $lParam)
	Local Const $WHEEL_DELTA = 120
	Local $iIndex, $hOldProc, $tMousePoint, $hChild, $iX, $iY
	$iIndex = _GuiCtrlVolume_GetIndex($hWnd) ; Get the Index of the Volume-Control
	$hOldProc = $__g_ahGuiCtrlVolume_Gui[$iIndex][1]
	Switch $iMsg
		Case $WM_DESTROY ; When deletes the Control (GUICtrlDelete)
			_GuiCtrlVolume_Remove($hWnd)
		Case $WM_NCHITTEST ; Test, which Volume-Control is under the Mouse
			$tMousePoint = _WinAPI_MakePoint($lParam) ; Create Point-Struct from Mouse-Position
			$hChild = _WinAPI_WindowFromPoint($tMousePoint) ; Get the Window (Volume-Control)
			_WinAPI_SetFocus($hChild) ; Set the focus to the Control under the Mouse
		Case $WM_MOUSEWHEEL ; A message even to the Parent-Window!
			$tMousePoint = _WinAPI_MakePoint($lParam) ; Create Point-Struct from Mouse-Position
			$hChild = _WinAPI_WindowFromPoint($tMousePoint) ; Get the Window (Volume-Control)
			$iIndex = _GuiCtrlVolume_GetIndex($hChild) ; Get the Index of the Volume-Control
			If @error Then Return True ; Dismiss the Message, when not over a Volume-Control (Parent-Window)
			$hOldProc = $__g_ahGuiCtrlVolume_Gui[$iIndex][1] ; Get previous WindowProc
			If Not BitAND($__g_ahGuiCtrlVolume_Gui[$iIndex][2], 0x80) Then ; Interpret the Message only when not muted
				$__g_ahGuiCtrlVolume_Gui[$iIndex][2] += _WinAPI_HiWord($wParam) / $WHEEL_DELTA * 5 ; 5% per wheel rotation
				If $__g_ahGuiCtrlVolume_Gui[$iIndex][2] < 0 Then $__g_ahGuiCtrlVolume_Gui[$iIndex][2] = 0 ; not below 0%
				If $__g_ahGuiCtrlVolume_Gui[$iIndex][2] > 100 Then $__g_ahGuiCtrlVolume_Gui[$iIndex][2] = 100 ; not above 100%
				_GuiCtrlVolume_SetVolumeGraphic($iIndex)
				_GuiCtrlVolume_CallFunction($iIndex)
			EndIf
		Case $WM_LBUTTONUP ; When the User clicked left on the Volume-Control
			$iX = _WinAPI_MakePoint($lParam, 1) ; X-Mouseposition
			$iY = _WinAPI_MakePoint($lParam, 2) ; Y-Mouseposition
			If _WinAPI_PtInRectEx($iX, $iY, 0, 2, 32, 34) Then ; when over the Mute-Image
				$__g_ahGuiCtrlVolume_Gui[$iIndex][2] = BitXOR($__g_ahGuiCtrlVolume_Gui[$iIndex][2], 0x80) ; Switch between muted and not muted
			Else
				$__g_ahGuiCtrlVolume_Gui[$iIndex][2] = Int(100 / _WinAPI_GetWindowWidth($hWnd) * $iX) ; Else change the Volume based on the Mouseposition
			EndIf
			_GuiCtrlVolume_SetVolumeGraphic($iIndex)
			_GuiCtrlVolume_CallFunction($iIndex)
		Case $WM_PAINT
			_GuiCtrlVolume_SetVolumeGraphic($iIndex)
	EndSwitch
	Return DllCall('user32.dll', 'lresult', 'CallWindowProc', 'ptr', $hOldProc, 'hwnd', $hWnd, 'uint', $iMsg, 'wparam', $wParam, 'lparam', $lParam)[0]
	; Bug in _WinAPI_CallWindowProc (https://autoit.de/index.php?thread/86028-mehrere-udfs-mit-windowproc-verketten/&postID=690695#post690695)
EndFunc   ;==>_GuiCtrlVolume_Proc

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_CallFunction
; Description ...: Hier wird entweder die Wave-Lautstaerke fuer das Script geaendert (Standard) oder die vorher registrierte
;                  Funktion aufgerufen. Wird nur intern verwendet (Aufruf von _GuiCtrlVolume_Proc)!
; Syntax ........: _GuiCtrlVolume_CallFunction($iIndex)
; Parameters ....: $iIndex              - der Index vom Array "$__g_ahGuiCtrlVolume_Gui"!
; Return values .: None
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_CallFunction($iIndex)
	Local $sFunction, $iValue, $bMute, $iVolume
	$sFunction = $__g_ahGuiCtrlVolume_Gui[$iIndex][5]
	$iValue = $__g_ahGuiCtrlVolume_Gui[$iIndex][2]
	$bMute = BitAND($iValue, 0x80) = 0x80
	$iVolume = $bMute ? 0 : BitAND($iValue, 0x7F)
	If IsFunc($sFunction) Then
		Call($sFunction, $iValue)
	Else
		SoundSetWaveVolume($iVolume)
	EndIf
EndFunc   ;==>_GuiCtrlVolume_CallFunction

; #FUNCTION# ====================================================================================================================
; Name ..........: _GuiCtrlVolume_SetVolumeGraphic
; Description ...: Hier wird die Grafik erstellt und in das Pic-Control gezeichnet
; Syntax ........: _GuiCtrlVolume_SetVolumeGraphic($iIndex)
; Parameters ....: $iIndex              - der Index vom Array "$__g_ahGuiCtrlVolume_Gui"!
; Return values .: None
; Author ........: Oscar (www.autoit.de)
; ===============================================================================================================================
Func _GuiCtrlVolume_SetVolumeGraphic($iIndex)
	Local $hWnd, $iVolume, $bMute, $iWidth, $iHeight, $hBitmap, $hGfxCtx, $hParent, $hDC, $iBkColor, $hBrush, $hPen
	Local $iColor, $iBkColor, $a, $b, $c, $alpha, $iVolumeCalc, $aPoints[4][2], $hGraphic
	Local $hVolBrush, $hVolFormat, $hVolFamily, $hVolFont, $tVolLayout, $hResize
	$hWnd = $__g_ahGuiCtrlVolume_Gui[$iIndex][0]
	$bMute = BitAND($__g_ahGuiCtrlVolume_Gui[$iIndex][2], 0x80) = 0x80
	$iVolume = $bMute ? 0 : BitAND($__g_ahGuiCtrlVolume_Gui[$iIndex][2], 0x7F)
	$iColor = $__g_ahGuiCtrlVolume_Gui[$iIndex][3]
	$iBkColor = $__g_ahGuiCtrlVolume_Gui[$iIndex][4]
	$iWidth = _WinAPI_GetWindowWidth($hWnd)
	$iHeight = _WinAPI_GetWindowHeight($hWnd)
	$hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
	$hGfxCtx = _GDIPlus_ImageGetGraphicsContext($hBitmap)
	$hParent = _WinAPI_GetParent($hWnd)
	If $iBkColor = -1 Then
		$hDC = _WinAPI_GetDC($hParent)
		$iBkColor = _WinAPI_GetBkColor($hDC) ; Hintergrundfarbe des Fensters ermitteln
		_WinAPI_ReleaseDC($hParent, $hDC)
	EndIf
	If $iColor = -1 Then $iColor = 0xFF000000 + BitXOR($iBkColor, 0xF0F0F0)
	_GDIPlus_GraphicsClear($hGfxCtx, 0xFF000000 + $iBkColor) ; die Bitmap mit der Hintergrundfarbe fuellen
	_GDIPlus_GraphicsSetSmoothingMode($hGfxCtx, 2)
	_GDIPlus_GraphicsSetCompositingQuality($hGfxCtx, 3)
	_GDIPlus_GraphicsSetTextRenderingHint($hGfxCtx, 4)
	$hVolBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $iColor) ; Farbe (ARGB) der Prozentzahl
	$hVolFormat = _GDIPlus_StringFormatCreate()
	_GDIPlus_StringFormatSetAlign($hVolFormat, 2) ; Schriftausrichtung = rechts (2)
	$hVolFamily = _GDIPlus_FontFamilyCreate('Tahoma') ; Schriftart
	$hVolFont = _GDIPlus_FontCreate($hVolFamily, 11 / $__g_iGuiCtrlVolume_AppDPI * 96, 0) ; Schriftgröße
	$tVolLayout = _GDIPlus_RectFCreate(36, 4, 46, 20) ; Left, Top, Width, Height
	$hResize = _GDIPlus_ImageResize($__g_ahGuiCtrlVolumeBitmap[$bMute], 32, 32)
	_GDIPlus_GraphicsDrawImage($hGfxCtx, $hResize, 0, 2) ; Lautsprecher-Icon anzeigen
	_GDIPlus_GraphicsDrawStringEx($hGfxCtx, $iVolume & '%', $hVolFont, $tVolLayout, $hVolFormat, $hVolBrush)
	_GDIPlus_FontDispose($hVolFont)
	_GDIPlus_FontFamilyDispose($hVolFamily)
	_GDIPlus_StringFormatDispose($hVolFormat)
	_GDIPlus_BrushDispose($hVolBrush)
	$hBrush = _GDIPlus_LineBrushCreate(0, 0, $iWidth, $iHeight, 0xFF448822, 0xFFAAFF99, 2)
	$hPen = _GDIPlus_PenCreate(0xFFAAAAAA, 1)
	$iWidth -= 1
	$iHeight -= 1
	$a = $iHeight - 8 ; Seite a und
	$b = $iWidth ; Seite b des rechtwinkligen Dreiecks sind bekannt
	$c = Sqrt(($a * $a) + ($b * $b)) ; Seite c berechnen
	$alpha = ACos(($a * $a - $b * $b - $c * $c) / (-2 * $b * $c)) ; Winkel alpha berechnen
	$iVolumeCalc = Int($iWidth / 100 * $iVolume) ; die Seite b des ausgefüllten Dreiecks berechnen
	$aPoints[0][0] = 3
	$aPoints[1][0] = 0
	$aPoints[1][1] = $iHeight
	$aPoints[2][0] = $iVolumeCalc
	$aPoints[2][1] = $iHeight
	$aPoints[3][0] = $iVolumeCalc
	$aPoints[3][1] = $iHeight - Int(Tan($alpha) * $iVolumeCalc)
	_GDIPlus_GraphicsFillPolygon($hGfxCtx, $aPoints, $hBrush) ; das Lautstärke-Dreieck ausfüllen
	$aPoints[1][0] = 0
	$aPoints[1][1] = $iHeight
	$aPoints[2][0] = $iWidth
	$aPoints[2][1] = $iHeight
	$aPoints[3][0] = $iWidth
	$aPoints[3][1] = 8
	_GDIPlus_GraphicsDrawPolygon($hGfxCtx, $aPoints, $hPen) ; den Rand um das Dreieck zeichnen
	$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
	_GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0)
	_GDIPlus_GraphicsDispose($hGraphic)
	_GDIPlus_PenDispose($hPen)
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_GraphicsDispose($hGfxCtx)
	_GDIPlus_BitmapDispose($hBitmap)
EndFunc   ;==>_GuiCtrlVolume_SetVolumeGraphic

; Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2015-09-19
; The both Mute-Images (PNG-Files) are converted as Base64-String.
; These Images has been developed by "The Oxygen Team" under the "GNU Lesser General Public License".

Func _GuiCtrlVolume_speaker1($bSaveBinary = False, $sSavePath = @ScriptDir)
	Local $speaker1
	$speaker1 &= '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'
	$speaker1 &= 'cMZ39wmyUQuG8DWJsSjef6qWdXSUL2toVPZ7LCcgZC4uLkL5pVSRlY6YyePx0ud7wGu0xB8sqpPnY83eo3WWHBfPsWzhR4ve8vX/ch+g4cAQedv7KSgtvXQz6eJFvwH9mHh6erotXryYuheKwq/gpu5AWG09cFOBmiUJyNlzQMFwWvlJTtsUZWU53GRjU/pxYryv7IvdwGhvlPuPwZUzZVuzWlvTB/prdoZlWXc6qFqzLFyvXMEbr46Fl7cncrcXKDiOkx8hys1n4ggIkkWlH6Qm+TY23sUvR07k5eh0aX2Ogb7QKh+3rZpOVYRKpZ2+o1vd9KQ8zdZ2+AQfnx8lOl1J/I0baWb+C/87/guNUERO1S95UAAAAABJRU5ErkJggg=='
	Local $bString = _WinAPI_Base64Decode($speaker1)
	If @error Then Return SetError(1, 0, 0)
	$bString = Binary($bString)
	If $bSaveBinary Then
		Local Const $hFile = FileOpen($sSavePath & "\speaker0.png", 18)
		If @error Then Return SetError(2, 0, $bString)
		FileWrite($hFile, $bString)
		FileClose($hFile)
	EndIf
	Return $bString
EndFunc   ;==>_GuiCtrlVolume_speaker1

Func _GuiCtrlVolume_speaker2($bSaveBinary = False, $sSavePath = @ScriptDir)
	Local $speaker2
	$speaker2 &= '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'
	$speaker2 &= 'nDghR0J50dXV5YbRVJTse6JkbTwlo9hfX/IClIyXEVL6F82MT5ycnFBcXAwfHx+NHDhy5MikpJQ2lDaPkNIOIqUpL0NKeeFpOYGwE4vFXPvlhZFSqoBpaTltHhbzKrScF/5gYmVlNS8wMFCL1zPiQgk46cFESQeTTa97MOFl5Gj2O8V9PiOq/NGMJCcjI+PNHs3ehLx1AP8Bu5RsSN2cIqIAAAAASUVORK5CYII='
	Local $bString = _WinAPI_Base64Decode($speaker2)
	If @error Then Return SetError(1, 0, 0)
	$bString = Binary($bString)
	If $bSaveBinary Then
		Local Const $hFile = FileOpen($sSavePath & "\speaker1.png", 18)
		If @error Then Return SetError(2, 0, $bString)
		FileWrite($hFile, $bString)
		FileClose($hFile)
	EndIf
	Return $bString
EndFunc   ;==>_GuiCtrlVolume_speaker2

Func _WinAPI_Base64Decode($sB64String)
	Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0)
	If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "")
	Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]")
	$aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0)
	If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "")
	Return DllStructGetData($bBuffer, 1)
EndFunc   ;==>_WinAPI_Base64Decode
