Opened 3 years ago
Last modified 2 years ago
#3968 assigned Bug
global struct gets corrupted after GUISetState()
| Reported by: | argumentum | Owned by: | Jon |
|---|---|---|---|
| Milestone: | Component: | AutoIt | |
| Version: | 3.3.16.1 | Severity: | None |
| Keywords: | Struct | Cc: |
Description (last modified by )
#include <WinAPISys.au3> ; for $tagLOGFONT ; Global $___gt__HiDpi_WinFont, $sFont _SystemParametersInfo_GetSystemFont() $hGUI = GUICreate('Test', 400, 400) GUISetState(@SW_SHOW, $hGUI) ; try the code with this and without it 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) ; this never changes 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
While troubleshooting we discovered a bug.
The thread is at https://www.autoitscript.com/forum/topic/210637-systemparametersinfo-getsystemfont-i-made-an-ugly-bug/?do=findComment&comment=1522165
Attachments (0)
Change History (8)
comment:2 by , 3 years ago
| Resolution: | → No Bug |
|---|---|
| Status: | new → closed |
comment:3 by , 3 years ago
In case it help the error was coming from the fact thatthe global variable was assign to a local variable
the correction is
#include <WinAPISys.au3> ; For $tagLOGFONT ; Global $g_sFont Global $___gt__HiDpi_WinFont= _SystemParametersInfo_GetSystemFont() Local $hGUI = GUICreate('Test', 400, 400) GUISetState(@SW_SHOW, $hGUI) ; try the code with this and without it 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: " & $g_sFont & @CRLF) ; this never changes 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) Local $tTemp = DllStructCreate($tagLOGFONT, DllStructGetPtr($tLOGFONT)) $g_sFont = DllStructGetData($___gt__HiDpi_WinFont, 'FaceName') Return $tTemp EndFunc ;==>_SystemParametersInfo_GetSystemFont
Cheers
comment:4 by , 3 years ago
hmm, I've run the correction you posted here but it does not correct the original code that is observable while running over and over again while testing.
comment:5 by , 3 years ago
| Resolution: | No Bug |
|---|---|
| Status: | closed → reopened |
Hi
I understand that the return is erratic even If I fix the
$g_sFont = DllStructGetData($_gtHiDpi_WinFont, 'FaceName')
to
$g_sFont = DllStructGetData($tTemp, 'FaceName')
I don't understand the influence of the position of
Global $_gtHiDpi_WinFont= _SystemParametersInfo_GetSystemFont()
which is ok after the
GUISetState(@SW_SHOW, $hGUI) ; try the code with this and without it
here is the code which is erratic
#include <WinAPISys.au3> ; For $tagLOGFONT ;
Global $g_sFont
Local $___gt__HiDpi_WinFont= _SystemParametersInfo_GetSystemFont()
Local $hGUI = GUICreate('Test', 400, 400)
GUISetState(@SW_SHOW, $hGUI) ; try the code with this and without it
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: " & $g_sFont & @CRLF) ; this never changes
Func _SystemParametersInfo_GetSystemFont()
Local $dMenuFont = Binary(RegRead('HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics', 'MenuFont'))
ConsoleWrite(BinaryLen($dMenuFont) & @CRLF)
ConsoleWrite($dMenuFont & @CRLF)
Local $tLOGFONT = DllStructCreate('byte[' & BinaryLen($dMenuFont) & ']')
DllStructSetData($tLOGFONT, 1, $dMenuFont)
Local $tTemp = DllStructCreate($tagLOGFONT, DllStructGetPtr($tLOGFONT))
$g_sFont = DllStructGetData($tTemp, 'FaceName')
Return $tTemp
EndFunc ;==>_SystemParametersInfo_GetSystemFont
comment:6 by , 3 years ago
| Description: | modified (diff) |
|---|
comment:7 by , 2 years ago
| Owner: | set to |
|---|---|
| Status: | reopened → assigned |
Hi,
I reanalyse the pb and I discover That :
The local $tTemp struct is return with local info so just after the return thos info can be overrided.
I modified the _Date_Time_EncodeSystemTime() example and I get the same problem
I am not sure how a fix can be produce
I leave to Jon the final answer
#include <FontConstants.au3> #include <WinAPIGdi.au3> #include <WinAPIGdiDC.au3> #include <WinAPIHObj.au3> #include <WinAPIMisc.au3> ; Select "Arial" font to DC and retrieve $tagOUTLINETEXTMETRIC structure Local $hDC = _WinAPI_GetDC(0) Local $hFont = _WinAPI_CreateFont(24, 0, 0, 0, $FW_NORMAL, 0, 0, 0, $DEFAULT_CHARSET, $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $ANTIALIASED_QUALITY, $DEFAULT_PITCH, 'Arial') Local $hSv = _WinAPI_SelectObject($hDC, $hFont) Local $tOLTM = _WinAPI_GetOutlineTextMetrics($hDC) ; to reproduce the bad behavior GUICreate("test") GUISetState() _WinAPI_SelectObject($hDC, $hSv) _WinAPI_ReleaseDC(0, $hDC) If IsDllStruct($tOLTM) Then ConsoleWrite('Family name: ' & _otm($tOLTM, 'otmFamilyName') & @CRLF) ConsoleWrite('Typeface name: ' & _otm($tOLTM, 'otmFaceName') & @CRLF) ConsoleWrite('Style name ' & _otm($tOLTM, 'otmStyleName') & @CRLF) ConsoleWrite('Full name: ' & _otm($tOLTM, 'otmFullName') & @CRLF) EndIf Func _otm(ByRef $tOLTM, $sName) Return _WinAPI_GetString(DllStructGetPtr($tOLTM) + DllStructGetData($tOLTM, $sName)) EndFunc ;==>_otm
comment:8 by , 2 years ago
Rethinking about the pb, if a Local Struct is to be return it is need that the receiving result get a copy of the local struct
There is a lot of place where a local Structure is return without any pb if the use of the return value is used right away
something must be fixed
following script show the pb
Local $tReturn = ReturnStruct() Local $pReturn = DllStructGetPtr($tReturn) ; should not use the local location created by the Function call ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pReturn = ' & $pReturn & @TAB & "KO should not use the local location" & @CRLF) ;### Debug Console Func ReturnStruct() Local $tStruct = DllStructCreate("Byte[128]") Local $pStruct = DllStructGetPtr($tStruct) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pStruct = ' & $pStruct & @CRLF) ;### Debug Console Local $tInternal = $tStruct ; OK just use the same location Local $pInternal = DllStructGetPtr($tInternal) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pInternal = ' & $pInternal & @TAB & "OK just use the same location" & @CRLF) ;### Debug Console Return $tStruct EndFunc

so, the bug was in the coder.
This works as advertised:
Do pardon my lack of experience if you would.