WildByDesign Posted 14 hours ago Posted 14 hours ago I am working on a custom DarkMode toolbar with custom toolbar button icons made from fonts such as Segoe MDL2 Assets and Segoe Fluent Icons. In the actual project (GUIDarkTheme UDF), the toolbar button sizes scale to current DPI. For the purpose of keeping this Example simple, the sizes are static. My goal is obviously for the toolbar button (font icon) to look as sharp and nice as possible. With DrawText, I have been back and forth between $PROOF_QUALITY and $ANTIALIASED_QUALITY with both looking quite good at various sizes. With GDI+, I have tried all of the following: _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSYSTEMDEFAULT) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSINGLEBITPERPIXELGRIDFIT) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSINGLEBITPERPIXEL) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTANTIALIASGRIDFIT) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTANTIALIAS) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTCLEARTYPEGRIDFIT) The GDI+ results vary, of course. But they don't seem to be quite as good as DrawText. But I am also not as familiar with GDI+ text rendering and I could be missing something. In my Example, the first 2 toolbar buttons are created with _CreateToolbarIconFromFont() which is using GDI+. The other two buttons are using _CreateToolbarIconFromFont_DrawText() which is using DrawText. If anybody has any suggestions to improve overall quality (whether it's GDI+ or DrawText), please let me know. I am open to either direction as long as the outcome is best. Thanks. expandcollapse popup#include <Misc.au3> #include <WinAPIvkeysConstants.au3> #include <WinAPITheme.au3> #include <GuiMenu.au3> #include <ToolbarConstants.au3> #include <WindowsNotifsConstants.au3> #include <FontConstants.au3> #include <APIGdiConstants.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #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 $TBCDRF_NOETCHEDEFFECT = 0x100000 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 $g_sFont = 'Segoe MDL2 Assets' Global $iToolbarColor = 0x202020 ; Toolbar Button IDs Global Enum $e_idNew = 1000, $e_idOpen, $e_idSave, $e_idHelp ; Dropdown Menu IDs Global Enum $e_idHelpOnline = 2000, $e_idHelpAbout Global $g_h_Dropdown _GDIPlus_Startup() Example() Func Example() ; Create GUI Local $hGUI = GUICreate("_CreateToolbarIconFromFont (v" & @AutoItVersion & ")", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW) GUISetBkColor(0x191919) ;Local $hToolbar = _GUICtrlToolbar_Create($hGUI, $TBSTYLE_LIST) Local $hToolbar = _GUICtrlToolbar_Create($hGUI, BitOR($TBSTYLE_LIST, $TBSTYLE_FLAT)) ;Local $hToolbar = _GUICtrlToolbar_Create($hGUI) _WinAPI_SetWindowTheme($hToolbar, "DarkMode", "Toolbar") ;_WinAPI_SetWindowTheme($hToolbar, "DarkMode_DarkTheme", "Toolbar") _GUICtrlToolbar_SetColorScheme($hToolbar, $iToolbarColor, $iToolbarColor) _GUICtrlToolbar_SetStyleTransparent($hToolbar, True) ;Local $iWidth = 48 ;Local $iHeight = 48 ;Local $iFontSize = 32 ; Set toolbar values Local $iBtnWidth = 30 Local $iBtnHeight = 30 Local $iFontSize = 15 Local $iFontSizeDT = 24 Local $sFont = 'Segoe MDL2 Assets' ; Create normal state toolbar buttons Local $hHBitmapBack = _CreateToolbarIconFromFont($iBtnWidth ,$iBtnHeight, $iFontSize, $sFont, 0xE105, 0xE0E0E0) Local $hHBitmapForward = _CreateToolbarIconFromFont($iBtnWidth ,$iBtnHeight, $iFontSize, $sFont, 0xE946, 0xE0E0E0) Local $hHBitmapUp = _CreateToolbarIconFromFont_DrawText($iBtnWidth ,$iBtnHeight, $iFontSizeDT, $sFont, 0xE105, 0xE0E0E0) Local $hHBitmapHelp = _CreateToolbarIconFromFont_DrawText($iBtnWidth ,$iBtnHeight, $iFontSizeDT, $sFont, 0xE946, 0xE0E0E0) ; Create disabled state toolbar buttons ; previous 0xE74C Local $hHBitmapBackDis = _CreateToolbarIconFromFont($iBtnWidth ,$iBtnHeight, $iFontSize, $sFont, 0xE105, 0x494949) Local $hHBitmapForwardDis = _CreateToolbarIconFromFont($iBtnWidth ,$iBtnHeight, $iFontSize, $sFont, 0xE946, 0x494949) Local $hHBitmapUpDis = _CreateToolbarIconFromFont_DrawText($iBtnWidth ,$iBtnHeight, $iFontSizeDT, $sFont, 0xE105, 0x494949) Local $hHBitmapHelpDis = _CreateToolbarIconFromFont_DrawText($iBtnWidth ,$iBtnHeight, $iFontSizeDT, $sFont, 0xE946, 0x494949) ; Create normal image list Local $hNormal = _GUIImageList_Create($iBtnWidth, $iBtnHeight, 5) ; Use a 32 bit DIB section _GUIImageList_Add($hNormal, $hHBitmapBack) _GUIImageList_Add($hNormal, $hHBitmapForward) _GUIImageList_Add($hNormal, $hHBitmapUp) _GUIImageList_Add($hNormal, $hHBitmapHelp) _GUICtrlToolbar_SetImageList($hToolbar, $hNormal) ; Create disabled image list Local $hDisabled = _GUIImageList_Create($iBtnWidth, $iBtnHeight, 5) ; Use a 32 bit DIB section _GUIImageList_Add($hDisabled, $hHBitmapBackDis) _GUIImageList_Add($hDisabled, $hHBitmapForwardDis) _GUIImageList_Add($hDisabled, $hHBitmapUpDis) _GUIImageList_Add($hDisabled, $hHBitmapHelpDis) _GUICtrlToolbar_SetDisabledImageList($hToolbar, $hDisabled) ; Add strings Local $aStrings[4] $aStrings[0] = _GUICtrlToolbar_AddString($hToolbar, "&GDI Plus") $aStrings[1] = _GUICtrlToolbar_AddString($hToolbar, "&GDI Plus") $aStrings[2] = _GUICtrlToolbar_AddString($hToolbar, "&DrawText") $aStrings[3] = _GUICtrlToolbar_AddString($hToolbar, "&DrawText ") ; Add buttons _GUICtrlToolbar_AddButton($hToolbar, $e_idNew, 0, $aStrings[0]) _GUICtrlToolbar_AddButton($hToolbar, $e_idOpen, 1, $aStrings[1]) _GUICtrlToolbar_AddButton($hToolbar, $e_idSave, 2, $aStrings[2]) $g_h_Dropdown = _GUICtrlToolbar_AddButton($hToolbar, $e_idHelp, 3, $aStrings[3]) ; Clean up HBITMAPs created from _CreateToolbarIconFromFont() _WinAPI_DeleteObject($hHBitmapBack) _WinAPI_DeleteObject($hHBitmapForward) _WinAPI_DeleteObject($hHBitmapUp) _WinAPI_DeleteObject($hHBitmapBackDis) _WinAPI_DeleteObject($hHBitmapForwardDis) _WinAPI_DeleteObject($hHBitmapUpDis) _WinAPI_DeleteObject($hHBitmapHelp) _WinAPI_DeleteObject($hHBitmapHelpDis) ;GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") GUISetState(@SW_SHOW) ; Loop until the user exits. Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _GDIPlus_Shutdown() EndFunc ;==>Example ; #FUNCTION# ==================================================================================================================== ; Name...........: _CreateToolbarIconFromFont ; Description....: Determines whether the specified link of the SysLink control is focused ; Syntax.........: _CreateToolbarIconFromFont($iWidth ,$iHeight, $iFontSize, $sFontName, $UNICODE, $iColor) ; Parameters.....: $iWidth - Width of the toolbar icon ; $iHeight - Height of the toolbar icon ; $iFontSize - Font size used for character ; $sFontName - Font name. Eg. 'Segoe MDL2 Assets' or 'Segoe Fluent Icons' ; $UNICODE - UNICODE code for character. Eg. 0xE72B ; $iColor - Color used for character. 0xRRGGBB ; Return values..: HBITMAP ; Author.........: WildByDesign (Thanks to ahmet for helping) ; Remarks........: You must use _WinAPI_DeleteObject to delete the HBITMAP after _GUICtrlToolbar_AddButton ; =============================================================================================================================== Func _CreateToolbarIconFromFont($iWidth ,$iHeight, $iFontSize, $sFontName, $UNICODEcode, $iColor) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth ,$iHeight , $GDIP_PXF32ARGB) Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSYSTEMDEFAULT) ;_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSINGLEBITPERPIXELGRIDFIT) ;_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTSINGLEBITPERPIXEL) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTANTIALIASGRIDFIT) ;_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTANTIALIAS) ;_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, $GDIP_TEXTRENDERINGHINTCLEARTYPEGRIDFIT) Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Local $hFormat = _GDIPlus_StringFormatCreate() Local $hFamily = _GDIPlus_FontFamilyCreate($sFontName) Local $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize) Local $tLayout = _GDIPlus_RectFCreate(0, 2, $iWidth, $iHeight) Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, ChrW($UNICODEcode), $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsDrawStringEx($hGraphics, ChrW($UNICODEcode), $hFont, $tLayout, $hFormat, $hBrush) Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap) _GDIPlus_GraphicsDispose($hGraphics) Local $hHBitmap = _WinAPI_Create32BitHBITMAP($hIcon, True) _WinAPI_DestroyIcon($hIcon) _GDIPlus_BitmapDispose($hBitmap) Return $hHBitmap EndFunc ;==>_CreateToolbarIconFromFont ; #FUNCTION# ==================================================================================================================== ; Name...........: _CreateToolbarIconFromFont_DrawText ; Description....: Determines whether the specified link of the SysLink control is focused ; Syntax.........: _CreateToolbarIconFromFont($iWidth ,$iHeight, $iFontSize, $sFontName, $UNICODE, $iColor) ; Parameters.....: $iWidth - Width of the toolbar icon ; $iHeight - Height of the toolbar icon ; $iFontSize - Font size used for character ; $sFontName - Font name. Eg. 'Segoe MDL2 Assets' or 'Segoe Fluent Icons' ; $UNICODE - UNICODE code for character. Eg. 0xE72B ; $iColor - Color used for character. 0xRRGGBB ; Return values..: HBITMAP ; Author.........: WildByDesign (Thanks to ahmet for helping) ; Remarks........: You must use _WinAPI_DeleteObject to delete the HBITMAP after _GUICtrlToolbar_AddButton ; =============================================================================================================================== Func _CreateToolbarIconFromFont_DrawText($iWidth ,$iHeight, $iFontSize, $sFontName, $UNICODEcode, $iColor) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth ,$iHeight , $GDIP_PXF32ARGB) Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap) Local $hDC = _GDIPlus_GraphicsGetDC($hGraphics) Local $hFont = _WinAPI_CreateFont($iFontSize, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _ $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $PROOF_QUALITY, 0, $sFontName) ; also try $ANTIALIASED_QUALITY Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) _WinAPI_SetTextColor($hDC, _WinAPI_SwitchColor($iColor)) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Local $tRECT = _WinAPI_CreateRectEx(1, 0, $iWidth, $iHeight) Local $iTextFlags = BitOR($DT_SINGLELINE, $DT_CENTER, $DT_NOCLIP, $DT_VCENTER) _WinAPI_DrawText($hDC, ChrW($UNICODEcode), $tRECT, $iTextFlags) _GDIPlus_GraphicsReleaseDC($hGraphics, $hDC) _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_DeleteObject($hFont) Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap) _GDIPlus_GraphicsDispose($hGraphics) Local $hHBitmap = _WinAPI_Create32BitHBITMAP($hIcon, True) _WinAPI_DestroyIcon($hIcon) _GDIPlus_BitmapDispose($hBitmap) Return $hHBitmap EndFunc ;==>_CreateToolbarIconFromFont_DrawText
WildByDesign Posted 13 hours ago Author Posted 13 hours ago I should mention that, while the DrawText looks quite nice in dark mode, it ended up looking terrible in light mode. It showed much more artifacts in light mode. So that is why I am now trying to experiment with GDI+ instead to see if I can obtain a better quality for both dark mode and light mode and at various font sizes.
Solution ioa747 Posted 13 hours ago Solution Posted 13 hours ago Func _CreateToolbarIconFromFont($iWidth, $iHeight, $iFontSize, $sFontName, $UNICODEcode, $iColor) Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $GDIP_PXF32ARGB) Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap) ; Settings for Sharpening _GDIPlus_GraphicsSetPixelOffsetMode($hGraphics, 4) ; HighQuality (Half-pixel offset) _GDIPlus_GraphicsSetTextRenderingHint($hGraphics, 5) ; $GDIP_TEXTRENDERINGHINTCLEARTYPEGRIDFIT , Local $hBrush = _GDIPlus_BrushCreateSolid("0xFF" & Hex($iColor, 6)) Local $hFormat = _GDIPlus_StringFormatCreate(BitOR(0x4000, 0x0004)) ; 0x4000 (NoClip) + 0x0004 (NoFitBlackBox) _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) Local $hFamily = _GDIPlus_FontFamilyCreate($sFontName) Local $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize) Local $tLayout = _GDIPlus_RectFCreate(0, 0, $iWidth, $iHeight) _GDIPlus_GraphicsDrawStringEx($hGraphics, ChrW($UNICODEcode), $hFont, $tLayout, $hFormat, $hBrush) ; Correct Cleanup _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_BrushDispose($hBrush) Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap) _GDIPlus_GraphicsDispose($hGraphics) Local $hHBitmap = _WinAPI_Create32BitHBITMAP($hIcon, True) _WinAPI_DestroyIcon($hIcon) _GDIPlus_BitmapDispose($hBitmap) Return $hHBitmap EndFunc ;==>_CreateToolbarIconFromFont WildByDesign 1 I know that I know nothing
WildByDesign Posted 5 hours ago Author Posted 5 hours ago @ioa747 Thank you so much for your help. Not only does it produce better results, but I also learned a lot from your solution. I had no idea how to ensure that the font character would be centered horizontally and vertically, and thanks to you I know more about _GDIPlus_StringFormatSetAlign and _GDIPlus_StringFormatSetLineAlign. I also wasn't sure how to combine the incoming $iColor with the GDI+ color which always begins with "0xFF". So that line was very helpful as well. ioa747 1
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