- Offizieller Beitrag
Für meinen neuen MP3-Player brauche ich einen Lautstärkeregler. Der soll nicht einfach nur ein Standard-Slider sein, sondern so ein Lautstärke-Dreieck.
Und zur Übung (mein 1. Script mit Subclassing) habe ich das Ganze dann auch noch mittels "_WinAPI_SetWindowSubclass" bedienbar gemacht.
Vielleicht mag mal jemand drüberschauen, ob ich da nicht irgendwelche groben Schnitzer reingehauen habe.
Hier das kommentierte Script:
AutoIt
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <WinAPIConstants.au3>
#include <WinAPIShellEx.au3>
#include <WindowsConstants.au3>
Opt('GUIOnEventMode', 1)
OnAutoItExitRegister('OnAutoItExit')
_GDIPlus_Startup() ; GDI-Plus starten
Global $ahGuiCtrlVolumeBmp[2] = [_GDIPlus_BitmapCreateFromMemory(_speaker1()), _GDIPlus_BitmapCreateFromMemory(_speaker0())]
; Register DLL callback that will be used as window subclass procedure
Global $hGuiCtrlVolumeDll = DllCallbackRegister('_SubclassProc', 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr')
Global $pGuiCtrlVolumeDll = DllCallbackGetPtr($hGuiCtrlVolumeDll)
Global $iVolume = 100, $fMute = False
$hGui = GUICreate('Test', 320, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, '_CloseGui')
GUISetBkColor(0x000000)
$idVolume = GUICtrlCreatePic('', 200, 56, 110, 40)
GUISetState()
_GuiCtrlVolume_SetData($idVolume, $iVolume, $fMute)
; Install window subclass callback
_WinAPI_SetWindowSubclass($hGui, $pGuiCtrlVolumeDll, $idVolume, 0)
WinWaitClose($hGui)
Exit
Func OnAutoItExit()
_GDIPlus_BitmapDispose($ahGuiCtrlVolumeBmp[0])
_GDIPlus_BitmapDispose($ahGuiCtrlVolumeBmp[1])
_GDIPlus_Shutdown()
_WinAPI_RemoveWindowSubclass($hGui, $pGuiCtrlVolumeDll, $idVolume)
DllCallbackFree($hGuiCtrlVolumeDll)
EndFunc ;==>OnAutoItExit
Func _CloseGui()
GUIDelete($hGui)
EndFunc ;==>_CloseGui
Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData)
#forceref $pData
Local $aGuiInfo, $iWheel
$aGuiInfo = GUIGetCursorInfo($hWnd)
If Not @error Then
Switch $aGuiInfo[4] ; Ctrl-ID unter dem Mauszeiger
Case $iID ; wenn die Maus sich über dem Lautstärkeregler befindet, dann...
$aPos = ControlGetPos($hWnd, '', $iID) ; die Position des Pic-Controls holen
If $aGuiInfo[2] Then ; Wenn die linke Maustaste gedrückt wurde, dann...
Local $iX = $aGuiInfo[0], $iY = $aGuiInfo[1]
If $iX > $aPos[0] + 2 And $iX < $aPos[0] + 26 And $iY > $aPos[1] + 2 And $iY < $aPos[1] + 26 Then ; wenn auf das Lautsprecher-Icon geklickt wurde, dann...
$fMute = Not $fMute
_GuiCtrlVolume_SetData($iID, $iVolume, $fMute)
Else ; ansonsten (Mausklick irgendwo im Lautstärke-Dreieck)
$iVolume = Round(100 / $aPos[2] * ($iX - $aPos[0])) ; Lautstärke entsprechend berechnen
_GuiCtrlVolume_SetData($iID, $iVolume, $fMute)
EndIf
Do
$aGuiInfo = GUIGetCursorInfo($hWnd)
Until Not $aGuiInfo[2] ; warten, bis die linke Maustaste wieder losgelassen wird
Return
EndIf
Switch $iMsg
Case $WM_MOUSEWHEEL ; Mausrad auswerten
$iWheel = _WinAPI_HiWord($wParam) / 120 ; "1" = vorwärts und "-1" = rückwärts
$iVolume += $iWheel * 5 ; pro Mausrad-Drehung 5% vor oder zurück
If $iVolume > 100 Then $iVolume = 100
If $iVolume < 0 Then $iVolume = 0
$fMute = False
_GuiCtrlVolume_SetData($iID, $iVolume, $fMute)
EndSwitch
EndSwitch
EndIf
Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc ;==>_SubclassProc
Func _GuiCtrlVolume_SetData($idPic, $iVolume, $fMute = False)
Local $hParent = _WinAPI_GetParent(GUICtrlGetHandle($idPic)) ; das Fenster des Pic-Controls ermitteln
If Not IsHWnd($hParent) Then Return SetError(1, 0, 0)
If $iVolume > 100 Then $iVolume = 100
If $iVolume < 0 Then $iVolume = 0
If $fMute Then $iVolume = 0
Local $aPos = ControlGetPos($hParent, '', $idPic)
If @error Then Return SetError(2, 0, 0)
Local $hVolBmp = _GDIPlus_BitmapCreateFromScan0($aPos[2], $aPos[3])
Local $hVolCtxt = _GDIPlus_ImageGetGraphicsContext($hVolBmp)
_GDIPlus_GraphicsClear($hVolCtxt, 0xFF000000)
_GDIPlus_GraphicsSetSmoothingMode($hVolCtxt, 2)
_GDIPlus_GraphicsSetCompositingQuality($hVolCtxt, 3)
_GDIPlus_GraphicsSetTextRenderingHint($hVolCtxt, 4)
Local $hVolBrush = _GDIPlus_BrushCreateSolid(0xFFEEEEEE) ; Farbe (ARGB) der Prozentzahl
Local $hVolFormat = _GDIPlus_StringFormatCreate()
Local $hVolFamily = _GDIPlus_FontFamilyCreate('Tahoma') ; Schriftart
Local $hVolFont = _GDIPlus_FontCreate($hVolFamily, 10) ; Schriftgröße
Local $tVolLayout = _GDIPlus_RectFCreate(28, 4, 70, 20) ; Left, Top, Width, Height
_GDIPlus_GraphicsDrawImage($hVolCtxt, $ahGuiCtrlVolumeBmp[$fMute], 2, 2) ; Lautsprecher-Icon anzeigen
_GDIPlus_GraphicsDrawStringEx($hVolCtxt, $iVolume & '%', $hVolFont, $tVolLayout, $hVolFormat, $hVolBrush)
Local $hBrush = _GDIPlus_LineBrushCreate(0, 0, $aPos[2], $aPos[3], 0xFF448822, 0xFFAAFF99, 2)
Local $hPen = _GDIPlus_PenCreate(0xFFAAAAAA, 1)
$aPos[2] -= 1 ; Breite -= 1 damit die Umrandung noch in das Pic-Control passt
$aPos[3] -= 1 ; Höhe -= 1 damit die Umrandung noch in das Pic-Control passt
Local $a = $aPos[3] - 8, $b = $aPos[2] ; Seite a und Seite b des rechtwinkligen Dreiecks sind bekannt
Local $c = Sqrt(($a * $a) + ($b * $b)) ; Seite c berechnen
Local $alpha = ACos(($a * $a - $b * $b - $c * $c) / (-2 * $b * $c)) ; Winkel alpha berechnen
Local $iVolumeCalc = Int($aPos[2] / 100 * $iVolume) ; die Seite b des ausgefüllten Dreiecks berechnen
Local $aPoints[4][2]
$aPoints[0][0] = 3
$aPoints[1][0] = 0
$aPoints[1][1] = $aPos[3]
$aPoints[2][0] = $iVolumeCalc
$aPoints[2][1] = $aPos[3]
$aPoints[3][0] = $iVolumeCalc
$aPoints[3][1] = $aPos[3] - Int(Tan($alpha) * $iVolumeCalc)
_GDIPlus_GraphicsFillPolygon($hVolCtxt, $aPoints, $hBrush) ; das Lautstärke-Dreieck ausfüllen
$aPoints[1][0] = 0
$aPoints[1][1] = $aPos[3]
$aPoints[2][0] = $aPos[2]
$aPoints[2][1] = $aPos[3]
$aPoints[3][0] = $aPos[2]
$aPoints[3][1] = 8
_GDIPlus_GraphicsDrawPolygon($hVolCtxt, $aPoints, $hPen) ; den Rand um das Dreieck zeichnen
_GDIPlus_PenDispose($hPen)
_GDIPlus_BrushDispose($hBrush)
Local $hBMP = _GDIPlus_BitmapCreateDIBFromBitmap($hVolBmp) ; HBitmap von der Bitmap erstellen
_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hBMP)) ; und an das Pic-Control senden
_WinAPI_DeleteObject($hBMP)
_GDIPlus_GraphicsDispose($hVolCtxt)
_GDIPlus_BitmapDispose($hVolBmp)
_GDIPlus_FontDispose($hVolFont)
_GDIPlus_FontFamilyDispose($hVolFamily)
_GDIPlus_StringFormatDispose($hVolFormat)
_GDIPlus_BrushDispose($hVolBrush)
EndFunc ;==>_GuiCtrlVolume_SetData
;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2015-01-20
Func _speaker0($bSaveBinary = False, $sSavePath = @ScriptDir)
Local $speaker0
$speaker0 &= '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'
$speaker0 &= 'BjG/CRMAyLe3AEcAOTkilIqKqcFQu7v7i4CNnmBXswCvr/+yq6v/fIBxcbtIOTkePwkJEwAKAcMqZVlZNwCck5PBkYaG/gqQYAyqYJSgmJj+AGxfX5lIODgOAz8JGwAtHx8Db2MAY0p/c3PYjIAIgP+k4KmJfn7t8GFSUl/wBb8jDwAPAAEIAEo9PQBAMDAABWhaWl5+cXEA14Z6evRvYWHgo2BQUBzwBQ8DDwADDwAMAGVYWABgUUBRCmpaWkcwAGmAZVVVKmdXV38pDw8ADwAPAAIAYlNTAAiOhoZyOGNVVQA8ZlYyZA8ABABxAv/8AHEA//AhAP/gAAEA/8ADAP8AoAcAwAADMgCAYDOogAAhMABzMAB/MAGofwD4MAD+MAD/MQCqgDQAwDAA4DAA8PAEDvgwAHEFMAA='
$speaker0 = _WinAPI_Base64Decode($speaker0)
Local $tSource = DllStructCreate('byte[' & BinaryLen($speaker0) & ']')
DllStructSetData($tSource, 1, $speaker0)
Local $tDecompress
_WinAPI_LZNTDecompress($tSource, $tDecompress, 2462)
$tSource = 0
Local Const $bString = Binary(DllStructGetData($tDecompress, 1))
If $bSaveBinary Then
Local Const $hFile = FileOpen($sSavePath & "\kmixdocked_error-2.ico", 18)
If @error Then Return SetError(1, 0, 0)
FileWrite($hFile, $bString)
FileClose($hFile)
EndIf
Return $bString
EndFunc ;==>_speaker0
Func _speaker1($bSaveBinary = False, $sSavePath = @ScriptDir)
Local $speaker1
$speaker1 &= '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'
$speaker1 &= 'Pj4AP6CXl9bn4+NE/5RgYYSDg+IXwBC9vf+44AB0amsAvjovLx9vRyUgWn9MM4FgJAx9AEwyYY5RPaOlKFlKGXkLJ2PKAVkAS0tTs6qq47NQrKz/heALqWBUtgSwsGJJal5fmkYANhkhXkEbaHoASi8gXEAcGHIASCughk43TakIWE8B/Rc6LS0AABwNDQl7cXFxIKOamu6H4DuXjgCO/7Gqqv+YjwCP9l5QUW9BNwANFFc/FxY3NAADBlQ9FldqRQAlaoNONQmmWAZMn9cAACITEwA8AC4uDXNmZoaBAHR095aLi/+oAJ+f/3ptbdpbqEtNNvAFAPAFAPAFAA5MOxAvX0EdcAyDTjaPBA8ABgBRAEREAE8/PxNtAF9fl4d6evOCAHV19GVWVoJeCE9QBzUCNDQCAYAlMQABaEQjDwQDDwAOAGRXVwBjU0BTFmdXV1+wBWKAZFVUFFtMTfYBADU0AgBGOQ0APFU+EYwPAA8ADwBkUxRUAPAFAPAFAGVVRlUPAgwA////MwDxBTAAwDAAgPsA/gAg+QCAAG0yAAAAqnQwAHY2AIAwAPgwAIL8cAH+AGwA/zACBP+AMADAewD/4BvwAzEA8DQFMAA='
$speaker1 = _WinAPI_Base64Decode($speaker1)
Local $tSource = DllStructCreate('byte[' & BinaryLen($speaker1) & ']')
DllStructSetData($tSource, 1, $speaker1)
Local $tDecompress
_WinAPI_LZNTDecompress($tSource, $tDecompress, 2462)
$tSource = 0
Local Const $bString = Binary(DllStructGetData($tDecompress, 1))
If $bSaveBinary Then
Local Const $hFile = FileOpen($sSavePath & "\kmixdocked-2.ico", 18)
If @error Then Return SetError(1, 0, 0)
FileWrite($hFile, $bString)
FileClose($hFile)
EndIf
Return $bString
EndFunc ;==>_speaker1
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
Func _WinAPI_LZNTDecompress(ByRef $tInput, ByRef $tOutput, $iBufferSize)
$tOutput = DllStructCreate("byte[" & $iBufferSize & "]")
If @error Then Return SetError(1, 0, 0)
Local $aRet = DllCall("ntdll.dll", "uint", "RtlDecompressBuffer", "ushort", 0x0002, "struct*", $tOutput, "ulong", $iBufferSize, "struct*", $tInput, "ulong", DllStructGetSize($tInput), "ulong*", 0)
If @error Then Return SetError(2, 0, 0)
If $aRet[0] Then Return SetError(3, $aRet[0], 0)
Return $aRet[6]
EndFunc ;==>_WinAPI_LZNTDecompress
Alles anzeigen