"Grafische" GUI-Buttons

  • Hallo,

    mit "Schrift auf Bild" habe ich vor einiger Zeit auch herumgespielt. Allerdings ging es dabei um die Gestaltung "grafischer" GUI-Buttons. In AU3 sieht das dann so aus:

    Demo.au3
    [autoit]

    #include <GuiConstantsEx.au3>
    #include "GUICtrlPushButton.au3"
    $hGUI = GUICreate("GDI+ colored Buttons", 300, 210)
    GUISetBkColor(0x404040)
    GUISetFont(10)

    [/autoit] [autoit][/autoit] [autoit]

    $idBtn0 = GUICtrlCreateButton("Einfarbig ($3D = 0)", 50, 20, 200)
    $hBM1 = _GUICtrlPushButton_CreateImage($idBtn0, "BF0000", "BFBF00", 0)
    $hBM2 = _GUICtrlPushButton_CreateImage($idBtn0, "Red", "Yellow", 0)
    $Ret = _GUICtrlPushButton_CreateImageList($idBtn0, $hBM1, $hBM2)

    [/autoit] [autoit][/autoit] [autoit]

    $idBtn1 = GUICtrlCreateButton("Erhaben ($3D = 1)", 50, 60, 200)
    $hBM1 = _GUICtrlPushButton_CreateImage($idBtn1, "006000|00A000", "Blue", 1)
    $hBM2 = _GUICtrlPushButton_CreateImage($idBtn1, "008000|00C000", "Red", 1)
    $Ret = _GUICtrlPushButton_CreateImageList($idBtn1, $hBM1, $hBM2)

    [/autoit] [autoit][/autoit] [autoit]

    $idBtn2 = GUICtrlCreateButton("Vertikal 3D ($3D = 2)", 50, 100, 200)
    $hBM1 = _GUICtrlPushButton_CreateImage($idBtn2, "404040|A0A0A0", "Blue", 2)
    $hBM2 = _GUICtrlPushButton_CreateImage($idBtn2, "606060|F0F0F0", "Green", 2)
    $hBM3 = _GUICtrlPushButton_CreateImage($idBtn2, "A0A0A0|404040", "Lime", 2)
    $Ret = _GUICtrlPushButton_CreateImageList($idBtn2, $hBM1, $hBM2, $hBM3)

    [/autoit] [autoit][/autoit] [autoit]

    $idBtn3 = GUICtrlCreateButton("Horizontal 3D ($3D = 3)", 50, 140, 200)
    $hBM1 = _GUICtrlPushButton_CreateImage($idBtn3, "606060|C0C0C0", "Yellow", 3)
    $hBM2 = _GUICtrlPushButton_CreateImage($idBtn3, "606060|F0F0F0", "606000", 3)
    GUICtrlSetData($idBtn3, "Deaktiviert ($3D = 3)")
    $hBM4 = _GUICtrlPushButton_CreateImage($idBtn3, "606060|A0A0A0", "606060", 3)
    $Ret = _GUICtrlPushButton_CreateImageList($idBtn3, $hBM1, $hBM2, Default, $hBM4)
    GUICtrlSetState(-1, $GUI_DISABLE)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetFont(9)
    $idCB1 = GUICtrlCreateCheckbox("Button aktivieren", 50, 170, 200)
    GUISetState()
    GUICtrlSetState($idCB1, $GUI_FOCUS)

    [/autoit] [autoit][/autoit] [autoit]

    While True
    Switch GUIGetMsg()
    Case $idCB1
    If GUICtrlRead($idCB1) = $GUI_CHECKED Then
    GUICtrlSetState($idBtn3, $GUI_ENABLE)
    Else
    GUICtrlSetState($idBtn3, $GUI_DISABLE)
    EndIf
    Case $GUI_EVENT_CLOSE
    ExitLoop
    EndSwitch
    WEnd
    Exit

    [/autoit]
    GUICtrlPushButton.au3
    [autoit]

    #include-once
    #include <Constants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <GuiButton.au3>
    #include <GuiImageList.au3>
    ; #INDEX# =======================================================================================================================
    ; Title .........: GuiCtrlPushButton
    ; AutoIt Version : 3.3.6.++
    ; Language ......: Deutsch
    ; Description ...: Zusätzliche Funktionen zum Erstellen von Buttonimages und einer ImageList für Pushbuttons
    ; Author(s) .....: Großvater (AutoIt.de)
    ; Dll(s) ........:
    ; ===============================================================================================================================

    [/autoit] [autoit][/autoit] [autoit]

    ; #CURRENT# =====================================================================================================================
    ;_GUICtrlPushButton_CreateImage
    ;_GUICtrlPushButton_CreateImageList
    ; ===============================================================================================================================

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GUICtrlPushButton_CreateImage
    ; Description ...: Erstellt eine Bitmap für einen GUI-Button
    ; Syntax.........: __GUICtrlPushButton_CreateImage($idBtn, $CB, [, $CT = Default [, $3D = Default [, $GC = Default]]])
    ; Parameters ....: $idBtn - ButtonID aus GUICtrlCreateButton()
    ; $CB - Hintergrundfarbe(n):
    ; 6-stelliger RGB-Hexwert ("RRGGBB") oder Name (xxxx) gemäß $COLOR_xxxx aus ColorConstants.au3.
    ; Zwei durch Pipe-Zeichen (|) getrennte Werte bestimmen die Start- und Zielfarbe eines Verlaufs.
    ; Für 3D = 9 muss CB den Pfad eines Bildes oder ein HBITMAP Handle enthalten.
    ; $CT - Textfarbe:
    ; 6-stelliger RGB-Hexwert ("RRGGBB") oder Name ("xxxx") wie $COLOR_xxxx aus ColorConstants.au3.
    ; Default: "000000" ("BLACK")
    ; $3D - "3D"-Effekt:
    ; |0 : einfarbig
    ; |1 : erhaben
    ; |2 : vertikaler "3D"-Verlauf
    ; |3 : horizontaler "3D"-Verlauf
    ; |9 : Hintergrundbild (CB enthält den Pfad oder das HBITMAP-Handle)
    ; Default: 0
    ; $GC - Gammakorrektur:
    ; |0 : nein
    ; |1 : ja
    ; Default: 0
    ; Return values .: Erfolg - HBITMAP-Handle der Bitmap
    ; Fehler - @error ist gesetzt,
    ; @extended enthält zusätzliche Informationen:
    ; |1 : Das Buttonhandle konnte nicht ermittelt werden,
    ; |2 : Das Control ist kein Pushbutton,
    ; |3 : GDIPlus ist nicht verfügbar.
    ; Author ........: Großvater (AutoIt.de)
    ; Modified.......:
    ; Remarks .......:
    ; Related .......: _GUICtrlPushButton_CreateImageList
    ; Link ..........:
    ; Example .......: Nein
    ; ===============================================================================================================================
    Func _GUICtrlPushButton_CreateImage($idBtn, $CB, $CT = Default, $3D = Default, $GC = Default)
    ; Windows Konstanten
    Local Const $SA_LEFT = 0, $SA_CENTER = 1, $SA_RIGHT = 2
    ; Defaultwerte
    Local Const $DEF_CT = "000000", $DEF_3D = 0, $DEF_LM = 1, $DEF_GC = 0
    ; Variablen
    Local $aResult, $Class, $Styles, $CB1, $CB2
    ; Radiosbuttons und Checkboxen
    Local $RCBUTTONS = BitOR($BS_CHECKBOX, $BS_RADIOBUTTON, $BS_AUTORADIOBUTTON)
    ; HWND des Buttons ermitteln
    Local $hBtn = GUICtrlGetHandle($idBtn)
    If $hBtn = 0 Then
    Return SetError(1, 1, 0)
    EndIf
    ; Class und Styles holen und prüfen
    $Class = _WinAPI_GetClassName($hBtn)
    $Styles = _WinAPI_GetWindowLong($hBtn, $GWL_STYLE)
    If $Class <> "Button" Or _
    BitXOR(BitAND($Styles, 0xF), $BS_GROUPBOX) = 0 Or _
    BitAND($Styles, $RCBUTTONS) > 1 Then
    Return SetError(1, 2, 0)
    EndIf
    ; Ggf. Defaultwerte für optionale Parameter setzen
    If $CT = Default Then $CT = $DEF_CT
    If $3D = Default Then $3D = $DEF_3D
    $3D = StringLeft($3D, 1)
    If Not StringInStr("01239", $3D) Then $3D = $DEF_3D
    If $GC = Default Then $GC = $DEF_GC
    $GC = StringLeft($GC, 1)
    If Not StringInStr("01", $GC) Then $GC = $DEF_GC
    If $3D < 4 Then
    If StringInStr($CB, "|") Then
    $aResult = StringSplit($CB, "|")
    $CB1 = $aResult[1]
    $CB2 = $aResult[2]
    Else
    $CB1 = $CB
    $CB2 = $CB
    EndIf
    If IsDeclared("COLOR_" & $CB1) Then
    $CB1 = "0xFF" & Hex(Eval("COLOR_" & $CB1), 6)
    Else
    $CB1 = "0xFF" & $CB1
    EndIf
    If IsDeclared("COLOR_" & $CB2) Then
    $CB2 = "0xFF" & Hex(Eval("COLOR_" & $CB2), 6)
    Else
    $CB2 = "0xFF" & $CB2
    EndIf
    EndIf
    If IsDeclared("COLOR_" & $CT) Then
    $CT = "0xFF" & Hex(Eval("COLOR_" & $CT), 6)
    Else
    $CT = "0xFF" & $CT
    EndIf
    ; Vefügbarkeit von GDIPlus prüfen
    If Not _GDIPlus_Startup() Then
    Return SetError(1, 3, 0)
    EndIf
    ; Buttonfont holen
    Local $hDC = _WinAPI_GetDC($hBtn)
    Local $hFont = _SendMessageA($hBtn, $WM_GETFONT)
    _WinAPI_SelectObject($hDC, $hFont)
    $aResult = DllCall($ghGDIPDll, "Int", "GdipCreateFontFromDC", "Handle", $hDC, "Ptr*", 0)
    $hFont = $aResult[2]
    _WinAPI_ReleaseDC($hBtn, $hDC)
    ; Größe des Buttons ermiteln
    $aResult = WinGetClientSize($hBtn)
    Local $W = $aResult[0]
    Local $H = $aResult[1]
    ; Buttontext holen
    Local $TX = GUICtrlRead($idBtn)
    ; GDI+ Bitmap erzeugen
    $aResult = DllCall($ghGDIPDll, "Int", "GdipCreateBitmapFromScan0", _
    "Int", $W, "Int", $H, "Int", 0, "Int", 0x26200A, "UInt", 0, "Ptr*", 0)
    Local $hBitmap = $aResult[6]
    ; Pointer auf den Grafikkontext holen
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    ; SmoothingMode auf "system default" setzen
    _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 0)
    If $3D < 4 Then
    ; Einen PathGradientBrush erzeugen
    Local $POINTS = DllStructCreate("Int [8]")
    DllStructSetData($POINTS, 1, $W - 1, 3)
    DllStructSetData($POINTS, 1, $W - 1, 5)
    DllStructSetData($POINTS, 1, $H - 1, 6)
    DllStructSetData($POINTS, 1, $H - 1, 8)
    $aResult = DllCall($ghGDIPDll, "Int", "GdipCreatePathGradientI", _
    "Ptr", DllStructGetPtr($POINTS), "Int", 4, "Int", 0, "Handle*", 0)
    Local $hBrush = $aResult[4]
    ; Start- und Zielfarbe
    If $3D = 0 Then $CB2 = $CB1
    ; PresetBlend setzen
    Local $COLORS = DllStructCreate("UInt [3]")
    DllStructSetData($COLORS, 1, $CB1, 1)
    DllStructSetData($COLORS, 1, $CB2, 2)
    Local $RELINT = DllStructCreate("Float [3]")
    DllStructSetData($RELINT, 1, 0.0, 1)
    DllStructSetData($RELINT, 1, 1.0, 2)
    DllCall($ghGDIPDll, "Int", "GdipSetPathGradientPresetBlend", _
    "Handle", $hBrush, "Ptr", DllStructGetPtr($COLORS), "Ptr", DllStructGetPtr($RELINT), "Int", 2)
    ; FocusScales setzen
    Local $DH = $H / 4
    Local $xScale, $yScale
    Switch $3D
    Case 1
    $xScale = ($W - $DH) / $W
    $yScale = ($H - $DH) / $H
    Case 2
    $xScale = 1
    $yScale = 0
    Case 3
    $xScale = 0
    $yScale = 1
    Case Else
    $xScale = 0
    $yScale = 0
    EndSwitch
    DllCall($ghGDIPDll, "Int", "GdipSetPathGradientFocusScales", _
    "Handle", $hBrush, "Float", $xScale, "Float", $yScale)
    ; Gammakorrektur setzen
    DllCall($ghGDIPDll, "Int", "GdipSetPathGradientGammaCorrection", _
    "Handle", $hBrush, "Int", $GC)
    ; Bitmap füllen
    _GDIPlus_GraphicsFillRect($hGraphics, 0, 0, $W, $H, $hBrush)
    ; Brush entsorgen
    _GDIPlus_BrushDispose($hBrush)
    ElseIf $3D = 9 Then
    ; Bitmap aus HBITMAP oder Datei erstellen
    Local $hBM
    If IsHWnd($CB) Then
    $hBM = _GDIPlus_BitmapCreateFromHBITMAP($CB, 0)
    Else
    $hBM = _GDIPlus_BitmapCreateFromFile($CB)
    EndIf
    ; Bitmap erstellen
    _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBM, 0, 0, $W, $H)
    ; Bitmap entsorgen
    _GDIPlus_ImageDispose($hBM)
    EndIf
    ; Beschriftung
    If $TX Then
    ; StringFormat-Objekt erzeugen
    Local $hFormat = _GDIPlus_StringFormatCreate(0x5404)
    ; Textfarbe
    Local $hBrush = _GDIPlus_BrushCreateSolid($CT)
    ; Horizontale Ausrichtung
    Local $HALIGN
    Switch ($Styles & $BS_CENTER)
    Case $BS_CENTER
    $HALIGN = $SA_CENTER
    Case $BS_RIGHT
    $HALIGN = $SA_RIGHT
    Case $BS_LEFT
    $HALIGN = $SA_LEFT
    Case Else
    $HALIGN = $SA_CENTER
    EndSwitch
    _GDIPlus_StringFormatSetAlign($hFormat, $HALIGN)
    ; Vertikale Ausrichtung
    Local $VALIGN
    Switch ($Styles & $BS_VCENTER)
    Case $BS_TOP
    $VALIGN = 0
    Case $BS_BOTTOM
    $VALIGN = 2
    Case Else
    $VALIGN = 1
    EndSwitch
    DllCall($ghGDIPDll, "Int", "GdipSetStringFormatLineAlign", _
    "Handle", $hFormat, "Int", $VALIGN)
    ; Renderqualität auf "system default" setzen
    DllCall($ghGDIPDll, "Int", "GdipSetTextRenderingHint", _
    "Handle", $hGraphics, "Int", 0)
    ; Rechteck für den Text setzen
    Local $RECTF = _GDIPlus_RectFCreate(0, 0, $W, $H)
    ; Text zeichnen
    $Ret = _GDIPlus_GraphicsDrawStringEx($hGraphics, $TX, $hFont, $RECTF, $hFormat, $hBrush)
    EndIf
    ; HBITMAP Handle aus der Bitmap erzeugen
    $hBM = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap, 0XFFFFFFFF)
    ; Ressourcen freigeben
    _GDIPlus_ImageDispose($hBitmap)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_GraphicsDispose($hGraphics)
    ; Shutdown GDI+
    _GDIPlus_Shutdown()
    ; Return HBITMAP
    Return $hBM
    EndFunc ;==>_GUICtrlPushButton_CreateImage

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GUICtrlPushButton_CreateImageList
    ; Description ...: Erstellt aus den übergebenen Images eine ImageList und weist sie dem Button zu
    ; Syntax.........: __GUICtrlPushButton_CreateImageList($Img1 [, $Img2 = Default [, $Img3 = Default, [ $Img4 = Default [, $Img5 = Default [, $Img6 = Default]]]]])
    ; Parameters ....: $idBtn - Button ID aus GUICtrlCreateButton()
    ; $Img1 - Bitmaps für die Buttonstati:
    ; .. http://msdn.microsoft.com/en-us/library/…28VS.85%29.aspx
    ; $Img6 enum PUSHBUTTONSTATES {
    ; PBS_NORMAL = 1,
    ; PBS_HOT = 2,
    ; PBS_PRESSED = 3,
    ; PBS_DISABLED = 4,
    ; PBS_DEFAULTED = 5,
    ; PBS_DEFAULTED_ANIMATING = 6, (Tablet PC)
    ; };
    ; Die Reihenfolge (Nummer) der $Img-Parameter bestimmt ihre Position in der ImageList und damit
    ; den zugehörigen Status. Wenn nur eine Bitmap übergeben wird, wird sie für alle Stati genutzt.
    ; Für fehlende Bitmaps wird die erste verwendet.
    ; Return values .: Erfolg - True
    ; Fehler - @error ist gesetzt,
    ; @extended enthält zusätzliche Informationen:
    ; |1 : Das Buttonhandle konnte nicht ermittelt werden,
    ; |2 : Das Control ist kein Pushbutton,
    ; Author ........: Großvater (AutoIt.de)
    ; Modified.......:
    ; Remarks .......: Die übergebenen Bitmaps werden nach dem Einstellen in die Imagelist per DeleteObject() entsorgt.
    ; Related .......: _GUICtrlPushButton_CreateImageList
    ; Link ..........:
    ; Example .......: Nein
    ; ===============================================================================================================================
    Func _GUICtrlPushButton_CreateImageList($idBtn, $Img1, $Img2 = Default, $Img3 = Default, $Img4 = Default, $Img5 = Default, $Img6 = Default)
    Local $aResult, $aImg, $hBtn, $hDC, $hIL, $Class, $Styles
    Local $I, $W, $H, $M
    ; Radiosbuttons und Checkboxen
    Local $RCBUTTONS = BitOR($BS_CHECKBOX, $BS_RADIOBUTTON, $BS_AUTORADIOBUTTON)
    ; HWND des Buttons ermitteln
    $hBtn = GUICtrlGetHandle($idBtn)
    If $hBtn = 0 Then
    Return SetError(1, 1, 0)
    EndIf
    ; Class und Styles holen und prüfen
    $Class = _WinAPI_GetClassName($hBtn)
    $Styles = _WinAPI_GetWindowLong($hBtn, $GWL_STYLE)
    If $Class <> "Button" Or _
    BitXOR(BitAND($Styles, 0xF), $BS_GROUPBOX) = 0 Or _
    BitAND($Styles, $RCBUTTONS) > 1 Then
    Return SetError(1, 2, 0)
    EndIf
    ; Größe des Buttons bestimmen
    $aResult = WinGetClientSize($hBtn)
    $W = $aResult[0]
    $H = $aResult[1]
    ; ImageList erzeugen
    If @NumParams > 2 Then
    If $Img2 = Default Then $Img2 = $Img1
    If $Img3 = Default Then $Img3 = $Img1
    If $Img4 = Default Then $Img4 = $Img1
    If $Img5 = Default Then $Img5 = $Img1
    If $Img6 = Default Then $Img6 = $Img1
    $M = 6
    Else
    $M = 1
    EndIf
    $hIL = _GUIImageList_Create($W, $H, 6, 0, $M , 0)
    For $I = 1 To $M
    _GUIImageList_Add($hIL, Eval("Img" & $I))
    Next
    ; ImageList dem Button zuweisen
    _GUICtrlButton_SetImageList($hBtn, $hIL, 4)
    ; Beschriftung des Buttons löschen
    GUICtrlSetData($idBtn, "")
    ; Bitmaps entsorgen
    For $I = 1 To 6
    _WinAPI_DeleteObject(Eval("Img" & $I))
    Next
    Return True
    EndFunc

    [/autoit]


    Ich habe das in zwei Funktionen gelöst, weil die Funktionsaufrufe meiner Meinung nach so übersichtlicher sind. Die Demo und die Kommentare in den Funktionsköpfen sollten die Möglichkeiten und die notwendigen Parameter ausreichend beschreiben. Falls es trotzdem Fragen gibt, werde ich sie gern beantworten. Und, wie immer, sollte ich eine ähnliche existierende Funktion übersehen haben, hat mir die Arbeit an meiner Umsetzung trotzdem Spaß gemacht.

    Viel Spaß damit!