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

You can open a ticket, I am curios as well. I had a look over an old version of AutoIt source code to see if there is something obvious in GuiSetState(). Didn't find anything relevant but I don't know anyway if and how it changed in latest versions.

When the words fail... music speaks.

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