ioa747 Posted Saturday at 06:37 PM Posted Saturday at 06:37 PM (edited) _GUIImageList_AddGlyph a variation of _AddFontIconToImageList (Thanks to the @WildByDesign ) Creates a GDI+ rendered glyph from a font and adds it to an ImageList with supersampling and rotation support. I added some extras to try. 😍 expandcollapse popup; https://www.autoitscript.com/forum/topic/213857-_guiimagelist_addglyph/ ;---------------------------------------------------------------------------------------- ; Title...........: _GUIImageList_AddGlyph.au3 ; Description.....: Creates a GDI+ rendered glyph from a font and adds it to an ImageList with supersampling and rotation support. ; AutoIt Version..: 3.3.18.0 Mod: ioa747 Script Version: 0.3 ; Note............: Testet in Windows 11 Pro 25H2 Date:28/8/2026 ; Modification ...: https://www.autoitscript.com/forum/topic/139260-autoit-snippets/page/29/#findComment-1554342 ;---------------------------------------------------------------------------------------- ;~ #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <GUIConstantsEx.au3> #include <GuiImageList.au3> #include <GuiListView.au3> #include <GDIPlus.au3> #include <WinAPITHeme.au3> ; $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = -2 DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "int_ptr", -2) _Example() Func _Example() ; Initialize GDI+ _GDIPlus_Startup() Local $hGUI = GUICreate("Add Font Icons To ImageList", 600, 700) GUISetBkColor(0x000000) Local $iCSZ = 48 Local $hImageList = _GUIImageList_Create($iCSZ, $iCSZ, 5, 1) Local $aDataList[16][3] = [ _ ; id, sText, $iImageIndex [0, "Settings|Modify application settings", _GUIImageList_AddGlyph($hImageList, "Segoe UI Emoji", 0x26A0, $iCSZ, 0xFF41B310)], _ ; "Segoe UI Emoji", .Glyph = 0x26A0 ⚠ [0, "Home|Emoji with GlyphScale=65", _GUIImageList_AddGlyph($hImageList, "Segoe UI Emoji", 0x1F4BE, $iCSZ, 0xFF41B310, 0, 65)], _ ; "Segoe UI Emoji", .Glyph = 0x1F4BE 💾 [0, "Save|Save current project changes", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF0094FF)], _ ; "Segoe MDL2 Assets", .Glyph = 0xE74E ; Save [0, "1|A 90-degree rotation without flipping", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 1)], _ [0, "2|A 180-degree rotation without flipping", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 2)], _ [0, "3|A 270-degree rotation without flipping", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 3)], _ [0, "4|No rotation and a horizontal flip", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 4)], _ [0, "5|A 90-degree rotation followed by a horizontal flip", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 5)], _ [0, "6|A 180-degree rotation followed by a horizontal flip", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 6)], _ [0, "7|A 270-degree rotation followed by a horizontal flip", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFF69BDF9, 7)], _ [0, "50|GlyphScale", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 50)], _ [0, "60|GlyphScale", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 60)], _ [0, "70|GlyphScale", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 70)], _ [0, "80|GlyphScale (Default)", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 80)], _ [0, "90|GlyphScale", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 90)], _ [0, "100|GlyphScale", _GUIImageList_AddGlyph($hImageList, "Segoe MDL2 Assets", 0xE74E, $iCSZ, 0xFFFF6A00, 0, 100)] _ ] Local $idListView = GUICtrlCreateListView("Icon Name |Description", 20, 20, 560, 660, BitOR($GUI_SS_DEFAULT_LISTVIEW, $LVS_NOCOLUMNHEADER)) GUICtrlSetBkColor(-1, 0x202020) GUICtrlSetColor(-1, 0xFFFFFF) ; ImageList -> ListView _GUICtrlListView_SetImageList($idListView, $hImageList, 1) ; 1 = Small icon list Local $hLV = GUICtrlGetHandle($idListView) For $i = 0 To UBound($aDataList) - 1 $aDataList[$i][0] = GUICtrlCreateListViewItem($aDataList[$i][1], $idListView) _GUICtrlListView_SetItemImage($hLV, $i, $aDataList[$i][2]) Next ; Information: Get item rectangle Local $aRect = _GUICtrlListView_GetItemRect($idListview, 0) ConsoleWrite(StringFormat("Item Rectangle : [%d, %d, %d, %d]", $aRect[0], $aRect[1], $aRect[2], $aRect[3]) & @CRLF) GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup _GUIImageList_Destroy($hImageList) GUIDelete($hGUI) _GDIPlus_Shutdown() EndFunc ;==>_Example ; #FUNCTION# ==================================================================================================================== ; Name...........: _GUIImageList_AddGlyph ; Description ...: Creates a GDI+ rendered glyph from a font and adds it to an ImageList with supersampling and rotation support. ; Syntax.........: _GUIImageList_AddGlyph($hImageList, $sFontName, $iUnicodeDecimalOrHex[, $iSize = 32[, $iARGBColor = 0xFF000000[, $iRotateFlipType = 0]]]) ; Parameters ....: $hImageList - Handle to the ImageList control. ; $sFontName - Name of the font family (e.g., "Segoe MDL2 Assets", "Segoe UI Emoji"). ; $iUnicodeDecimalOrHex - Unicode code point (Decimal or Hex integer, e.g., 0xE74E or 0x1F60A). ; $iSize - [optional] Target icon size in pixels (Width & Height). Default is 32. ; $iARGBColor - [optional] Color of the glyph in ARGB format (0xAARRGGBB). Default is 0xFF000000 (Opaque Black). ; $iRotateFlipType - [optional] GDI+ RotateFlipType enumeration (0-7). Default is 0 ($GDIP_ROTATENONEFLIPNONE). ; $GDIP_RotateNoneFlipNone = 0 (Default) ; $GDIP_Rotate90FlipNone = 1 ; $GDIP_Rotate180FlipNone = 2 ; $GDIP_Rotate270FlipNone = 3 ; $GDIP_RotateNoneFlipX = 4 ; $GDIP_Rotate90FlipX = 5 ; $GDIP_Rotate180FlipX = 6 ; $GDIP_Rotate270FlipX = 7 ; $iGlyphScale - [optional] Font scale percentage relative to canvas size (1-100). Default is 80. ; Return values .: Success - The 0-based index of the added image in the ImageList. ; Failure - Returns index from _GUIImageList_Add or -1. ; Author ........: ioa747 ; Remarks .......: Requires _GDIPlus_Startup() to be called beforehand in your script. ; =============================================================================================================================== Func _GUIImageList_AddGlyph($hImageList, $sFontName, $iUnicodeDecimalOrHex, $iSize = 32, $iARGBColor = 0xFF000000, $iRotateFlipType = 0, $iGlyphScale = 80) Local $iRenderSize = $iSize * 2 Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iRenderSize, $iRenderSize) Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2) _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTCLEARTYPEGRIDFIT) Local $hBrush = _GDIPlus_BrushCreateSolid($iARGBColor) Local $hFamily = _GDIPlus_FontFamilyCreate($sFontName) Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * ($iGlyphScale / 100), 0, 2) Local $tLayout = _GDIPlus_RectFCreate(0, 0, $iRenderSize, $iRenderSize) Local $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) ; Surrogate Pairs for Unicode > 0xFFFF (Emojis, etc.) Local $sChar = "" If $iUnicodeDecimalOrHex > 0xFFFF Then Local $iCode = $iUnicodeDecimalOrHex - 0x10000 Local $iHigh = BitOR(0xD800, BitShift($iCode, 10)) Local $iLow = BitOR(0xDC00, BitAND($iCode, 0x3FF)) $sChar = ChrW($iHigh) & ChrW($iLow) Else $sChar = ChrW($iUnicodeDecimalOrHex) EndIf _GDIPlus_GraphicsDrawStringEx($hGraphics, $sChar, $hFont, $tLayout, $hFormat, $hBrush) ; Creation of final bitmap to $iSize and resampling (supersampling) Local $hFinalBitmap = _GDIPlus_BitmapCreateFromScan0($iSize, $iSize) Local $hFinalGraphics = _GDIPlus_ImageGetGraphicsContext($hFinalBitmap) _GDIPlus_GraphicsSetInterpolationMode($hFinalGraphics, $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC) _GDIPlus_GraphicsDrawImageRect($hFinalGraphics, $hBitmap, 0, 0, $iSize, $iSize) ; ROTATE / FLIP TRANSFORMATION If $iRotateFlipType Then _GDIPlus_ImageRotateFlip($hFinalBitmap, $iRotateFlipType) ; Conversion to Win32 HBITMAP Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hFinalBitmap) ; Addition to ImageList Local $iIndex = _GUIImageList_Add($hImageList, $hHBITMAP, 0) ; Cleanup _WinAPI_DeleteObject($hHBITMAP) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hFinalGraphics) _GDIPlus_BitmapDispose($hFinalBitmap) _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_BitmapDispose($hBitmap) Return $iIndex EndFunc ;==>_GUIImageList_AddGlyph Please, every comment is appreciated! leave your comments and experiences here! Thank you very much Edited Sunday at 06:29 AM by ioa747 update to v0.3 WildByDesign and argumentum 2 I know that I know nothing
argumentum Posted Saturday at 07:44 PM Posted Saturday at 07:44 PM 200% scale ioa747 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
WildByDesign Posted Saturday at 08:39 PM Posted Saturday at 08:39 PM 53 minutes ago, argumentum said: 200% scale Try to change: Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * 0.48, 0, 3) To: Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * 0.32, 0, 3) It seems that we may need to apply some DPI scaling to that value somehow. argumentum 1
WildByDesign Posted Saturday at 11:34 PM Posted Saturday at 11:34 PM It looks like I used the wrong measurement for _GDIPlus_FontCreate in my original script. Changing this: Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * 0.48, 0, 3) ; 3 - A unit is 1 point or 1/72 inch To this: Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * 0.90, 0, 2) ; 2 - A unit is 1 pixel This seems to be more appropriate across various DPI factors. argumentum and ioa747 2
ioa747 Posted Sunday at 06:08 AM Author Posted Sunday at 06:08 AM (edited) I added an optional $iGlyphScale parameter (1–100, default: 80) to the function signature. This allows fine-tuning the glyph size directly from the call, which is useful not only for handling different font families, but also for adapting to various UI themes and layouts where a custom padding or margin is required. I updated the first post with the new version. Thank you once again for the continuous feedback and support! Edited Sunday at 06:33 AM by ioa747 to GlyphScale WildByDesign and argumentum 2 I know that I know nothing
WildByDesign Posted Sunday at 11:29 AM Posted Sunday at 11:29 AM 5 hours ago, ioa747 said: I added an optional $iGlyphScale parameter (1–100, default: 80) to the function signature. I really like what you've done with this function. Adding GlyphScale is an excellent idea because of how different fonts have different padding and characteristics. Your function is fantastic and is quite powerful for giving users a modern experience. This can now be used quite easily for making changes to ImageLists during WM_DPICHANGED messages to always have sharp icons/images. The technique reminds me quite a lot of SVG since these modern fonts are also designed to scale quite well. It opens up the possibility to have custom, modern icons for toolbar buttons, tabs and so much more. It can also be used to make nice checkboxes that some of these fonts have. The possibilities are almost endless. Excellent work, as always. ioa747 1
ioa747 Posted 13 hours ago Author Posted 13 hours ago (edited) following the same philosophy to approach _GUICtrlSetGlyph (Renders a GDI+ font glyph and assigns it directly to a GUI control) because the function has all the extras flip/ rotate/ color/ size expandcollapse popup#include <GUIConstants.au3> #include <GDIPlus.au3> #include <WinAPISysWin.au3> _Example() Func _Example() _GDIPlus_Startup() Local $hGUI = GUICreate("GUICtrlSetGlyph Example", 400, 200) GUISetBkColor(0x002844) ; Button Control Local $idBtn1 = GUICtrlCreateButton(ChrW(0xE74E), 30, 40, 64, 64) GUICtrlSetFont ( -1, 40, 0, 0, "Segoe MDL2 Assets") ; usual way to set directly to the Button ;~ _GUICtrlSetGlyph($idBtn1, "Segoe MDL2 Assets", 0xE74E, 64, 0xFF0094FF) Local $idBtn2 = GUICtrlCreateButton("Save Icon", 120, 40, 64, 64) _GUICtrlSetGlyph($idBtn2, "Segoe MDL2 Assets", 0xE74E, 64, 0xFFFF00DC) Local $idBtn3 = GUICtrlCreateButton("", 210, 40, 64, 64) _GUICtrlSetGlyph($idBtn3, "Segoe MDL2 Assets", 0xE74E, 64, 0xFFFF6A00, 2) ; 180° Rotated Local $idPic1 = GUICtrlCreatePic("", 30, 120, 64, 64) ; Pic Control ?? _GUICtrlSetGlyph($idPic1, "Segoe MDL2 Assets", 0xE74E, 64, 0xFF41B310) Local $idIco1 = GUICtrlCreateIcon("shell32.dll", 7, 120, 120, 64, 64) _GUICtrlSetGlyph($idIco1, "Segoe MDL2 Assets", 0xE74E, 64, 0xFFFF00DC) Local $idIco2 = GUICtrlCreateIcon("shell32.dll", 7, 210, 120, 64, 64) _GUICtrlSetGlyph($idIco2, "Segoe MDL2 Assets", 0xE74E, 64, 0xFFFF6A00, 2) ; 180° Rotated GUISetState(@SW_SHOW) While GUIGetMsg() <> -3 WEnd _GDIPlus_Shutdown() EndFunc ;==>_Example ; #FUNCTION# ==================================================================================================================== ; Name...........: _GUICtrlSetGlyph ; Description ...: Renders a GDI+ font glyph and assigns it directly to a GUI control (Button, Pic, Icon). ; Syntax.........: _GUICtrlSetGlyph($idControl, $sFontName, $iUnicodeDecimalOrHex[, $iSize = 32[, $iARGBColor = 0xFF000000[, $iRotateFlipType = 0[, $iGlyphScale = 80]]]]) ; Parameters ....: $idControl - Control ID or HWND of the target control. ; $sFontName - Name of the font family (e.g., "Segoe MDL2 Assets", "Segoe UI Emoji"). ; $iUnicodeDecimalOrHex - Unicode code point (Decimal or Hex integer, e.g., 0xE74E or 0x1F60A). ; $iSize - [optional] Icon size in pixels (Width & Height). Default is 32. ; $iARGBColor - [optional] Color of the glyph in ARGB format (0xAARRGGBB). Default is 0xFF000000. ; $iRotateFlipType - [optional] GDI+ RotateFlipType enumeration (0-7). Default is 0 ($GDIP_ROTATENONEFLIPNONE). ; $iGlyphScale - [optional] Font scale percentage relative to canvas size (1-100). Default is 80. ; Return values .: Success - Returns the handle to the previously assigned HICON (or 0 if none). ; Failure - Returns 0 and sets @error. ; Author ........: ioa747 ; Remarks .......: Requires _GDIPlus_Startup() to be called beforehand in your script. ; =============================================================================================================================== Func _GUICtrlSetGlyph($idControl, $sFontName, $iUnicodeDecimalOrHex, $iSize = 32, $iARGBColor = 0xFF000000, $iRotateFlipType = 0, $iGlyphScale = 80) Local $hCtrl = GUICtrlGetHandle($idControl) If Not $hCtrl Then $hCtrl = $idControl Local $sClassName = _WinAPI_GetClassName($hCtrl) ConsoleWrite("$sClassName=" & $sClassName & @CRLF) Local $iMsg = 0 Local $iStyle = _WinAPI_GetWindowLong($hCtrl, -16) ; GWL_STYLE Switch $sClassName Case "Button" $iMsg = $BM_SETIMAGE If BitAND($iStyle, 0x0040) = 0 Then _WinAPI_SetWindowLong($hCtrl, -16, BitOR($iStyle, 0x0040)) ; BS_ICON EndIf Case "Static" $iMsg = $STM_SETIMAGE ; Remove SS_BITMAP (0x0E) and apply SS_ICON (0x03) + SS_REALSIZECONTROL (0x40) $iStyle = BitAND($iStyle, BitNOT(0x0E)) _WinAPI_SetWindowLong($hCtrl, -16, BitOR($iStyle, 0x0043)) Case Else Return SetError(1, 0, 0) EndSwitch ; Supersampling Canvas Setup (2x Size for crisp AA) Local $iRenderSize = $iSize * 2 Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iRenderSize, $iRenderSize) Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2) _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTCLEARTYPEGRIDFIT) Local $hBrush = _GDIPlus_BrushCreateSolid($iARGBColor) Local $hFamily = _GDIPlus_FontFamilyCreate($sFontName) Local $hFont = _GDIPlus_FontCreate($hFamily, $iRenderSize * ($iGlyphScale / 100), 0, 2) Local $tLayout = _GDIPlus_RectFCreate(0, 0, $iRenderSize, $iRenderSize) Local $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) ; Surrogate Pairs for Unicode > 0xFFFF Local $sChar = "" If $iUnicodeDecimalOrHex > 0xFFFF Then Local $iCode = $iUnicodeDecimalOrHex - 0x10000 Local $iHigh = BitOR(0xD800, BitShift($iCode, 10)) Local $iLow = BitOR(0xDC00, BitAND($iCode, 0x3FF)) $sChar = ChrW($iHigh) & ChrW($iLow) Else $sChar = ChrW($iUnicodeDecimalOrHex) EndIf _GDIPlus_GraphicsDrawStringEx($hGraphics, $sChar, $hFont, $tLayout, $hFormat, $hBrush) ; Resample to Target Size Local $hFinalBitmap = _GDIPlus_BitmapCreateFromScan0($iSize, $iSize) Local $hFinalGraphics = _GDIPlus_ImageGetGraphicsContext($hFinalBitmap) _GDIPlus_GraphicsSetInterpolationMode($hFinalGraphics, $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC) _GDIPlus_GraphicsDrawImageRect($hFinalGraphics, $hBitmap, 0, 0, $iSize, $iSize) ; Apply Rotation / Flip if needed If $iRotateFlipType Then _GDIPlus_ImageRotateFlip($hFinalBitmap, $iRotateFlipType) ; Convert to Win32 HICON (Preserves full Alpha Transparency) Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hFinalBitmap) ; Send HICON message to Control ($IMAGE_ICON = 1) Local $hPrevIcon = _SendMessage($hCtrl, $iMsg, 1, $hIcon) ; Destroy previous icon if any existed to prevent memory leaks If $hPrevIcon Then _WinAPI_DestroyIcon($hPrevIcon) ; Cleanup GDI+ Resources _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hFinalGraphics) _GDIPlus_BitmapDispose($hFinalBitmap) _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_BitmapDispose($hBitmap) _WinAPI_InvalidateRect($hCtrl) Return $hIcon EndFunc ;==>_GUICtrlSetGlyph Thank you once again for the continuous feedback and support! Edited 12 hours ago by ioa747 WildByDesign 1 I know that I know nothing
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now