Jump to content

SystemParametersInfo > GetSystemFont ( I made an ugly bug )


Go to solution Solved by Andreik,

Recommended Posts

#include <WinAPISys.au3> ; for $tagLOGFONT ;
;       _WinAPI_SystemParametersInfo() is actualy SystemParametersInfoW and the filename is not clear text


#include <WinAPIsysinfoConstants.au3> ; for NONCLIENTMETRICS

Global $___gt__HiDpi_WinFont = _SystemParametersInfo_GetSystemFont()


ConsoleWrite("Font : Attributes: " & $___gt__HiDpi_WinFont.Attributes & @CRLF)
ConsoleWrite("Font :     Weight: " & $___gt__HiDpi_WinFont.Weight & @CRLF)
ConsoleWrite("Font :    Quality: " & $___gt__HiDpi_WinFont.Quality & @CRLF)
ConsoleWrite("Font :   FaceName: " & $___gt__HiDpi_WinFont.FaceName & @CRLF)


Func _SystemParametersInfo_GetSystemFont()
    ; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsa
    Local $log_font, $tag_LOGFONT = StringReplace(StringReplace($tagLOGFONT, "wchar", "char"), "OutPrecision", "Attributes")

;~  $log_font = DllStructCreate($tag_LOGFONT)
;~  $log_font.Attributes = 0
;~  $log_font.Weight = 400
;~  $log_font.Quality = 5
;~  $log_font.FaceName = "Segoe UI"
;~  Return SetError(@error, @extended, $log_font)

    ;Warning: bug inducing something ahead !

    Local $tagNONCLIENTMETRICS = DllStructCreate("STRUCT;uint;int;int;int;int;int;byte lfCaptionFont[60];int;int;byte lfSmCaptionFont[60];int;int;byte lfMenuFont[60];byte lfStatusFont[60];byte lfMessageFont[60];ENDSTRUCT")
    DLLStructSetData($tagNONCLIENTMETRICS,1,DllStructGetSize($tagNONCLIENTMETRICS))
    If Not _WinAPI_SystemParametersInfoA($SPI_GETNONCLIENTMETRICS, DllStructGetSize($tagNONCLIENTMETRICS), DllStructGetPtr($tagNONCLIENTMETRICS)) Then
        $log_font.Attributes = 0
        $log_font.Weight = 400
        $log_font.Quality = 5
        $log_font.FaceName = "did not work"
        Return SetError(@error, @extended, $log_font)
    EndIf
    $log_font = DllStructCreate($tag_LOGFONT,DLLStructGetPtr($tagNONCLIENTMETRICS,"lfMenuFont"))
    $log_font.Attributes = BitOR(($log_font.Italic ? 2 : 0),($log_font.Underline ? 4 : 0),($log_font.Strikeout ? 8 : 0)) ; attributes = BitOR of italic:2, undeline:4, strikeout:8
    Return $log_font
EndFunc

;   _WinAPI_SystemParametersInfo() is actualy SystemParametersInfoW and the font filename is not clear text
Func _WinAPI_SystemParametersInfoA($iAction, $iParam = 0, $vParam = 0, $iWinIni = 0)
    Local $aCall = DllCall("user32.dll", "bool", "SystemParametersInfoA", "uint", $iAction, "uint", $iParam, "struct*", $vParam, "uint", $iWinIni)
    If @error Then Return SetError(@error, @extended, False)
    Return $aCall[0]
EndFunc

..what did I do wrong !?. Run this in a GUI and every so often, the GUI's font goes bananas !. Did I do something conceptually wrong ? 
should use "SystemParametersInfoW" instead of SystemParametersInfo(A) ?

help :baby: 

Edit: here's are files to show the bug. BugCreatorThing_v0.2023.8.1(e).zip

Edited by argumentum
added ZIP

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

This seems to work for me:

#include <WinAPISys.au3> ; for $tagLOGFONT ;
;       _WinAPI_SystemParametersInfo() is actualy SystemParametersInfoW and the filename is not clear text

#include <WinAPIsysinfoConstants.au3> ; for NONCLIENTMETRICS

Global $___gt__HiDpi_WinFont = _SystemParametersInfo_GetSystemFont()


ConsoleWrite("Font : Attributes: " & $___gt__HiDpi_WinFont.Attributes & @CRLF)
ConsoleWrite("Font :     Weight: " & $___gt__HiDpi_WinFont.Weight & @CRLF)
ConsoleWrite("Font :    Quality: " & $___gt__HiDpi_WinFont.Quality & @CRLF)
ConsoleWrite("Font :   FaceName: " & $___gt__HiDpi_WinFont.FaceName & @CRLF)


Func _SystemParametersInfo_GetSystemFont()
    ; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsa
    ;92 is the struct size for $tagLOGFONT
    Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;int iCaptionHeight;byte lfCaptionFont[92];int iSmCaptionWidth;int iSmCaptionHeight;byte lfSmCaptionFont[92];int iMenuWidth;int iMenuHeight;byte lfMenuFont[92];byte lfStatusFont[92];byte lfMessageFont[92];int iPaddedBorderWidth;ENDSTRUCT")
    $tNONCLIENTMETRICS.cbsize = DllStructGetSize($tNONCLIENTMETRICS)
    If Not _WinAPI_SystemParametersInfo($SPI_GETNONCLIENTMETRICS, $tNONCLIENTMETRICS.cbsize, $tNONCLIENTMETRICS) Then Return SetError(@error, @extended, 0)
    Local $log_font = DllStructCreate($tagLOGFONT, DllStructGetPtr($tNONCLIENTMETRICS, "lfCaptionFont"))
    $log_font.Attributes = BitOR(($log_font.Italic ? 2 : 0),($log_font.Underline ? 4 : 0),($log_font.Strikeout ? 8 : 0)) ; attributes = BitOR of italic:2, undeline:4, strikeout:8
    Return $log_font
EndFunc

Output:

Font : Attributes: 0
Font :     Weight: 400
Font :    Quality: 0
Font :   FaceName: Segoe UI

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

You mean compiled? x64 or x86? I see only running the x64 compiled version that the fonts are bold.

 

Main monitor at 125% compiled:

x86.jpg


x64.jpg

 

Btw, your $tagNONCLIENTMETRICS struct is not correct -> the arrays must be 92 of size and not 60!

 

When running at 100% the x64 exe and changing the monitor to 125% I get following output:

Font : Attributes: 0
Font :     Weight: 400
Font :    Quality: 0
Font :   FaceName: Segoe UI
- $___ga__HiDpi_Controls  0
- ratio2 96
+ $___gi__HiDpi_Context = -4
@@ (-1,0) : 0,28
..lets use WM_DPICHANGED
+ Func WM_DPICHANGED(0x0000000000160A36, 02E0, 0x0000000000780078, 0x0000003AF9DDF870)
-      $dpi_new = 120
-    $dpi_ratio = 1.25
-   $dpi_ratio2 = 0.8
- WM_DPICHANGED TimerDiff: 314.8765

GUI looks ok, no bold font. Even when switching back to 100% again.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

..because

Func _SystemParametersInfo_GetSystemFont()
    ; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsa
    ;92 is the struct size for $tagLOGFONT
;~     Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;int iCaptionHeight;byte lfCaptionFont[92];int iSmCaptionWidth;int iSmCaptionHeight;byte lfSmCaptionFont[92];int iMenuWidth;int iMenuHeight;byte lfMenuFont[92];byte lfStatusFont[92];byte lfMessageFont[92];int iPaddedBorderWidth;ENDSTRUCT")
    Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;int iCaptionHeight;byte lfCaptionFont[92];int Attributes;int iSmCaptionHeight;byte lfSmCaptionFont[92];int iMenuWidth;int iMenuHeight;byte lfMenuFont[92];byte lfStatusFont[92];byte lfMessageFont[92];int iPaddedBorderWidth;ENDSTRUCT")
    $tNONCLIENTMETRICS.cbsize = DllStructGetSize($tNONCLIENTMETRICS)
;~     If Not _WinAPI_SystemParametersInfo($SPI_GETNONCLIENTMETRICS, 0, $tNONCLIENTMETRICS) Then Return SetError(@error, @extended, 0)
;~     Local $log_font = DllStructCreate($tagLOGFONT, DllStructGetPtr($tNONCLIENTMETRICS, 13))

    ; this, without the SystemParametersInfo call, shows no bug ?!, it has to be "SystemParametersInfo"
    ; can I read the registry "HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics" 
    Local $log_font = DllStructCreate($tagLOGFONT)
    $log_font.Weight = 400
    $log_font.Quality = 5
    $log_font.FaceName = "Segoe UI"
    
    $log_font.Attributes = BitOR(($log_font.Italic ? 2 : 0),($log_font.Underline ? 4 : 0),($log_font.Strikeout ? 8 : 0)) ; attributes = BitOR of italic:2, undeline:4, strikeout:8
    Return $log_font
EndFunc

this works just fine.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

7 minutes ago, UEZ said:
+ Func WM_DPICHANGED(0x0000000000160A36, 02E0, 0x0000000000780078, 0x0000003AF9DDF870)

..that in is part the reason that I split the code into

;~  RefreshGui() ; I introduced some bug. This is to fake overcome it until is fixed

in the example, but is just wrong. There's memory corruption somewhere.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Does WM_DPICHANGED work for you when running the code by F5 as x64? On my PC it doesn't work.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

7 minutes ago, argumentum said:

..because

Func _SystemParametersInfo_GetSystemFont()
    ; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsa
    ;92 is the struct size for $tagLOGFONT
;~     Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;int iCaptionHeight;byte lfCaptionFont[92];int iSmCaptionWidth;int iSmCaptionHeight;byte lfSmCaptionFont[92];int iMenuWidth;int iMenuHeight;byte lfMenuFont[92];byte lfStatusFont[92];byte lfMessageFont[92];int iPaddedBorderWidth;ENDSTRUCT")
    Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;int iCaptionHeight;byte lfCaptionFont[92];int Attributes;int iSmCaptionHeight;byte lfSmCaptionFont[92];int iMenuWidth;int iMenuHeight;byte lfMenuFont[92];byte lfStatusFont[92];byte lfMessageFont[92];int iPaddedBorderWidth;ENDSTRUCT")
    $tNONCLIENTMETRICS.cbsize = DllStructGetSize($tNONCLIENTMETRICS)
;~     If Not _WinAPI_SystemParametersInfo($SPI_GETNONCLIENTMETRICS, 0, $tNONCLIENTMETRICS) Then Return SetError(@error, @extended, 0)
;~     Local $log_font = DllStructCreate($tagLOGFONT, DllStructGetPtr($tNONCLIENTMETRICS, 13))

    ; this, without the SystemParametersInfo call, shows no bug ?!, it has to be "SystemParametersInfo"
    ; can I read the registry "HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics" 
    Local $log_font = DllStructCreate($tagLOGFONT)
    $log_font.Weight = 400
    $log_font.Quality = 5
    $log_font.FaceName = "Segoe UI"
    
    $log_font.Attributes = BitOR(($log_font.Italic ? 2 : 0),($log_font.Underline ? 4 : 0),($log_font.Strikeout ? 8 : 0)) ; attributes = BitOR of italic:2, undeline:4, strikeout:8
    Return $log_font
EndFunc

this works just fine.

In this case you simply call _WinAPI_SystemParametersInfo() if you use tagLOGFONT as is defined in StructureConstants.au3. Anyway help file it's misleading on this structure.

Global Const $tagLOGFONT = "struct; int Height;int Width;int Escapement;int Orientation;int Weight;byte Italic;byte Underline;" & _
"byte Strikeout;byte CharSet;byte OutPrecision;byte ClipPrecision;byte Quality;byte PitchAndFamily;char FaceName[32]; endstruct"

This is what it's stated in help file but actually FaceName is defined as wchar in StructureConstants.

Link to comment
Share on other sites

I mean:

start the script in SciTE by pressing F5 but with #AutoIt3Wrapper_UseX64=y

move the GUI to another monitor with different DPI or change the DPI for you monitor so that WM_DPICHANGED is triggered.

When running it as x86 (#AutoIt3Wrapper_UseX64=n) then the wm is triggered but not when running it as x64.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

9 minutes ago, argumentum said:

did you run the code?, did you see the bug ? can I RegRead() into that struct and save me from dll hell ?, can you help ? ( other than RTFM ? ) :) 

Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
Local $tMF = DllStructCreate('byte Data[' & BinaryLen($dMenuFont) & ']')
DllStructSetData($tMF, 'Data', $dMenuFont)
Local $tFontName = DllStructCreate('wchar FontName[32]', DllStructGetPtr($tMF) + 28)
ConsoleWrite(DllStructGetData($tFontName, 'FontName') & @CRLF)

Like this?

Link to comment
Share on other sites

#include <StructureConstants.au3>

Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
Local $tLOGFONT = DllStructCreate('byte[' & BinaryLen($dMenuFont) & ']')
DllStructSetData($tLOGFONT, 1, $dMenuFont)
Local $tNew = DllStructCreate($tagLOGFONT, DllStructGetPtr($tLOGFONT))

ConsoleWrite("Italic: " & $tNew.Italic & @CRLF)
ConsoleWrite("Underline: " & $tNew.Underline & @CRLF)
ConsoleWrite("Strikeout: " & $tNew.Strikeout & @CRLF)
ConsoleWrite("Weight: " & $tNew.Weight & @CRLF)
ConsoleWrite("Quality: " & $tNew.Quality & @CRLF)
ConsoleWrite("FaceName: " & $tNew.FaceName & @CRLF)

 

Link to comment
Share on other sites

gash darn !, WTF :mad2:

..I really thought that by getting from registry would fix it. Didn't.

So all that's left is the struct itself !?. Why would just declaring a value be any different from using a struct ?. All I have left is to read the binary string and chop it by hand. I'm so perplexed by this thing.

I'll go take a walk and go at it again latter

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...