Autres l'api findwindow

patricktoulon

XLDnaute Barbatruc
Bonjour a tous
je voudrais faire une fonction findwindow sur!!!
en effet findwindow récupère me handle de la fenêtre par sa classe et sa caption
sauf que si( 1/2 ou plus(multiple instance)) fenêtres porte la même captions ben c'est toujours la première de la hiérarchie d'affichage (ou l'instance active )qui sera prise en compte

un petit exemple représentatif du probleme
1 userform instancié 2 fois
VB:
#If VBA7 Then
    #If Win64 Then
        Declare PtrSafe Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
        Declare PtrSafe Function SetWindowLongA Lib "user32" (ByVal Hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As Long
        Dim HwndUsF As LongPtr
    #Else
        Declare PtrSafe Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
        Declare PtrSafe Function SetWindowLongA Lib "user32" (ByVal Hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        Dim HwndUsF As Long

    #End If
#Else
    Declare Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Declare Function SetWindowLongA Lib "user32" (ByVal Hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

    Dim HwndUsF As Long
#End If
Dim UF(3) As UserForm1
Sub testmultipleInstance()
'on lance une première instance de l'userform1
Set UF(1) = New UserForm1
With UF(1): .Show 0: .Top = 50: .Left = 100: End With

'on lance une 2d instance de l'userform1
Set UF(2) = New UserForm1
With UF(2): .Show 0: .Top = 50: .Left = 400: End With

End Sub

Sub testsurle_one()
Dim Hwnd&
Hwnd = FindWindowA(vbNullString, UF(1).Caption)
SetWindowLongA Hwnd, -16, &H94CF8080
End Sub
dans cet exemple c'est la 2d instance qui vas prendre la modification sur 2013 et sur W7 avec 2007 c'est la bonne la première de l'ordre d'affichage
c'est donc un problème
il est évident que si je change le titre de la caption l'ors du show je n'aurais pas de probleme bien sur
sauf que ce n'est pas destiné a des userform mais a une app plan 3D que je lance a partir de vba la modification de la caption est des lors pas envisageable

les userforms ne sont qu'un exemple représentatif de la situation

allez les Cracks ,des idées ;)
 

Pièces jointes

  • exercice findwindow multipleinstance.xlsm
    16.2 KB · Affichages: 5

Dranreb

XLDnaute Barbatruc
Bonjour.
C'est pour ça que je n'aime pas FindWindowA
Je mettrais dans l'UserForm1 :
VB:
Option Explicit
            #If VBA7 Then
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As Long
            #Else
Private Declare Function GetForegroundWindow Lib "user32" () As Long
               #End If
Private PvHWnd As Long
Private Sub UserForm_Activate()
   PvHWnd = GetForegroundWindow
   End Sub
Public Function HWnd() As Long
   HWnd = PvHWnd
   End Function
Comme ça je l'aurais en propriété.
Mais je pense que je l'équiperais plutôt d'une méthode pour qu'il se fasse lui même son SetWindowLongA
 

patricktoulon

XLDnaute Barbatruc
bonjour @Dranreb
a oui pas mal
sauf que c'est pas tout a fait ma recherche

j’instancie par exemple 2 fenêtre d'un même app

je veux modifier la première

il me faut donc retrouver la première en ayant que pour seul bagage( le texte de la barre de titre )
c'est chaud non?
je ne sais pas si ça existe ou alors j'ai complètement oublié
peut on chercher dans le threads ou processthread ou quelque chose du genre

j'ai pas essayé getwindownext voir si je peux lister dans l'ordre dans les quel les fenêtres on été ouvertes
 

Dranreb

XLDnaute Barbatruc
Mais comme dit, on a en général besoin de ce handle pour modifier des propriétés qui ne sont pas accessible par MSForms. Alors je préfèrerais que ce soit l'UserForm qui s'en charge par une méthode conçue pour ça, sans avoir besoin de communiquer son handle, sauf éventuellement à une procédure de service dans un module standard si tu veux pouvoir le faire pour des UserForm différents, sans avoir besoin d'y mettre chaque fois une même méthode longue, ni devoir la changer partout si elle évolue.
Mais sinon ça c'est déjà très bien :
VB:
SetWindowLongA UF(1).HWnd, -16, &H94CF8080
 
Dernière édition:

dysorthographie

XLDnaute Accro
bonjour Patrick et bonjour le forum!
tu lui donne un caption improbable puis tu restitues le bon!
VB:
Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type

Private Declare Function CoCreateGuid Lib "ole32.dll" (G As GUID) As Long
Private Declare Function StringFromGUID2 Lib "ole32.dll" (G As GUID, _
    ByVal str As String, _
    ByVal cchMax As Long) As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long

Private Function GetGUID() As String
    Dim G As GUID
    Dim S As String

    S = String(76, vbNullChar)
    CoCreateGuid G
    StringFromGUID2 G, S, Len(S)
    S = StrConv(S, vbFromUnicode)
    GetGUID = S
End Function

Private Function GetUserFormHandle(ByVal UF As Object)
    Dim S As String
    Dim OrigCaption As String

    S = GetGUID()
    OrigCaption = UF.Caption
    UF.Caption = S
    GetUserFormHandle = FindWindow(vbNullString, S)
    UF.Caption = OrigCaption
End Function

Private Sub UserForm_Initialize()
    MsgBox "UserForm window handle: 0x" + Hex(GetUserFormHandle(Me))
End Sub
si dans ton Userfom tu déclare ta variable HWnd comme public tu pourras faire
VB:
Sub testsurle_one()
SetWindowLongA  UF(1).Hwnd, -16, &H94CF8080
End Sub
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
oui les deux méthodes sont bonnes sauf que dans la vrai situation sur mes instances de fenêtre je ne peux pas changer le texte de la barre de titre
j'ai essayé pourtant avec SetWindowTextA
il doit y avoir un truc qui me l'interdit

c'est bien pour ça que j'ai posé la question ;)
 

patricktoulon

XLDnaute Barbatruc
re
ben pour le post 2 c'est pas bon car c'est basé sur celui qui est en topwindow(focus)
pour le post 5 ben je crois que ca fonctionnerait sur vb6 ou vb.net mais pas dans vba

en vba c'est object.[_GethWnd]
et ça ne fonctionne que sur les fenêtre enfant ayant un contexte (listbox,frame)
 

Dranreb

XLDnaute Barbatruc
Chez moi GetForegroundWindow fonctionne parfaitement.
Serait-ce quand même une histoire de poids fort du handle … trop fort ?
À tout hasard essaye :
VB:
Option Explicit
            #If VBA7 Then
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private PvHWnd As LongPtr
Public Function HWnd() As LongPtr
            #Else
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private PvHWnd As Long
Public Function HWnd() As Long
               #End If
   HWnd = PvHWnd
   End Function
Private Sub UserForm_Activate()
   PvHWnd = GetForegroundWindow
   End Sub
 

Discussions similaires

Statistiques des forums

Discussions
312 103
Messages
2 085 325
Membres
102 862
dernier inscrit
Emma35400