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: 8

patricktoulon

XLDnaute Barbatruc
re
UF(1).Hwnd
ca ne fonctionne pas (cette propriété n'existe pas en vba pour un userform pas avec un excel en 32 bit en tout cas

et UF(1). contrôle.setfocus?
ben c'est ce que je viens de dire

il faut pas lire en diagonale robert 🤣

cela dit c'est décevant que je soit obligé d'activer une fenêtre pour correctement la cibler
 

dysorthographie

XLDnaute Accro
Il suffit de dire que UF(1).Hwnd existe pour qu'elle existe
dans le UserForm!
Code:
Public HWnd As Long
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
    
Public HWnd As Long
Private Declare Function GetActiveWindow Lib "user32" () 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()
HWnd = GetUserFormHandle(Me)
End Sub
 
Dernière édition:

dysorthographie

XLDnaute Accro
Bien sur que tu m'a perdu
Tu dis qu'avec FindWindow tu n'arrives pas à récupérer la bonne instance alors qu'avec un setfocus sur un contrôle tu y arrives !

Je suis perplexe comment faire un setfocus sur la bonne fenêtre alors que tu ne la trouve pas avec FindWindow?

Je te rappel pour ce qui me concerne Public HWnd As Long est univoque avec FindWindow

Comment gères tu ton setfocus ?
 

Dranreb

XLDnaute Barbatruc
oui ça implique que je doive faire cela pour tout les instances donc mémoriser x handles
C'est le Show qui le détermine sans qu'on soit obligé de s'en occuper de l'extérieur et il est conservé en propre par chaque exemplaire et resservi comme sa propriété HWnd en lecture seule (c'est en effet une Function Public chez moi, non une variable Public de l'UserForm).

Exemple dérivé de ton classeur :

Aïe ! Ils ont le même HWnd !!?

Avec un DoEvents derrière le Show du 1er ça a l'air de se passer mieux. Mais c'est très inattendu pour moi ! On dirait que Windows est averti trop tard du changement de fenêtre au premier plan. En tout cas c'est quelque chose de ce genre.

À la réflexion, ce sont plutôt les Private Sub UserForm_Activate() qui sont exécutées après la Sub testmultipleInstance et c'est à ce moment la le UF(2) qui est en avant plan pour les deux …
 

Pièces jointes

  • ExercicePropriétéHWnd.xlsm
    18.5 KB · Affichages: 5
Dernière édition:

dysorthographie

XLDnaute Accro
Bonjour,
Si tu changes le captions avant le FindWindow il n'y a plus de problème !
Code:
S = GetGUID()

    OrigCaption = UF.Caption
    UF.Caption = S
    GetUserFormHandle = FindWindow(vbNullString, S)
    UF.Caption = OrigCaption
Et tu Stock le résultat dans la variable public de ton userform
Code:
Private Sub UserForm_Initialize()
HWnd = GetUserFormHandle(Me)
End Sub

Maintenant si tu ne veux pas implémenter tous ça dans ton userform tu déplacement le code dans un module standard et utiliser le tag du userform pour y stocker le HWnd!
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
bonjour @Dranreb
ben oui c'est toujours le dernier affiché qui est en avant plan
je viens de comprendre ton uf(x).hwnd en fait c'est une variable public dans le userform je suis vraiment bete des fois 😂d'autant plus que c'est une méthode que j'utilise le plus souvent

donc oui comme ca pas de soucis ca fonctionne mais pour les userforms
pour des fenêtres autres lancées par vba c'est plus compliqué
 

Dranreb

XLDnaute Barbatruc
C'est une Function Public plus exactement, donc une propriété en lecture seule.
La seule complication inattendue sur laquelle je suis tombé c'est que lorsque les UserForm sont affichés non modal leurs Sub UserForm_Activate sont exécutées après que la procédure principale soit terminée, de sorte qu'alors c'est le dernier affiché qui est en avant plan. Mais comme vu dans mon dernier classeur du #21, on s'en affranchit aisément par une instruction DoEvents qui impose son exécution immédiate.
 
Dernière édition:

Discussions similaires

  • Résolu(e)
Microsoft 365 32 ou 64 bits
Réponses
46
Affichages
2 K

Membres actuellement en ligne

Statistiques des forums

Discussions
314 729
Messages
2 112 271
Membres
111 481
dernier inscrit
zrk