Page 1 sur 1

Problème de comportement d'un script avec _WinAPI_SetWindowLong

Posté : mar. 17 sept. 2019 00:16
par DDY
Bonjour,
Je rencontre un problème curieux dans des scripts utilisant _WinAPI_SetWindowLong avec le paramètre $GWL_USERDATA.

Ci-dessous un script d'exemple :
#cs -----------------------------------------------------------------------------------------------
    Test de stockage de data dans une fenêtre
    Méthode : _WinAPI_SetWindowLong( $hWnd, $GWL_USERDATA, $lptrData )
    OS: Windows 7 pro 64 bits
    Version AutoIt : v3.3.14.5 (idem avec AutoIt Beta.v3.3.15.1.0 )
#ce -----------------------------------------------------------------------------------------------

Opt('MustDeclareVars',1)
Opt("GUIOnEventMode",0)

#include-once
#include <Constants.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <WinAPI.au3>

global $GUI = GUICreate( "GUI", 600, 400, -1, -1, $WS_MINIMIZEBOX+$WS_MAXIMIZEBOX+$WS_SIZEBOX )
global $Edit = GUICtrlCreateEdit("", 0, 0, 600, 400 )
    GUICtrlSetResizing( -1, $GUI_DOCKBORDERS )
GUISetState( @SW_SHOW )

global $OldUserData = _WinAPI_GetWindowLong( $GUI, $GWL_USERDATA )
_GUICtrlEdit_AppendText( $Edit, StringFormat( "GetWindowLong( %s, GWL_USERDATA ) return %i\r\n", "GUI", $OldUserData ))

global $TestBUG =false             ; CHANGER PAR true  POUR TESTER L'ANOMALIE...
if ( $TestBUG ) then
    global $lptrData = _WinAPI_CreateString( "Data..." )

    global $wLong = _WinAPI_SetWindowLong( $GUI, $GWL_USERDATA, $lptrData )
    if ( @error ) then
        _GUICtrlEdit_AppendText( $Edit, StringFormat( "SetWindowLong( %s, GWL_USERDATA, $lptrData ) set @error = %i\r\n", "GUI", @error ))
    endif

    _GUICtrlEdit_AppendText( $Edit, StringFormat( "SetWindowLong( %s, GWL_USERDATA, $lptrData ) return %i\r\n", "GUI", $wLong ))

    global $NewUserData = _WinAPI_GetWindowLong( $GUI, $GWL_USERDATA )
    _GUICtrlEdit_AppendText( $Edit, StringFormat( "GetWindowLong( %s, GWL_USERDATA ) return %i\r\n", "GUI", $NewUserData ))

    global $Data = _WinAPI_GetString( $NewUserData )

    _GUICtrlEdit_AppendText( $Edit, StringFormat( "$Data = %s\r\n", $Data ))
endif

while 1
    switch GUIGetMsg()
        case $GUI_EVENT_CLOSE
            _GUICtrlEdit_AppendText( $Edit, "GUIGetMsg()::GUI_EVENT_CLOSE"& @CRLF )
            ExitLoop
    endswitch
wend

_GUICtrlEdit_AppendText( $Edit, "exit"& @CRLF )
MsgBox(0, "Validez", "Cliquez pour terminer." )         ; Pour visualsiser la trace jusqu'à la fin...
exit
Lorsqu'on exécute les lignes de code dépendant de $TestBUG (en remplaçant false par true), le comportement de la GUI est perturbé, il semblerait que GUIGetMsg, ou pire, AutoIt3.exe ne réagit plus (boucle sans fin ?) :

- Le contrôle Edit n'est plus redimentionné avec la GUI. (sans doute WM_SIZE n'est pas capturé ?)

- Impossible de fermer la GUI, sauf par le menu Exit de l'icône AutoIt de la barre des tâches (TrayIcon), et malgré tout dans ce cas AutoIt3.exe tourne encore, il faut arrêter le process par le Gestionnaire des tâches.

Si l'on met met en commentaire la boucle while ... wend, le script s'exécute jusqu'à la fin et la GUI se ferme.
Par contre, ici aussi, AutoIt3.exe tourne toujours et il faut l'arrêter par le Gestionnaire des tâches.

Quelqu'un peut-il éclairer ma lanterne ?
S'agit-il d'un BUG, ou le présent code code est-il en cause ?
Où puis-je trouver un exemple qui fontionne ( $GWL_USERDATA + $GWL_WNDPROC sur une GUI créée avec GuiCreate ) ?

NB :
Ce type de problème s'est révélé à moi lors de la rédaction de code beaucoup plus complexe concernant des fenêtres enfant (Child windows) destinées à créer des 'Panels' supportant des contrôles divers, ayant leur propre procédure de fenêtre, et associés à une structure de données.
Ce code, inachevé actuellement, est en standby, en attendant de résoudre ce problème.
Il est d'autre part trop volumineux, je ne l'ai donc pas communiqué.

Merci d'avance pour toute info de nature à résoudre ou documenter ce problème.

DDY

Re: Problème de comportement d'un script avec _WinAPI_SetWindowLong

Posté : mar. 17 sept. 2019 11:06
par TommyDDR
Sujet déplacé dans la bonne section.

Re: Problème de comportement d'un script avec _WinAPI_SetWindowLong

Posté : mar. 17 sept. 2019 11:33
par TommyDDR
Je n'ai jamais utilisé GWL_USERDATA mais après quelques tests, il semblerait que si vous l'utilisez sur une fenêtre, cela bloque les messages reçus par GUIGetMsg().

La solution serait de passer par le control au lieu de la fenêtre.
#cs -----------------------------------------------------------------------------------------------
    Test de stockage de data dans une fenêtre
    Méthode : _WinAPI_SetWindowLong( $hWnd, $GWL_USERDATA, $lptrData )
    OS: Windows 7 pro 64 bits
    Version AutoIt : v3.3.14.5 (idem avec AutoIt Beta.v3.3.15.1.0 )
#ce -----------------------------------------------------------------------------------------------

Opt('MustDeclareVars',1)
Opt("GUIOnEventMode",0)

#include-once
#include <Constants.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <WinAPI.au3>

global $GUI = GUICreate( "GUI", 600, 400, -1, -1, $WS_MINIMIZEBOX+$WS_MAXIMIZEBOX+$WS_SIZEBOX )
global $Edit = GUICtrlCreateEdit("", 0, 0, 600, 400 )
Global $hEdit = GUICtrlGetHandle($Edit)
    GUICtrlSetResizing( -1, $GUI_DOCKBORDERS )
GUISetState( @SW_SHOW )

global $OldUserData = _WinAPI_GetWindowLong( $hEdit, $GWL_USERDATA )
_GUICtrlEdit_AppendText( $Edit, StringFormat( "GetWindowLong( %s, GWL_USERDATA ) return %i\r\n", "hEdit", $OldUserData ))

global $TestBUG =true             ; CHANGER PAR true  POUR TESTER L'ANOMALIE...
if ( $TestBUG ) then
        Local $hText = _WinAPI_CreateString("test")

    Local $wLong = _WinAPI_SetWindowLong( $hEdit, $GWL_USERDATA, $hText)
    if ( @error ) then
        _GUICtrlEdit_AppendText( $Edit, StringFormat( "SetWindowLong( %s, GWL_USERDATA, $lptrData ) set @error = %i\r\n", "h", @error ))
    endif

    _GUICtrlEdit_AppendText( $Edit, StringFormat( "SetWindowLong( %s, GWL_USERDATA, $lptrData ) return %i\r\n", "GUI", $wLong ))

    Local $NewUserData = _WinAPI_GetWindowLong( $hEdit, $GWL_USERDATA )
    _GUICtrlEdit_AppendText( $Edit, StringFormat( "GetWindowLong( %s, GWL_USERDATA ) return %i\r\n", "GUI", $NewUserData ))

        _GUICtrlEdit_AppendText( $Edit, StringFormat( "$Data = %s\r\n", _WinAPI_GetString($NewUserData)))
endif

while 1
    switch GUIGetMsg()
        case $GUI_EVENT_CLOSE
            _GUICtrlEdit_AppendText( $Edit, "GUIGetMsg()::GUI_EVENT_CLOSE"& @CRLF )
            ExitLoop
    endswitch
wend

_GUICtrlEdit_AppendText( $Edit, "exit"& @CRLF )
MsgBox(0, "Validez", "Cliquez pour terminer." )         ; Pour visualsiser la trace jusqu'à la fin...
exit