Jump to content
Advert

DarkMode: Any way to add custom icons to Toolbar with _GUICtrlToolbar_AddButton?


Go to solution Solved by ahmet,

Recommended Posts

Posted

Special thanks to @ahmet for helping me with the goal of creating completely custom toolbar icons.

I have updated my example to use the proper technique for alpha toolbar icons from the solution. I have made the toolbar transparent as well just to show the transparency of the icons. Now with proper alpha, we can see the nice effects when clicking on the toolbar buttons.

#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiToolbar.au3>
#include <WinAPIGdi.au3>
#include <WindowsStylesConstants.au3>

#include <GDIPlus.au3>

; Initialize System DPI awareness
DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2)

Global Const $TBCDRF_USECDCOLORS = 0x800000

Global Const $tagNMTBCUSTOMDRAW = $tagNMHDR & ";dword dwDrawStage;handle hdc;" & $tagRECT & ";dword_ptr dwItemSpec;uint uItemState;lparam lItemlParam;" & _
        "ptr hbrMonoDither;ptr hbrLines;ptr hpenLines;dword clrText;dword clrMark;dword clrTextHighlight;dword clrBtnFace;dword clrBtnHighlight;dword clrHighlightHotTrack;" & _
        "long TextLeft;long TextTop;long TextRight;long TextBottom;int nStringBkMode;int nHLStringBkMode;int iListGap;"

_GDIPlus_Startup()

Example()

Func Example()
    ; Create GUI
    Local $hGUI = GUICreate("Toolbar Get/Set ImageList (v" & @AutoItVersion & ")", 600, 400, -1, -1, $WS_OVERLAPPEDWINDOW)
    GUISetBkColor(0x202020)
    Local $hToolbar = _GUICtrlToolbar_Create($hGUI)

    ;_GUICtrlToolbar_SetWindowTheme($hToolbar, 'DarkMode')

    _GUICtrlToolbar_SetColorScheme($hToolbar, 0x202020, 0x202020)
    _GUICtrlToolbar_SetStyleTransparent($hToolbar, True)

    ; get imagelist size
    ;Local $hImageList = _GUICtrlToolbar_GetImageList($hToolbar)
    ;Local $aSize = _GUIImageList_GetIconSize($hImageList)
    ;Local $iW = $aSize[0]
    ;Local $iH = $aSize[1]
    Local $iW = 48
    Local $iH = 48

    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW ,$iH , $GDIP_PXF32ARGB)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    Local $hDC = _GDIPlus_GraphicsGetDC($hGraphics)
    Local $hFont = _WinAPI_CreateFont(Round(32), 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Segoe MDL2 Assets')
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)
    _WinAPI_SetTextColor($hDC, _WinAPI_SwitchColor(0xFFFFFF))
    _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $iW, $iH)
    Local $iTextFlags = BitOR($DT_SINGLELINE, $DT_CENTER, $DT_NOCLIP, $DT_VCENTER)
    _WinAPI_DrawText($hDC, ChrW(0xE72B), $tRECT, $iTextFlags)
    _GDIPlus_GraphicsReleaseDC($hGraphics, $hDC)
    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_DeleteObject($hFont)
    Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    Local $hHBitmapBack = _WinAPI_Create32BitHBITMAP($hIcon, True)
    _WinAPI_DestroyIcon($hIcon)
    _GDIPlus_BitmapDispose($hBitmap)

    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW ,$iH , $GDIP_PXF32ARGB)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    Local $hDC = _GDIPlus_GraphicsGetDC($hGraphics)
    Local $hFont = _WinAPI_CreateFont(Round(32), 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Segoe MDL2 Assets')
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)
    _WinAPI_SetTextColor($hDC, _WinAPI_SwitchColor(0xFFFFFF))
    _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $iW, $iH)
    Local $iTextFlags = BitOR($DT_SINGLELINE, $DT_CENTER, $DT_NOCLIP, $DT_VCENTER)
    _WinAPI_DrawText($hDC, ChrW(0xE72A), $tRECT, $iTextFlags)
    _GDIPlus_GraphicsReleaseDC($hGraphics, $hDC)
    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_DeleteObject($hFont)
    Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    Local $hHBitmapForward = _WinAPI_Create32BitHBITMAP($hIcon, True)
    _WinAPI_DestroyIcon($hIcon)
    _GDIPlus_BitmapDispose($hBitmap)

    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW ,$iH , $GDIP_PXF32ARGB)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    Local $hDC = _GDIPlus_GraphicsGetDC($hGraphics)
    Local $hFont = _WinAPI_CreateFont(Round(32), 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Segoe MDL2 Assets')
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)
    _WinAPI_SetTextColor($hDC, _WinAPI_SwitchColor(0xFFFFFF))
    _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $iW, $iH)
    Local $iTextFlags = BitOR($DT_SINGLELINE, $DT_CENTER, $DT_NOCLIP, $DT_VCENTER)
    _WinAPI_DrawText($hDC, ChrW(0xE74A), $tRECT, $iTextFlags)
    _GDIPlus_GraphicsReleaseDC($hGraphics, $hDC)
    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_DeleteObject($hFont)
    Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphics)
    Local $hHBitmapUp = _WinAPI_Create32BitHBITMAP($hIcon, True)
    _WinAPI_DestroyIcon($hIcon)
    _GDIPlus_BitmapDispose($hBitmap)

    ; Create normal image list
    Local $hNormal = _GUIImageList_Create($iW, $iW, 5)
    _GUIImageList_Add($hNormal, $hHBitmapBack)
    _GUIImageList_Add($hNormal, $hHBitmapForward)
    _GUIImageList_Add($hNormal, $hHBitmapUp)
    _GUICtrlToolbar_SetImageList($hToolbar, $hNormal)

    ; Create disabled image list
    Local $hDisabled = _GUIImageList_Create($iW, $iW, 5)
    _GUIImageList_Add($hDisabled, $hHBitmapBack)
    _GUIImageList_Add($hDisabled, $hHBitmapForward)
    _GUIImageList_Add($hDisabled, $hHBitmapUp)
    _GUICtrlToolbar_SetDisabledImageList($hToolbar, $hDisabled)

    ; Create hot image list
    Local $hHot = _GUIImageList_Create($iW, $iW, 5)
    _GUIImageList_Add($hHot, $hHBitmapBack)
    _GUIImageList_Add($hHot, $hHBitmapForward)
    _GUIImageList_Add($hHot, $hHBitmapUp)
    _GUICtrlToolbar_SetHotImageList($hToolbar, $hHot)

    ; Add buttons
    Local Enum $idRed = 1000, $idGreen, $idBlue
    _GUICtrlToolbar_AddButton($hToolbar, $idRed, 0)
    _GUICtrlToolbar_AddButton($hToolbar, $idGreen, 1)
    _GUICtrlToolbar_AddButton($hToolbar, $idBlue, 2)

    ; Clean up bitmaps created from _WinAPI_Create32BitHBITMAP()
    _WinAPI_DeleteObject($hHBitmapBack)
    _WinAPI_DeleteObject($hHBitmapForward)
    _WinAPI_DeleteObject($hHBitmapUp)

    GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

    GUISetState(@SW_SHOW)

    ; Disable Blue button
    ;_GUICtrlToolbar_EnableButton($hToolbar, $idBlue, False)

    ; Loop until the user exits.
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    _GDIPlus_Shutdown()
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    Local $tTool = DllStructCreate($tagNMTBCUSTOMDRAW, $lParam)
    If $tTool.Code <> $NM_CUSTOMDRAW Then Return $GUI_RUNDEFMSG

    Local Static $iGuiWidth = WinGetClientSize($hWnd)[0]
    Local Static $iToolbarWidth = _WinAPI_GetWindowWidth($tTool.hWndFrom)

    Local $dwDrawStage = $tTool.dwDrawStage
    Local $sClass = _WinAPI_GetClassName($tTool.hWndFrom)
    Switch $sClass
        Case "ToolbarWindow32"
            ; resize toolbar only if toolbar covers full client width
            If $iToolbarWidth = $iGuiWidth Then
                Local $aSize = WinGetClientSize($hWnd)
                WinMove($tTool.hWndFrom, "", 0, 0, $aSize[0])
            EndIf
            Switch $dwDrawStage
                Case $CDDS_PREPAINT
                    Local $hBrush = _WinAPI_CreateSolidBrush(0x383838)
                    Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left"))
                    ;_WinAPI_FillRect($tTool.hdc, $tRect, $hBrush)
                    _WinAPI_DeleteObject($hBrush)
                    Return $CDRF_NOTIFYITEMDRAW

                Case $CDDS_ITEMPREPAINT
                    Local $iState = $tTool.uItemState

                    If BitAND($iState, $CDIS_HOT) Then
                        $tTool.clrText = 0xFFFFFF
                        $tTool.clrTextHighlight = 0xFFFFFF

                        Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left"))
                        Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0x6B6B6B)
                        Local $hOldPen = _WinAPI_SelectObject($tTool.hdc, $hPen)
                        Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($iState, $CDIS_SELECTED) ? 0x666666 : 0x383838)
                        Local $hObj = _WinAPI_SelectObject($tTool.hdc, $hBrush)
                        ;_WinAPI_InflateRect($tRect, 0, -2)
                        _WinAPI_RoundRect($tTool.hdc, $tRect, 6, 6)
                        _WinAPI_SelectObject($tTool.hdc, $hObj)
                        ;_WinAPI_SelectObject($tTool.hdc, $hOldPen)
                        _WinAPI_DeleteObject($hBrush)
                        _WinAPI_DeleteObject($hPen)

                        ; clear item state or else this will not work
                        $tTool.uItemState = Null

                        Return $TBCDRF_USECDCOLORS
                    EndIf

                    If BitAND($iState, $CDIS_CHECKED) Then
                        $tTool.clrText = 0xFFFFFF
                        $tTool.clrTextHighlight = 0xFFFFFF

                        Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left"))
                        Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0x6B6B6B)
                        Local $hOldPen = _WinAPI_SelectObject($tTool.hdc, $hPen)
                        Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($iState, $CDIS_SELECTED) ? 0x666666 : 0x454545)
                        Local $hObj = _WinAPI_SelectObject($tTool.hdc, $hBrush)
                        ;_WinAPI_InflateRect($tRect, 0, -2)
                        _WinAPI_RoundRect($tTool.hdc, $tRect, 6, 6)
                        _WinAPI_SelectObject($tTool.hdc, $hObj)
                        ;_WinAPI_SelectObject($tTool.hdc, $hOldPen)
                        _WinAPI_DeleteObject($hBrush)
                        _WinAPI_DeleteObject($hPen)

                        ; clear item state or else this will not work
                        $tTool.uItemState = Null

                        Return $TBCDRF_USECDCOLORS
                    EndIf

                    If Not BitAND($iState, $CDIS_DISABLED) Then
                        $tTool.clrText = 0xFFFFFF
                        $tTool.clrTextHighlight = 0xFFFFFF

                        Return $TBCDRF_USECDCOLORS
                    EndIf

            EndSwitch
        
        Case Else
            Return $GUI_RUNDEFMSG
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

Advert

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...