WildByDesign Posted 15 hours ago Posted 15 hours ago Thinking of this from a UDF perspective (GUIDarkTheme), I don't have access to the GUI font size if the user has something different set with GUISetFont. My goal is to obtain the font size for the GUI (eg. 8.5, 10, 12, etc.) which can then automatically set the font size for the menubar (in GUIDarkMenu UDF) so that the font size matches. I do have access to the GUI handle since that is passed on to GUIDarkTheme. So we do have a GUI handle to work with. I could technically get the user to pass on the font size as well, but my goal is to keep everything as simple and automatic as possible for whoever uses the UDF. I did spend some time searching the forum and did not find much, unfortunately. It's understandable because we would typically know the font size. But from the perspective of a UDF, I don't have that. I did find something interesting from @Yashied in this post. expandcollapse popup#Include <Array.au3> #Include <FontConstants.au3> #Include <WinAPI.au3> #Include <WindowsConstants.au3> $hGUI = GUICreate('MyGUI', 300, 200) GUISetFont(12) $Label = GUICtrlCreateLabel('Simple Text', 20, 40, 100, 22) ;GUICtrlSetFont(-1, 12, 700, 2 + 4, 'Tahoma') GUISetState(@SW_SHOW) ;$aFont = GUIGetFont($hGUI) $aFont = GUICtrlGetFont($Label) _ArrayDisplay($aFont) Do Until GUIGetMsg() = -3 #cs [0] - Size [1] - Weight [2] - Attribute [3] - Name [4] - Quality #ce Func GUIGetFont($hWnd) Local $Ret, $hDC, $hFont, $tFont Local $aFont = 0 $hDC = _WinAPI_GetDC($hWnd) $hFont = _SendMessage($hWnd, $WM_GETFONT) $tFont = DllStructCreate($tagLOGFONT) $Ret = DllCall('gdi32.dll', 'int', 'GetObjectW', 'ptr', $hFont, 'int', DllStructGetSize($tFont), 'ptr', DllStructGetPtr($tFont)) If (Not @error) And ($Ret[0]) Then ConsoleWrite("past error" & @CRLF) Dim $aFont[5] = [0] $aFont[0] = -Round(DllStructGetData($tFont, 'Height') / _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY) * 72, 1) $aFont[1] = DllStructGetData($tFont, 'Weight') $aFont[2] = BitOR(2 * (DllStructGetData($tFont, 'Italic') <> 0), 4 * (DllStructGetData($tFont, 'Underline') <> 0), 8 * (DllStructGetData($tFont, 'Strikeout') <> 0)) $aFont[3] = DllStructGetData($tFont, 'FaceName') $aFont[4] = DllStructGetData($tFont, 'Quality') EndIf _WinAPI_ReleaseDC($hWnd, $hDC) Return $aFont EndFunc ;==>GUIGetFont Func GUICtrlGetFont($CtrlID) Local $hWnd = GUICtrlGetHandle($CtrlID) If Not $hWnd Then Return 0 EndIf Local $Ret, $hDC, $hFont, $tFont Local $aFont = 0 $hDC = _WinAPI_GetDC($hWnd) $hFont = _SendMessage($hWnd, $WM_GETFONT) $tFont = DllStructCreate($tagLOGFONT) $Ret = DllCall('gdi32.dll', 'int', 'GetObjectW', 'ptr', $hFont, 'int', DllStructGetSize($tFont), 'ptr', DllStructGetPtr($tFont)) If (Not @error) And ($Ret[0]) Then Dim $aFont[5] = [0] $aFont[0] = -Round(DllStructGetData($tFont, 'Height') / _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY) * 72, 1) $aFont[1] = DllStructGetData($tFont, 'Weight') $aFont[2] = BitOR(2 * (DllStructGetData($tFont, 'Italic') <> 0), 4 * (DllStructGetData($tFont, 'Underline') <> 0), 8 * (DllStructGetData($tFont, 'Strikeout') <> 0)) $aFont[3] = DllStructGetData($tFont, 'FaceName') $aFont[4] = DllStructGetData($tFont, 'Quality') EndIf _WinAPI_ReleaseDC($hWnd, $hDC) Return $aFont EndFunc ;==>GUICtrlGetFont The only problem is that it only works with controls. It works very well though. I tried my best to modify his function so I could send the GUI handle (since I do have that) in hopes to get the font details, but it fails. My added function is GUIGetFont($hWnd). Does anyone know of a way to get the GUI font size in this scenario? Thank you for your time.
WildByDesign Posted 15 hours ago Author Posted 15 hours ago From what I can tell so far, it is failing to get the font here: $hFont = _SendMessage($hWnd, $WM_GETFONT)
WildByDesign Posted 15 hours ago Author Posted 15 hours ago Adding: $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) Gives me something but of course, that is just giving the default font size in the end.
Nine Posted 14 hours ago Posted 14 hours ago Try this : expandcollapse popup; From Nine #include <GUIConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> #include <Array.au3> Opt("MustDeclareVars", True) Example() Func Example() Local $hGUI = GUICreate("Example") Local $idEdit = GUICtrlCreateEdit("Test", 10, 10, 200, 20) GUICtrlSetFont(-1, 10, 0, 0, "Consolas") GUISetState() _ArrayDisplay(GUICtrlGetFont($idEdit)) While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func GUICtrlGetFont($hWnd) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $aFont[5], $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _SendMessage($hWnd, $WM_GETFONT), $tFont = DllStructCreate($tagLOGFONT) _WinAPI_GetObject($hFont, DllStructGetSize($tFont), $tFont) $aFont[0] = Abs(Round($tFont.Height / _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY) * 72, 1)) $aFont[1] = $tFont.Weight $aFont[2] = BitOR(2 * ($tFont.Italic <> 0), 4 * ($tFont.Underline <> 0), 8 * ($tFont.Strikeout) <> 0) $aFont[3] = $tFont.FaceName $aFont[4] = $tFont.Quality _WinAPI_ReleaseDC($hWnd, $hDC) Return $aFont EndFunc ;==>_GetFont WildByDesign and MattyD 2 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted 14 hours ago Author Posted 14 hours ago 7 minutes ago, Nine said: Try this : Thanks. It does work well but it is not getting the font size for the GUI itself. For example, if you add GUISetFont(14) before the edit control is created and changing to _ArrayDisplay(GUICtrlGetFont($hGUI)) it fails to get the GUI font. I've ran into this issue before as well but never bothered to look too deep into it.
Solution Nine Posted 14 hours ago Solution Posted 14 hours ago It does says GUICtrlGetFont expandcollapse popup; From Nine #include <GUIConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> #include <Array.au3> Opt("MustDeclareVars", True) Example() Func Example() Local $hGUI = GUICreate("Example") GUISetFont(14) Local $idEdit = GUICtrlCreateEdit("Test", 10, 10, 200, 20) GUICtrlSetFont(-1, 10, 0, 0, "Consolas") GUISetState() _ArrayDisplay(GUICtrlGetFont($idEdit)) ConsoleWrite(GUIGetFontSize($hGUI) & @CRLF) While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func GUICtrlGetFont($hWnd) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $aFont[5], $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _SendMessage($hWnd, $WM_GETFONT), $tFont = DllStructCreate($tagLOGFONT) _WinAPI_GetObject($hFont, DllStructGetSize($tFont), $tFont) $aFont[0] = Abs(Round($tFont.Height / _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY) * 72, 1)) $aFont[1] = $tFont.Weight $aFont[2] = BitOR(2 * ($tFont.Italic <> 0), 4 * ($tFont.Underline <> 0), 8 * ($tFont.Strikeout) <> 0) $aFont[3] = $tFont.FaceName $aFont[4] = $tFont.Quality _WinAPI_ReleaseDC($hWnd, $hDC) Return $aFont EndFunc ;==>GUICtrlGetFont Func GUIGetFontSize($hWnd) Local $idTest = GUICtrlCreateLabel("Test", -100, -100, 150, 30) Local $aTest = GUICtrlGetFont($idTest) GUICtrlDelete($idTest) Return $aTest[0] EndFunc ;==>GUIGetFontSize WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted 13 hours ago Author Posted 13 hours ago 2 minutes ago, Nine said: It does says GUICtrlGetFont Indeed, of course. Your new method of creating a hidden label that would technically pull in the GUI font size and then getting the size from that label is a brilliant and creative idea. That works really well. Nice technique. It looks like you are rounding the returned value to the nearest .5 which is also smart. That was going to be my next question. Thank you for this. I haven't tried it within the UDF yet, but from the perspective of the UDF this should work.
WildByDesign Posted 13 hours ago Author Posted 13 hours ago 11 minutes ago, WildByDesign said: It looks like you are rounding the returned value to the nearest .5 which is also smart. That was going to be my next question. Actually, maybe I was wrong on this. It doesn't appear to be rounding to the nearest .5 value. The reason why I noticed that is because the value is slightly different depending on the DPI scaling set. The return value is different whether DPI is set or not, and also when changing the DPI scaling level. That makes sense, of course. It is adapting to those changes which is a really good thing from a measurement perspective. With that being said, could you please help with rounding to the nearest .5? It can be a separate function or built into the main function, either way. Thank you so much.
MattyD Posted 13 hours ago Posted 13 hours ago Just a small nitpick.. $aFont[0] = -_WinAPI_MulDiv($tFont.Height, 72, _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY)) WildByDesign 1
WildByDesign Posted 13 hours ago Author Posted 13 hours ago (edited) 9 minutes ago, MattyD said: Just a small nitpick.. Small but mighty! That fixed the return values on the different DPI levels perfectly. Thank you! EDIT: Also negates the need for any rounding. Edited 13 hours ago by WildByDesign
MattyD Posted 13 hours ago Posted 13 hours ago yeah - not quite there actually. You lose a little bit of granularity.
Nine Posted 13 hours ago Posted 13 hours ago Good catch Matty. Anyway to answer your question Wild about .5, here how : Local $aTest = [1.432, 1.123, 1.632, 1.789, 1.985] For $nNum In $aTest ConsoleWrite(Round($nNum / 0.5) * 0.5 & @CRLF) Next WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
MattyD Posted 12 hours ago Posted 12 hours ago (edited) -(($tFont.Height * 72)/_WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY)) I think this is as good as we're getting. The system rounds going the other way so there's a limit. It gives a bit more granularity as $tFont.Height changes, which is a signed int. The amount it changes might change depending on the DC/font. Edited 12 hours ago by MattyD WildByDesign 1
WildByDesign Posted 11 hours ago Author Posted 11 hours ago You guys are fantastic. This community wins… always. I can confirm that this method does work wonderfully in the UDF and does set the menubar text at the font size matching the GUI as set by the user. Thank you both for your time on this. Have a great weekend.
WildByDesign Posted 4 hours ago Author Posted 4 hours ago I've updated the script by adding the font handle ($hFont) to the array because we can use that for the menubar text measurement as well. @UEZ This technique that Nine has come up with should be beneficial for you as well because I use your menubar subclassing code. From your code: Local $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) That is used in your WM_MEASUREITEM and WM_DRAWITEM and possibly elsewhere. The initial Local $hFont fails 100% of the time. Therefore it always falls back to the stock GUI font. With the technique from Nine, you get the font handle (and other details) and also the DPI precision thanks to Matty. Anyway, here is my updated script which returns the font handle in the array as well. expandcollapse popupDllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) ; From Nine #include <GUIConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> #include <Array.au3> Opt("MustDeclareVars", True) Example() Func Example() Local $hGUI = GUICreate("Example") GUISetFont(12) Local $idEdit = GUICtrlCreateEdit("Test", 10, 10, 200, 20) GUICtrlSetFont(-1, 10, 0, 0, "Consolas") Local $aFont = GUIGetFontSize($hGUI) ConsoleWrite("Font Size: " & @TAB & @TAB & @TAB & $aFont[0] & @CRLF) ConsoleWrite("Font Weight: " & @TAB & @TAB & $aFont[1] & @CRLF) ConsoleWrite("Font Attributes: " & @TAB & $aFont[2] & @CRLF) ConsoleWrite("Font Name: " & @TAB & @TAB & @TAB & $aFont[3] & @CRLF) ConsoleWrite("Font Quality: " & @TAB & @TAB & $aFont[4] & @CRLF) ConsoleWrite("Font Handle: " & @TAB & @TAB & $aFont[5] & @CRLF) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func GUICtrlGetFont($hWnd) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $aFont[6], $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _SendMessage($hWnd, $WM_GETFONT), $tFont = DllStructCreate($tagLOGFONT) _WinAPI_GetObject($hFont, DllStructGetSize($tFont), $tFont) $aFont[0] = Round(-(($tFont.Height * 72)/_WinAPI_GetDeviceCaps($hDC, $LOGPIXELSY)) / 0.5) * 0.5 $aFont[1] = $tFont.Weight $aFont[2] = BitOR(2 * ($tFont.Italic <> 0), 4 * ($tFont.Underline <> 0), 8 * ($tFont.Strikeout) <> 0) $aFont[3] = $tFont.FaceName $aFont[4] = $tFont.Quality $aFont[5] = $hFont _WinAPI_ReleaseDC($hWnd, $hDC) Return $aFont EndFunc ;==>GUICtrlGetFont Func GUIGetFontSize($hWnd) Local $idTest = GUICtrlCreateLabel("Test", -100, -100, 150, 30) Local $aFont = GUICtrlGetFont($idTest) GUICtrlDelete($idTest) ;Return Round($aTest[0] / 0.5) * 0.5 Return $aFont EndFunc ;==>GUIGetFontSize
WildByDesign Posted 3 hours ago Author Posted 3 hours ago It worked! I replaced all instances of: Local $hFont = __SendMessage($hWnd, $WM_GETFONT, 0, 0) With: Local $hFont = GUIGetFontSize($hGUI)[5] MattyD 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