Jump to content

SystemParametersInfo > GetSystemFont ( I made an ugly bug )


Go to solution Solved by Andreik,

Recommended Posts

1 hour ago, UEZ said:

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

 

I modified this function. When you change the function in GuiCtrls_HiDpi.au3 to this and try again, do you still get odd things?

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

Looks like GuiSetState() mess up something. :frantics:

Try this code to confirm. It never fails when GuiSetState() is commented and fails almost each time when it's not.

#include <WinAPISys.au3> ; for $tagLOGFONT ;

Global $___gt__HiDpi_WinFont
_SystemParametersInfo_GetSystemFont()

$hGUI = GUICreate('Test', 400, 400)
;~ GUISetState(@SW_SHOW, $hGUI)


;~ ConsoleWrite("Font : Attributes: " & $___gt__HiDpi_WinFont.Attributes & @CRLF)
ConsoleWrite("Font :     Weight: " & DllStructGetData($___gt__HiDpi_WinFont, 'Weight') & @CRLF)
ConsoleWrite("Font :    Quality: " & DllStructGetData($___gt__HiDpi_WinFont, 'Quality') & @CRLF)
ConsoleWrite("Font :   FaceName: " & DllStructGetData($___gt__HiDpi_WinFont, 'FaceName') & @CRLF)


Func _SystemParametersInfo_GetSystemFont()
    Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
    ConsoleWrite($dMenuFont & @CRLF)
    Local $tLOGFONT = DllStructCreate('byte[' & BinaryLen($dMenuFont) & ']')
    DllStructSetData($tLOGFONT, 1, $dMenuFont)
    $___gt__HiDpi_WinFont = DllStructCreate($tagLOGFONT, DllStructGetPtr($tLOGFONT))
EndFunc

 

When the words fail... music speaks.

Link to comment
Share on other sites

2 hours ago, argumentum said:

this needs a ticket I'd say

#include <WinAPISys.au3> ; for $tagLOGFONT ;

Global $___gt__HiDpi_WinFont, $sFont
_SystemParametersInfo_GetSystemFont()

$hGUI = GUICreate('Test', 400, 400)
GUISetState(@SW_SHOW, $hGUI)


;~ ConsoleWrite("Font : Attributes: " & $___gt__HiDpi_WinFont.Attributes & @CRLF)
ConsoleWrite("Font :     Weight: " & DllStructGetData($___gt__HiDpi_WinFont, 'Weight') & @CRLF)
ConsoleWrite("Font :    Quality: " & DllStructGetData($___gt__HiDpi_WinFont, 'Quality') & @CRLF)
ConsoleWrite("Font :   FaceName: " & DllStructGetData($___gt__HiDpi_WinFont, 'FaceName') & @CRLF)
ConsoleWrite("Font :   FaceName: " & $sFont & @CRLF)


Func _SystemParametersInfo_GetSystemFont()
    Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
    ConsoleWrite($dMenuFont & @CRLF)
    Local $tLOGFONT = DllStructCreate('byte[' & BinaryLen($dMenuFont) & ']')
    DllStructSetData($tLOGFONT, 1, $dMenuFont)
    $___gt__HiDpi_WinFont = DllStructCreate($tagLOGFONT, DllStructGetPtr($tLOGFONT))
    $sFont = DllStructGetData($___gt__HiDpi_WinFont, 'FaceName')
EndFunc

Yes it does. @Andreik, would you mind since you discover it, open a ticket ?. I'll do it ( open a ticket ) if you don't want to have to stay on top of it.

The bug was with the coders :drinks:

Edited by argumentum
oops

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

Until someone will get the real problem you can use this.

#include <Array.au3>

Global $___gt__HiDpi_WinFont = _SystemParametersInfo_GetSystemFont()

$hGUI = GUICreate('Test', 400, 400)
GUISetState(@SW_SHOW, $hGUI)

_ArrayDisplay($___gt__HiDpi_WinFont)

Func _SystemParametersInfo_GetSystemFont()
    Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
    Local $aFont[6] ; [FaceName, Weight; Quality; Italic; Underline; Strikeout]
    $aFont[0] = BinaryToString('0x' & StringRegExpReplace($dMenuFont,'^0x(([0-9a-fA-F]{2}){28})|((00){4})+$', ''), 2)
    $aFont[1] = Dec(Hex(BinaryMid($dMenuFont, 18, 1) & BinaryMid($dMenuFont, 17, 1)))
    $aFont[2] = Dec(Hex(BinaryMid($dMenuFont, 27, 1)))
    $aFont[3] = Dec(Hex(BinaryMid($dMenuFont, 21, 1)))
    $aFont[4] = Dec(Hex(BinaryMid($dMenuFont, 22, 1)))
    $aFont[5] = Dec(Hex(BinaryMid($dMenuFont, 23, 1)))
    Return $aFont
EndFunc

 

When the words fail... music speaks.

Link to comment
Share on other sites

I'll be using it as:

#include <Array.au3>

Global $g_aFont = _SystemParametersInfo_GetSystemFont()
Global $hGUI = GUICreate('Test', 400, 400)
GUISetState(@SW_SHOW, $hGUI)
GUIDelete($hGUI)

_ArrayDisplay($g_aFont)

Func _SystemParametersInfo_GetSystemFont($sFontUseage = 'MenuFont')
    Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', $sFontUseage))
    ;Local $aFont[6] ; [FaceName, Weight(18,17); Quality(27); Italic(21); Underline(22); Strikeout(23)]
    Local $aFont[4] ; [FaceName, Weight; Quality; Attributes]
    $aFont[0] = BinaryToString('0x' & StringRegExpReplace($dMenuFont,'^0x(([0-9a-fA-F]{2}){28})|((00){4})+$', ''), 2)
    $aFont[1] = Dec(Hex(BinaryMid($dMenuFont, 18, 1) & BinaryMid($dMenuFont, 17, 1)))
    $aFont[2] = Dec(Hex(BinaryMid($dMenuFont, 27, 1)))
    $aFont[3] = BitOR(Dec(Hex(BinaryMid($dMenuFont, 21, 1))), Dec(Hex(BinaryMid($dMenuFont, 22, 1))), Dec(Hex(BinaryMid($dMenuFont, 23, 1))))
    Return $aFont
EndFunc

given that we use the attributes BitORed.

Edited by argumentum
better code

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

  • Solution

Well after a closer inspection I think it has nothing to do with GuiSetState() but with data returned by _WinAPI_SystemParametersInfo() that goes out of scope when function returns so data is not reliable anymore. This code would be a better approach:

#include <WinAPISys.au3>
#include <WinAPIsysinfoConstants.au3>

Global $___gt__HiDpi_WinFont = _SystemParametersInfo_GetSystemFont()

$hGUI = GUICreate('Test', 400, 400)
GUISetState(@SW_SHOW, $hGUI)

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()
    Local $tLOGFONT = DllStructCreate(StringReplace($tagLOGFONT, 'OutPrecision', 'Attributes'))
    Local $iSize = DllStructGetSize($tLOGFONT)
    Local $tNONCLIENTMETRICS = DllStructCreate("STRUCT;uint cbsize;int iBorderWidth;int iScrollWidth;int iScrollHeight;int iCaptionWidth;" & _
    "int iCaptionHeight;byte lfCaptionFont[" & $iSize & "];int iSmCaptionWidth;int iSmCaptionHeight;byte lfSmCaptionFont[" & $iSize & "];int iMenuWidth;" & _
    "int iMenuHeight;byte lfMenuFont[" & $iSize & "];byte lfStatusFont[" & $iSize & "];byte lfMessageFont[" & $iSize & "];int iPaddedBorderWidth;ENDSTRUCT")
    $tNONCLIENTMETRICS.cbsize = DllStructGetSize($tNONCLIENTMETRICS)
    If Not _WinAPI_SystemParametersInfo($SPI_GETNONCLIENTMETRICS, $tNONCLIENTMETRICS.cbsize, $tNONCLIENTMETRICS) Then Return SetError(@error, @extended, 0)
    Local $tTemp = DllStructCreate($tagLOGFONT, DllStructGetPtr($tNONCLIENTMETRICS, "lfCaptionFont"))
    With $tLOGFONT
        .Weight = $tTemp.Weight
        .FaceName = $tTemp.FaceName
        .Quality = $tTemp.Quality
        .Attributes = BitOR(($tTemp.Italic ? 2 : 0),($tTemp.Underline ? 4 : 0),($tTemp.Strikeout ? 8 : 0))
    EndWith
    Return $tLOGFONT
EndFunc

 

When the words fail... music speaks.

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