Opened 16 months ago
Last modified 8 months 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 mLipok)
#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:1 Changed 16 months ago by argumentum
comment:2 Changed 16 months ago by Jos
- Resolution set to No Bug
- Status changed from new to closed
comment:3 Changed 16 months ago by Jpm
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 Changed 16 months ago by argumentum
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 Changed 16 months ago by Jpm
- Resolution No Bug deleted
- Status changed from closed to 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 Changed 15 months ago by mLipok
- Description modified (diff)
comment:7 Changed 8 months ago by Jpm
- Owner set to Jon
- Status changed from reopened to 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 Changed 8 months ago by Jpm
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
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
so, the bug was in the coder.
This works as advertised:
Do pardon my lack of experience if you would.