Jump to content

Recommended Posts

Posted

I'm working on a dark mode version of Toolbars for GUIDarkTheme UDF and it's going very well.

The only problem that I am trying to figure out is how to add custom icons with the _GUICtrlToolbar_AddButton function. Ideally, I would like to try adding toolbar icons created from the Segoe Fluent Icons or Segoe MDL2 Assets icon sets. This way, the icons could easily support monochrome, dark mode, etc.

The _GUICtrlToolbar_AddButton makes no mention of using custom icons or adding an icon by handle or anything like that.

There are, however, functions related to ImageList of these buttons:

  • _GUICtrlToolbar_GetDisabledImageList - along with related *Set* function
  • _GUICtrlToolbar_GetHotImageList - along with related *Set* function
  • _GUICtrlToolbar_GetImageList - along with related *Set* function

 

From WinAPIConstants.au3 we have:

; Standard Icon Index Constants
Global Const $STD_CUT = 0
Global Const $STD_COPY = 1
Global Const $STD_PASTE = 2
Global Const $STD_UNDO = 3
Global Const $STD_REDOW = 4
Global Const $STD_DELETE = 5
Global Const $STD_FILENEW = 6
Global Const $STD_FILEOPEN = 7
Global Const $STD_FILESAVE = 8
Global Const $STD_PRINTPRE = 9
Global Const $STD_PROPERTIES = 10
Global Const $STD_HELP = 11
Global Const $STD_FIND = 12
Global Const $STD_REPLACE = 13
Global Const $STD_PRINT = 14

 

Would I essentially need to destroy those ImageLists and recreate the ImageLists to replace those specific Standard Icons?

If Yes, that is good. That would make sense and cover the standard icons that users may already be using in their AutoIt GUI scripts that have toolbars.

However, finding a way to add completely custom icons to the toolbar which are not related to those standard icons would also be important if possible.

This thread is all about making toolbars (ToolbarWindow32 class) great again! :)

The following example from @Nine should serve as a good starting point. Please note that the toolbar background fill color does not extend when the GUI is resized bigger. If anyone knows how to fix that, please let me know. Thank you.

; From Nine
#include <GUIConstants.au3>
#include <WinAPI.au3>
#include <StructureConstants.au3>
#include <GuiToolbar.au3>

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

Opt("MustDeclareVars", True)

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;"
Global Const $TBCDRF_NOBACKGROUND = 0x400000
Global Const $TBCDRF_HILITEHOTTRACK = 0x20000

Example()

Func Example()
    Local Enum $e_idNew = 1000, $e_idOpen, $e_idSave, $e_idHelp
    Local $hGUI = GUICreate("Toolbar", 600, 400, -1, -1, $WS_OVERLAPPEDWINDOW)
    GUISetBkColor(0x202020)
    Local $hToolbar = _GUICtrlToolbar_Create($hGUI)

    ; Set theme for toolbar. Should work on both Win10/11.
    ; This works well enough to not need to use WM_NOTIFY, but that gives us more control.
    _GUICtrlToolbar_SetWindowTheme($hToolbar, 'DarkMode')

    _GUICtrlToolbar_SetColorScheme($hToolbar, 0x383838, 0x383838)
    _GUICtrlToolbar_SetStyleTransparent($hToolbar, False) ; this can be useful, particularly without WM_NOTIFY

    _GUICtrlToolbar_AddBitmap($hToolbar, 1, -1, $IDB_STD_LARGE_COLOR)
    _GUICtrlToolbar_AddButton($hToolbar, $e_idNew, $STD_FILENEW)
    _GUICtrlToolbar_AddButton($hToolbar, $e_idOpen, $STD_FILEOPEN)
    _GUICtrlToolbar_AddButton($hToolbar, $e_idSave, $STD_FILESAVE)
    _GUICtrlToolbar_AddButtonSep($hToolbar, 20)
    _GUICtrlToolbar_AddButton($hToolbar, $e_idHelp, $STD_HELP)
    GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

    GUISetState()

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    _GUICtrlToolbar_Destroy($hToolbar)
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tTool = DllStructCreate($tagNMTBCUSTOMDRAW, $lParam)
    If _WinAPI_GetClassName($tTool.hWndFrom) <> "ToolbarWindow32" Or $tTool.Code <> $NM_CUSTOMDRAW Then Return $GUI_RUNDEFMSG
    If $tTool.dwDrawStage = $CDDS_PREPAINT Then
        Local $hBrush = _WinAPI_CreateSolidBrush(0x383838)
        Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left"))
        _WinAPI_FillRect($tTool.hdc, $tRect, $hBrush)
        _WinAPI_DeleteObject($hBrush)
        Return $CDRF_NOTIFYITEMDRAW
    ElseIf $tTool.dwDrawStage = $CDDS_ITEMPREPAINT And BitAND($tTool.uItemState, $CDIS_HOT) Then
        $tTool.clrHighlightHotTrack = BitAND($tTool.uItemState, $CDIS_SELECTED) ? 0x484848 : 0x606060
        Return $TBCDRF_HILITEHOTTRACK
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

Posted

Now, skipping ahead of myself for a moment here, let's assume that I am able to create these custom icons to replace the standard icons index while in dark mode.

The easiest way (I assume) for an already existing GUI script with toolbar (such as Helpfile toolbar examples) to benefit from this would be to add them as Local Const to override the Global Const and to retain the same value numbers:

; Standard Icon Index Constants (now in a dark mode function)
Local Const $STD_CUT = 0
Local Const $STD_COPY = 1
Local Const $STD_PASTE = 2
Local Const $STD_UNDO = 3
Local Const $STD_REDOW = 4
Local Const $STD_DELETE = 5
Local Const $STD_FILENEW = 6
Local Const $STD_FILEOPEN = 7
Local Const $STD_FILESAVE = 8
Local Const $STD_PRINTPRE = 9
Local Const $STD_PROPERTIES = 10
Local Const $STD_HELP = 11
Local Const $STD_FIND = 12
Local Const $STD_REPLACE = 13
Local Const $STD_PRINT = 14

 

Posted

I was just testing the helpfile script from the _GUICtrlToolbar_SetImageList page and that example script does almost everything that I was hoping for. Incredible example. That example covers modifying the 3 different ImageLists related to Toolbar controls.

So that shows that my initial idea is possible which is fantastic.

Now it really comes down to properly creating the Bitmaps to go into those ImageLists. I personally always get confused between Bitmap, hBitmap, and HBITMAP because I have made mistakes before based on those differences.

Posted (edited)

Does anyone know if we can get the value (eg. $STD_FILEOPEN) of the toolbar button being drawn within the WM_NOTIFY parameters? Or from the NMCUSTOMDRAW?

If yes, we may be able to avoid creating the bitmaps and messing with ImageLists and simply FillRect and DrawText the equivalent from Fluent font file by its unicode value.

Edited by WildByDesign
Posted

I was finally able to get a custom font icon to show on the toolbar which is neat. But I think I may be in way over my head. I have no idea how to make sure that the text fits perfectly (size) or centered vertically/horizontally. I'm kind of losing this battle. My GDI+ knowledge is exactly zero. I don't even know how to make the text white.

 

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

#include <GDIPlus.au3>

_GDIPlus_Startup()

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

Example()

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

    _GUICtrlToolbar_SetWindowTheme($hToolbar, 'DarkMode')

    _GUICtrlToolbar_SetColorScheme($hToolbar, 0x383838, 0x383838)
    _GUICtrlToolbar_SetStyleTransparent($hToolbar, False)

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

    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iW)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)     ;get the graphics context of the bitmap
    _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsClear($hBmpCtxt, 0xFFFFFFFF)
    _GDIPlus_GraphicsSetTextRenderingHint($hBmpCtxt, $GDIP_TEXTRENDERINGHINTANTIALIASGRIDFIT)
    _GDIPlus_GraphicsDrawString($hBmpCtxt, ChrW(0xE64E), 0, 0, "Segoe MDL2 Assets", 12)
    $hHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

    ; Create normal image list
    Local $hNormal = _GUIImageList_Create($iW, $iW)
    ;_GUIImageList_Add($hNormal, _WinAPI_CreateSolidBitmap($hGUI, 0xFF0000, $iW, $iW))
    _GUIImageList_Add($hNormal, $hHBMP)
    _GUIImageList_Add($hNormal, $hHBMP)
    _GUIImageList_Add($hNormal, $hHBMP)
    ;_GUIImageList_Add($hNormal, _WinAPI_CreateSolidBitmap($hGUI, 0x00FF00, $iW, $iW))
    ;_GUIImageList_Add($hNormal, _WinAPI_CreateSolidBitmap($hGUI, 0x0000FF, $iW, $iW))
    Local $hPrevImageList = _GUICtrlToolbar_SetImageList($hToolbar, $hNormal)

    ; Create disabled image list
    Local $hDisabled = _GUIImageList_Create($iW, $iW)
    _GUIImageList_Add($hDisabled, _WinAPI_CreateSolidBitmap($hGUI, 0xCCCCCC, $iW, $iW))
    _GUIImageList_Add($hDisabled, _WinAPI_CreateSolidBitmap($hGUI, 0xCCCCCC, $iW, $iW))
    _GUIImageList_Add($hDisabled, _WinAPI_CreateSolidBitmap($hGUI, 0xCCCCCC, $iW, $iW))
    _GUICtrlToolbar_SetDisabledImageList($hToolbar, $hDisabled)

    ; Create hot image list
    Local $hHot = _GUIImageList_Create($iW, $iW)
    _GUIImageList_Add($hHot, _WinAPI_CreateSolidBitmap($hGUI, 0x111111, $iW, $iW))
    _GUIImageList_Add($hHot, _WinAPI_CreateSolidBitmap($hGUI, 0x888888, $iW, $iW))
    _GUIImageList_Add($hHot, _WinAPI_CreateSolidBitmap($hGUI, 0xAAAAAA, $iW, $iW))
    _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)

    GUISetState(@SW_SHOW)

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

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

    _GDIPlus_GraphicsDispose($hBmpCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
EndFunc   ;==>Example

 

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...