Récupérer les infos sur les controles d'une fenêtre externe

Signaler
Messages postés
48
Date d'inscription
lundi 11 avril 2011
Statut
Membre
Dernière intervention
29 avril 2020
-
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
-
Bonjour,

En recherchant sur le net j'ai réussi à obtenir le Handle d'une fenêtre externe à mon application.

Je butte maintenant pour trouver les informations concernant les contrôles contenus dans cette fenêtre externe. En fait, je voudrais pouvoir récupérer et charger les valeurs de ces contrôles à partir de mon application.

Avez-vous une idée de la méthode pour réaliser cette fonction et quels sont les API à utiliser ?

Merci par avance.

Cordialement.

2 réponses

Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113
Messages postés
48
Date d'inscription
lundi 11 avril 2011
Statut
Membre
Dernière intervention
29 avril 2020

Merci,
Je n'ai pas encore chargé le projet, mais à la lecture de l'intro, ça ressemble assez bien à ce que je recherche.

Je me penche dessus aussitôt que possible.

Cordialement
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113
Messages postés
48
Date d'inscription
lundi 11 avril 2011
Statut
Membre
Dernière intervention
29 avril 2020

Bonjour,

Je reviens sur le sujet. L'application proposée par cs_Le Pivert est super, mais en fait ce n'est pas exactement ce que je souhaite.

En effet, je souhaite récupérer tous les éléments d'une fenêtre à partir de son handle et pouvoir les manipuler (faire de la récupération de données et du remplissage d'information à partir de mon application).

Y a t'il une ou plusieurs API qui à partir du handle d'une fenêtre permet de :

- Récupérer tous les éléments de la fenêtre.
- Une fois fait accéder à leurs propriétés et leurs méthode.


Pouvez-vous m'indiquer un fil conducteur.

Merci d'avance à tous
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113
Voici un exemple pour le titre et le redimensionnement de la fenêtre qui fonctionne:

http://codes-sources.commentcamarche.net/forum/affich-10041058-lancer-un-exe-et-le-redimensionner#11

Et celui-ci pour les controls que je n'ai pas réussi à faire fonctionner. Tu auras peut-être plus de chance que moi!

http://codes-sources.commentcamarche.net/forum/affich-10022830-handle-d-un-controle-d-une-fenetre-externe#11

@+ Le Pivert
Messages postés
48
Date d'inscription
lundi 11 avril 2011
Statut
Membre
Dernière intervention
29 avril 2020
>
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020

Merci encore du temps passé pour m'aider.

Le premier exemple est déjà fait dans mon application, lorsque je récupère le Handle de la fenêtre qui m'intéresse, je rétréci la dite fenêtre. Mais avant j'aimerai récupérer les infos de certains contrôles contenus dans cette fenêtre.
Pour le deuxième,il faut que j'analyse.

Merci encore.
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113 >
Messages postés
48
Date d'inscription
lundi 11 avril 2011
Statut
Membre
Dernière intervention
29 avril 2020

J'ai finalement réussi à adapter le dernier code avec un autre code trouvé sur le net:

Option Strict On
Imports System.Runtime.InteropServices
Public Class Form1
    ' http://www.pinvoke.net/default.aspx/user32.enumchildwindows
    <DllImport("User32.dll")> _
    Private Shared Function EnumChildWindows _
     (ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
     ByVal lParam As IntPtr) As Boolean
    End Function
    Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
    Public Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
        Dim ChildrenList As New List(Of IntPtr)
        Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
        Try
            EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
        Finally
            If ListHandle.IsAllocated Then ListHandle.Free()
        End Try
        Return ChildrenList.ToArray
    End Function
    Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
        Dim ChildrenList As List(Of IntPtr) = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
        If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
        ChildrenList.Add(Handle)
        Return True
    End Function
    ' http://codes-sources.commentcamarche.net/forum/affich-10022830-handle-d-un-controle-d-une-fenetre-externe#11
    Private Const WM_GETTEXT As Integer = &HD
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
    ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        For Each p As Process In Process.GetProcesses
            If p.MainWindowTitle.Contains("Assistant photos") Then ' adapter le titre de la fenêtre
                Dim Childrens As IntPtr() = GetChildWindows(p.MainWindowHandle)
                Dim Handle As IntPtr = Marshal.AllocHGlobal(100)
                'Dans mon cas, PositionDuContrôle=10
                Dim NumText As Integer = CInt(SendMessage(Childrens(10), WM_GETTEXT, CType(50, IntPtr), Handle))
                'Récupération du texte du contrôle!
                MsgBox(Marshal.PtrToStringUni(Handle))
            End If
        Next
        End Sub
End Class


J'ai mis les 2 liens

@+ Le Pivert
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113 >
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020

Je viens de penser à faire une boucle sur tous les controls comme ceci:

 Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Try
            For Each p As Process In Process.GetProcesses
                If p.MainWindowTitle.Contains("Assistant photos") Then ' adapter le titre de la fenêtre
                    Dim Childrens As IntPtr() = GetChildWindows(p.MainWindowHandle)
                    Dim Handle As IntPtr = Marshal.AllocHGlobal(100)
                    For i = 1 To 30 'a adapter au nombre de controls
                        'Dans mon cas, PositionDuContrôle=10
                        Dim NumText As Integer = CInt(SendMessage(Childrens(i), WM_GETTEXT, CType(50, IntPtr), Handle))
                        'Récupération du texte du contrôle!
                        ListBox1.Items.Add(Marshal.PtrToStringUni(Handle))
                    Next
                End If
            Next
        Catch
        End Try
    End Sub


il suffit d'ajouter une Listbox pour afficher les textes.
J'ai mis un Try catch pour éviter le bug quand on ne connait pas le nombre de controls

Voilà
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020
113 >
Messages postés
6947
Date d'inscription
jeudi 13 septembre 2007
Statut
Contributeur
Dernière intervention
12 octobre 2020

Je me suis amusé à faire un programme,

2 listBox nommées:

lstappli et lstcontrol

2 buttons nommés:

cmdcontrol et cmdappli
mettre cmdcontrol.Enabled = False

et un label:

lblcontrol

voici le code:

Option Strict On
Imports System.Runtime.InteropServices
Public Class Form1
    ' http://www.pinvoke.net/default.aspx/user32.enumchildwindows
    <DllImport("User32.dll")> _
    Private Shared Function EnumChildWindows _
     (ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
     ByVal lParam As IntPtr) As Boolean
    End Function
    Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
    Public Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
        Dim ChildrenList As New List(Of IntPtr)
        Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
        Try
            EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
        Finally
            If ListHandle.IsAllocated Then ListHandle.Free()
        End Try
        Return ChildrenList.ToArray
    End Function
    Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
        Dim ChildrenList As List(Of IntPtr) = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
        If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
        ChildrenList.Add(Handle)
        Return True
    End Function
    ' http://codes-sources.commentcamarche.net/forum/affich-10022830-handle-d-un-controle-d-une-fenetre-externe#11
    Private Const WM_GETTEXT As Integer = &HD
    Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
    ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    Dim nomappli As String
    Private Sub cmdcontrol_Click(sender As System.Object, e As System.EventArgs) Handles cmdcontrol.Click
        Try
            For Each p As Process In Process.GetProcesses
                If p.MainWindowTitle.Contains(nomappli) Then
                    Dim Childrens As IntPtr() = GetChildWindows(p.MainWindowHandle)
                    Dim Handle As IntPtr = Marshal.AllocHGlobal(100)
                    For i As Integer = 1 To Childrens.Length
                        Dim NumText As Integer = CInt(SendMessage(Childrens(i), WM_GETTEXT, CType(50, IntPtr), Handle))
                        'Récupération du texte du contrôle!
                        lstcontrol.Items.Add(i & "    " & Marshal.PtrToStringUni(Handle))
                    Next
                End If
            Next
        Catch
        End Try
        lblcontrol.Text = CStr(lstcontrol.Items.Count) & " controls"
    End Sub
    Private Sub cmdappli_Click(sender As System.Object, e As System.EventArgs) Handles cmdappli.Click
        lstappli.Items.Clear()
        cmdcontrol.Enabled = False
        For Each p As Process In Process.GetProcesses
            If Len(Trim(p.MainWindowTitle)) > 0 Then lstappli.Items.Add(p.MainWindowTitle)
        Next p
    End Sub
    Private Sub lstappli_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles lstappli.SelectedIndexChanged
        nomappli = CStr(lstappli.SelectedItem) 'affiche le nom de l'application
        cmdcontrol.Enabled = True
    End Sub
End Class


Bonne programmation