Problème de comportement d'un script avec _WinAPI_SetWindowLong

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
DDY
Niveau 1
Niveau 1
Messages : 1
Enregistré le : lun. 16 sept. 2019 20:45
Status : Hors ligne

Problème de comportement d'un script avec _WinAPI_SetWindowLong

#1

Message par DDY » mar. 17 sept. 2019 00:16

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

Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 1820
Enregistré le : mar. 22 juil. 2008 20:55
Localisation : Nantes
Status : Hors ligne

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

#2

Message par TommyDDR » mar. 17 sept. 2019 11:06

Sujet déplacé dans la bonne section.
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 1820
Enregistré le : mar. 22 juil. 2008 20:55
Localisation : Nantes
Status : Hors ligne

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

#3

Message par TommyDDR » mar. 17 sept. 2019 11:33

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
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

Répondre