IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB 6 et antérieur Discussion :

Plantage dans une fonction callback


Sujet :

VB 6 et antérieur

  1. #1
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut Plantage dans une fonction callback
    Bonjour tout le monde.

    Une fois n'est pas coutume, je vais publier du code : tenez-vous bien !

    Je développe un projet dans lequel j'espère simuler des actions utilisateur dans une autre application. Je lance cette application depuis mon programme, donc je récupère son PID à partir duquel j'obtiens le handle de sa fenêtre principale, puis j'essaie de lister ses fenêtres filles. C'est là que ça plante. Voici le code significatif :
    Voire ligne 82
    Code VB6 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    Option Explicit
    Public Type Fille
      Numero As Integer
      Handle As Long
      Type As String * 20
      Texte As String * 20
      Autre As String * 20
    End Type
     
    Public Filles() As Fille, MaxFilles As Integer, nfille As Long
     
    Public PID As Long, hwnd0 As Long
    Public Nom As String
    Public IniM As New Ini
     
    Private Declare Function GetWindowThreadProcessId Lib "USER32" (ByVal hwnd As Long, _
            lpdwprocessid As Long) As Long
    Private Declare Function GetParent Lib "USER32" (ByVal hwnd As Long) As Long
    Private Declare Function GetWindow Lib "USER32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
    Public Declare Function GetWindowText Lib "USER32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
            ByVal Texte As String, ByVal L As Long) As Long
    Private Declare Function EnumChildWindows Lib "USER32" (ByVal hwnd As Long, ByVal lpEnumProc As Long, _
            ByVal LParam As Long) As Boolean
    Private Declare Function FindWindow Lib "USER32" Alias "FindWindowA" _
            (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
     
    Private Declare Function GetClassName Lib "USER32" _
            (hwnd As Long, ByRef Nom, longueur As Integer) As Integer
     
    Private Const GW_HWNDNEXT = 2
     
    Public Function ProcIDFromWnd(ByVal hwnd As Long) As Long
    'Renvoie l'id d'un processus à partir d'un handle de fenêtre
      Dim idproc As Long
      GetWindowThreadProcessId hwnd, idproc
      ProcIDFromWnd = idproc
    End Function
     
    Public Function GetWindowHandle(id As Long) As Long
    'Renvoie un handle de fenêtre à partir d'un id de processus
      Dim tempHwnd As Long
      Nom = "Démineur" & Chr(0)
      GetWindowHandle = 0
      tempHwnd = FindWindow(vbEmpty, Nom)
      Do Until tempHwnd = 0
        If GetParent(tempHwnd) = 0 Then
          If id = ProcIDFromWnd(tempHwnd) Then
            GetWindowHandle = tempHwnd
            Exit Do
          End If
        End If
        tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
      Loop
    End Function
     
    Public Sub Fenetres_filles(Mere As Long, fenetre As Object)
    'fenetre est la msflexgrid où sont listées les fenêtres filles
    Dim i As Integer
      MaxFilles = 100
      ReDim Filles(MaxFilles)
      nfille = 0
      Do
        If Not EnumChildWindows(Mere, AddressOf Une_Fille, nfille) Then Exit Do
        nfille = nfille + 1
      Loop
    With fenetre
      .Rows = nfille + 1
      For i = 0 To nfille
        .Row = i + 1
        .Col = 0
        .Text = Format(Filles(i).Numero)
        .Col = 1
        .Text = Hex(Filles(i).Handle)
        .Col = 2
        .Text = Filles(i).Texte
      Next
    End With
    End Sub
     
    Public Sub Une_Fille(hwnd As Long, num As Long)
    Dim Texte As String * 21, n As Long
     If num > MaxFilles Then '<------------------------ ICI ----------------------
        MaxFilles = MaxFilles + 100
        ReDim Preserve Filles(MaxFilles)
      End If
      With Filles(num)
        .Numero = num
        .Handle = hwnd
        n = GetClassName(hwnd, Texte, 20)
        .Type = Left(Texte, n)
        .Texte = ""
        .Autre = ""
      End With
    End Sub

    Après quelques bidouilles, j'appelle Fenetres_filles avec le handle de la mère et la référence de la MSFlexGrid où je veux lister les filles, et c'est là que ça plante.

    Si je met un point d'arrêt sur la première instruction de "Une_fille" (je l'ai mise en gras), j'obtiens bien un arrêt là, mais quoi que je fasse ensuite, je sors de VB6 ("quoi que je fasse", c'est par exemple de passer la souris sur "num" pour faire afficher sa valeur, ou F8 pour passer à l'instruction suivante etc...).
    Je pense que la cause est évidente : un mauvais pointeur quelque part. Mais où ?

    A vot'bon cœur, m'sieurs-dames.

    AMIcalement.

  2. #2
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Salut

    Dans un premier temps, tentes de modifier la déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Public Type Fille
      Numero As Integer
      Handle As Long
      ' Type As String * 20 <---- nom réservé
      Typer As String * 20 '<---- ou autre mais pas Type
      Texte As String * 20
      Autre As String * 20
    End Type
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  3. #3
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Merci d'être toujours là, ProgElect !

    C'est une excellente remarque, que je me suis empressé d'appliquer.

    J'en ai profité pour transformer mon "sub" Une_Fille en "Function" qui retourne toujours "True" (c'est mieux de bien lire la doc jusqu'au bout !)

    Mais ça ne résout pas le problème.

    On dirait qu'il porte d'ailleurs précisément sur "num" (que j'ai transformé en "numero" par acquis de conscience), car si je place la souris sur le handle, j'ai bien une valeur numérique qui s'affiche, alors que sur "numero", VB6 se ferme sans autre forme de procès !

    Encre merci.

    AMIcalement.

  4. #4
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Re

    Bon une chose d'éliminée.
    On dirait qu'il porte d'ailleurs précisément sur "num" (que j'ai transformé en "numero" par acquis de conscience), car si je place la souris sur le handle, j'ai bien une valeur numérique qui s'affiche, alors que sur "numero", VB6 se ferme sans autre forme de procès !
    Tu parles je pense du mode debug, pourrais tu remettre la sub Une_Fille transformée en fuction Une_Fille.
    Il serait intéressant de faire un Print.debug VarName(numero) comme première ligne est un Exit Fuction avant les lignes Dim Texte As String * 21, n As Long pour essayer de comprendre.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  5. #5
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Eh bien voila :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    Public Function Une_Fille(hwnd As Long, numero As Long) As Boolean
    Debug.Print numero
    Exit Function
    Dim Texte As String * 21, n As Long
      If numero > MaxFilles Then
        MaxFilles = MaxFilles + 100
        ReDim Preserve Filles(MaxFilles)
      End If
      With Filles(numero)
        .numero = numero
        .Handle = hwnd
        n = GetWindowText(hwnd, Texte, 20)
        .TypeF = Left(Texte, n)
        .Texte = ""
        .Autre = ""
      End With
      Une_Fille = MaxFilles < 999
    End Function
    Je ne sais pas si nous parlons du même VB6 : pour moi, c'est "debug.print numero", la fonction VarName n'existe pas.

    Je suis incapable de comprendre ce qu'il se passe : en l'état, la fenêtre d'exécution affiche UN SEUL "0" et VB6 ne plante plus, et ma MSFlexGrid affiche deux "0" dans une seule ligne.

    Il est arrivé une fois que j'aie un message que j'ai oublié, mais qui indiquait que "Numero" avait atteint des valeurs invraisemblables.

    Je dis "en l'état", par ce que le paramètre "Numero" de la fonction "EnumChildWindows" est déclaré "ByRef" (ou plutôt, sans le dire, mais c'est par défaut), alors que si je le déclare "ByVal" (ce qui me semble correspondre à la doc µ$, mais elle n'est pas très explicite), ça plante VB6.

  6. #6
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Re
    Je ne sais pas si nous parlons du même VB6 : pour moi, c'est "debug.print numero", la fonction VarName n'existe pas.
    Je t'indiquais çà de mémoire et j'ai inversé l'ordre de la commande , je n'ai pas VB6 sur l'ordinateur ou je discute avec toi.

    De plus ce n'est pas VarName mais VarType et TypeName qui peuvent être employés pour avoir des renseignements de debug.
    Il existe un type Decimal rarement utilisé, je ne sais pas si cela ferait avancer le chmiblic.

    Tu peux tenter un Debug.Print VarType(numero) suivit d'un Debug.Print TypeName(numero) pour avancer dans la compréhention du problème.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  7. #7
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    L'histoire du print n'est pas importante, et j'ai un (tout petit) peu honte d'utiliser encore cette antiquité de VB6, et j'ai (modérément) essayé d'autres trucs, mais rien ne m'a convaincu en face de la façon de construire une interface graphique avec VB6;

    Pour en revenir à mon problème, une idée m'a réveillé cette nuit : ByVal ou ByRef ? Il m'a soudain paru évident que ce devait être "ByVAL", et j'ai essayé ce matin. Le résultat me laisse rêveur : ça ne plante plus, mais ça ne fait pas du tout ce que j'attendais : la première fois, ça a bouclé jusqu'à 31889 (ou à peu près). Je crois que là, MSFlexGrid a flanché. En laissant Numero "ByRef", ça ne plante plus, et ça monte bien comme il faut.

    J'ai mis une limite "raisonnable" (499) à Numero (en renvoyant "False" à ce moment là dans Une_Fille) et le programme y va, mais j'ai toujours la même valeur pour Hwnd. En le mettant "ByRef", j'ai toujours 0 !

    Pour mémoire, voici ce que dit la doc µ$ pour la fonction Une_Fille :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    BOOL CALLBACK EnumChildProc(
      _In_ HWND   hwnd,
      _In_ LPARAM lParam
    );

    Que veut dire "_In_" ?

    AMIcalement.

  8. #8
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    En complément de ce que j'ai déjà dit, j'ai modifié mon programme pour ne plus avoir besoin de "numéro" (j'utilise une variable globale à la place), et si je déclare le Hwnd "ByRef", j'ai toujours la même valeur, et si c'est "ByVal", j'ai toujours 0 ???? On dirait que EnumChildWindows ne boucle pas sur les filles (qu'il y en ait ou non ?), mais ne fait simplement rien qu'appeler le callback.

    Pour mémoire, l'application que je lance est un programme de démineur que j'ai écrit en VB6 et compilé, où chacune des "fenêtres" sur l'une des 480 places de mines est un bouton.

    AMIcalement.

  9. #9
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 376
    Points
    20 376
    Par défaut
    bonsoir j'ai regardé le code rapidement et étant donné qu'il y a une boucle déboguer pas-à-pas pour voir si la boucle se termine bien sous peine d'obtenir un message d'erreur "dépassement de pile"
    Ensuite en VB plutôt que d'utiliser redim preserve je préfère utiliser des listes d'instances de classes.

    Sinon pour utiliser les API Windows il est souhaitable de faire un programme en C/C++ c'est bien plus facile...

  10. #10
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Merci, Mat.M

    Mais, en somme, tu ne m'aides pas beaucoup.

    J'ai,dit plus haut que j'avais fait quelque (maigres) essais pour évoluer après VB6, mais que rien ne m'avait convaincu en matière de programmation d'interface Homme-machine. Peux-tu corriger ça ? J'ai essayé du java, insupportablement verbeux, j'ai essayé Eclipse, insupportablement compliqué (sans parler des mises à jour...) et je ne sais quoi encore...

    Mais l'appel des API est (en principe) possible - et même prévue (vois "AddressOf") en VB6. Alors quoi ?

    Existe-t-il un environnement de RAD avec une bibliothèque d'objets pré-programmés que l'on peut utiliser aussi facilement qu'en VB6 ?

    Je ne parle pas de VB.Net (une pensée émue pour le regretté JCB) qui va générer des méga octets d'on ne sait pas quoi pour la première broutille...

    Mais bon, le sujet est peut-être polémique...

    AMIcalement.

  11. #11
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 376
    Points
    20 376
    Par défaut
    @Yves le problème c'est que j'ai pas VB6 sous la main donc je ne peux pas corriger le code.
    J'aurais pu faire du code VBA aussi mais c'est pareil je n'ai pas Ms-Office sous la main.
    Est-ce pour un projet pro ?
    Je peux faire un morceau de code vite fait bien fait sous VB.Net m'envoyer un MP.

  12. #12
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Merci d'être présent. Je ne sais pas si on va bien pouvoir avancer. La question de "Redim Preserve" est surtout une question de performance : ça fait le job, alors que, présentement, il ne se fait pas ailleurs.

    Et, pour le moment, je n'ai que VB6 "opérationnel", mais cela ne devrait n'être qu'un problème de performances (ou de mode ???), mais les fontionnalités sont (devraient ?) présentes. J'ai l'impression que le question qui se pose vient des déclarations "ByRef" ou "ByVal". Le formalisme de C++ n'est pas très explicite à mes yeux peu expérimentés, et la doc µ$ encore moins, c'est pourquoi j'espère que des gens plus experts que moi en VB6 pourront m'éclairer.

    Non, non, ce n'est pas un projet pro : je suis retraité depuis plusieurs années, et j'essaie de faire un programme d'intelligence (rudimentaire, mais quand même automatique) capable de jouer au démineur : c'est dire l'importance de la chose.

    AMIcalement.

  13. #13
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Salut

    Bien que toujours abonné à cette discussion, je n'interviens que très peu car je n'ai plus VB6 et antérieur d’installé que sur un vieux PC sous windows 7 qui, quand je le met en route pleure de partout pour les mises à jour.
    Revenons quand même à ton problème, le passage par ByRef peut être plus ou moins dangereux car on peut modifier la valeur du paramètre, ByVal lui n'est qu'en lecture donc n’interfère jamais sur la référence à cette valeur.
    J'avoue ne pas comprendre se qui fait planter l’éditeur VB6 quand il est utilisé ByRef, et pourquoi la fonction avec ByVal renvoie toujours 0.

    Moi aussi je regrette VB6, c'était un bon langage, ou tout du moins, un langage qui permettait une certaine indépendance comparé à tous ces nouveaux qui mettent un fil à la patte du programmeur amateur ou professionnel.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  14. #14
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Mais mon VB6 tourne sous Windows 10 ! Et il support très bien les mises à jour (à moins que mon problème actuel ait quelque chose à voir avec ça ?).

    J'ai aussi installé les anciens jeux de Windows 7, mais ça, il faut les réinstaller à chaque "grosse"" MàJ !

    Je pense que ce qui faisait planter VB6, c'était un paramètre modifiable par la fonction appelée, et déclaré en ByVal : l'appelé voyait ça comme une adresse, et il essayait d'écrire dans un mauvais endroit.

    Maintenant, ça ne plante plus, mais on dirait que les API "Enum..." n'énumèrent rien du tout. Quelle peut bien en être la raison ? Je n'ai pas d'idée...

    AMIcalement.

  15. #15
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 376
    Points
    20 376
    Par défaut
    Citation Envoyé par L'AMI Yves Voir le message
    Je pense que ce qui faisait planter VB6, c'était un paramètre modifiable par la fonction appelée, et déclaré en ByVal : l'appelé voyait ça comme une adresse, et il essayait d'écrire dans un mauvais endroit.
    oui c'est exactement ça c'est un problème de pointeur qui pointe sur une adresse mémoire non allouée donc le pointeur veut exécuter du code qui est n'importe quoi...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    If Not EnumChildWindows(Mere, AddressOf Une_Fille, nfille) Then Exit Do
    le problème ne vient-il pas du Not ?
    Je préférerais écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Dim code_retour as Long
    code_retour =EnumChildWindows(Mere, AddressOf Une_Fille, nfille)

  16. #16
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Bonsoir Mat.M

    Je n'ai pas encore tout passé au peigne fin, donc ça ne marche pas encore.

    J'en ai déjà trouvé une bien bonne : lorsqu'un appel de fonction en VB6 doit passer un argument String, il passe systématiquement un pointeur. Donc si on appelle une API qui attend une chaîne, il faut déclarer cet argument "ByVal" et laisser VB6 faire comme il fait d'habitude (en tout cas, c'est ce que j'ai compris, et j'ai vu au cours de mes recherches un exemple où les APIs étaient déclarées comme ça. Il fait dir que ça fait drôle de déclarer ByVal u argument que la doc µ$ appelle "lsStr").

    Quant à ta remarque sur Not, je ne suis pas d'accord : la doc précise bien que la fonction renvoie un "Bool", qui est "True" tant qu'il y a des fénêtres à lister, et "False" quand c'est fini. Je ne peux être sûr de rien tant que ça ne marche pas, mais j'ai peu de doutes sur cette ligne là.

    Bien sûr, je ne manquerai pas de venir dire ici ce qu'il m'a fallu corriger quand ça marchera.

    AMIcalement.

  17. #17
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Bonsoir Kamarades

    Jusqu'à plus ample informé, je suis sûr de moi. Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    Public Declare Function EnumChildWindows Lib "USER32" _
            (ByVal hwnd As Long, ByVal lpEnumProc As Long, ByVal LParam As Long) As Boolean
     
    Public Sub Fenetres_filles(Mere As Long)
    '"Filles" est la table des types "Fille" où sont listées les données des fenêtres filles
      MaxFilles = 100
      ReDim Filles(MaxFilles)
      nfille = 0
      Do While EnumChildWindows(Mere, AddressOf Une_Fille, 0)
        nfille = nfille + 1
      Loop
    End Sub
     
    Public Function Une_Fille(ByVal hwndf As Long, ByVal numero As Long) As Boolean
    Debug.Print nfille, VarType(hwndf), TypeName(hwndf), hwndf
    Dim texte As String * 21, n As Long
      If nfille > MaxFilles Then
        MaxFilles = MaxFilles + 100
        ReDim Preserve Filles(MaxFilles)
      End If
      With Filles(nfille)
        .numero = nfille
        .Handle = hwndf
        n = GetWindowText(hwndf, texte, 20)
        .TypeF = IIf(n > 0, Left(texte, n), "_")
        n = SendMessage(hwndf, WM_GETTEXT, 20, texte)
        .texte = IIf(n > 0, Left(texte, n), "_")
        .Autre = ""
      End With
      Une_Fille = nfille < 600
      End Function
    Et les Debug.Print indiquent bien que ce sont des entiers longs. Or, dans les conditions où je lance mon programme, EnumChildWindows n'énumère rien du tout : le hwndf retourné est toujours le même (et les textes sont toujours vides), et la boucle ne s'arrête jamais (je suis allé jusqu'à 1000 !)

    Je ne vois pas ce qui peut foirer !

    Merci de votre aide.

    AMIcalement.

  18. #18
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Salut

    Dans un vieux programme qui fonctionne sans plantage j'ai
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EnumChildWindows CphWndP, AddressOf EnumChildProc, ByVal 0&
    alors que toi tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Do While EnumChildWindows(Mere, AddressOf Une_Fille, 0)
    Comme tu peux le voir, le passage du troisième paramètre est plus renseigné que toi, ByValet surtout le & qui suis le 0 qui permet de confirmer/typer la valeur.

    Si tu le désir, je pourrai te poster le programme complet, ce n'est qu'un programme d'étude de différentes APIs, mais si cela te permet de comparer, pourquoi pas.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  19. #19
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    506
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 506
    Points : 131
    Points
    131
    Par défaut
    Merci ProgElect

    J'ai remplacé mon "0" par ton "ByVal 0&", et le résultat est exactement le même.

    Je veux bien les sources complètes de ton programme.

    Ton exemple me laisse quand-même perplexe, car il semble que tu appelles EnumChildWindows comme un sub, et non une Function ; est-ce comme ça que tu l'as déclaré, et, si oui, comment détectes-tu que l'énumération est finie ?

    Je l'ai déclaré comme une Function, conformément à la doc µ$, et la boucle s'arrête bien quand ma fonction callback renvoie False (bien qu'il soit écrit aussi dans la doc que le code retour de la fonction callback n'est pas utilisé ???)

    Encore merci.

    AMIcalement.

  20. #20
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 182
    Points
    17 182
    Par défaut
    Re

    Le dossier du projet ziper en pièce jointe
    L'étude fonctionne sans plantage, mais j'ai rien nettoyé, il reste peut être des APIs non utilisés ou autre contrôles inutilisés.
    Je te laisse découvrir le truc , sachant que le bouton en haut à gauche enclenche une surveillance ou non via un Timer.
    C'est un programme d'étude qui m'a servis pour un autre programme plus important, mais celui-ci, je ne l'ai plus, ayant été développé pour le pro.
    Fichiers attachés Fichiers attachés
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

Discussions similaires

  1. plantage dans une fonction récursive
    Par Lintel-oo dans le forum Langage
    Réponses: 3
    Dernier message: 04/05/2014, 21h16
  2. [C#] Mettre à jour l'affichage dans une fonction callback
    Par pdgnr dans le forum Windows Forms
    Réponses: 2
    Dernier message: 12/02/2012, 08h33
  3. [Doctrine] Requête dans une fonction callback
    Par darkalex dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 24/10/2010, 12h34
  4. appel d'un autre callback dans une fonction
    Par jponsoda dans le forum Interfaces Graphiques
    Réponses: 4
    Dernier message: 23/06/2010, 10h01
  5. Changer valeur variable global dans une fonction callback
    Par bog333 dans le forum GTK+ avec C & C++
    Réponses: 3
    Dernier message: 02/10/2008, 15h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo