Debug window MS Office

cavo789 Messages postés 168 Date d'inscription vendredi 9 janvier 2004 Statut Membre Dernière intervention 28 juillet 2009 - 19 mars 2007 à 12:29
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 - 22 mars 2007 à 13:33
Bonjour

Je développe en VB 6 et en VBA.    En VB6, j'ai écris une toute grosse DLL qui reprend une multitude de classes que j'utilise ensuite; par exemple, en VBA MS Access ou Excel.

Dans ma DLL, j'ai prévu une variable publique bDebug qui, une fois initialisée à True, m'affiche une série de messages type debugging.  

Ma demande : j'aimerais que ma DLL puisse retrouver le handle de la fenêtre de debugging Debug Window de MS Excel (fenêtre qu'on obtient lorsqu'on appuie sur CTRL-G).   Une fois le handle de la fenêtre trouvée (ça je sais le faire), permettre d'écrire dans cette fenêtre.

Pour dire les choses autrement : en VBA, je peux faire un Debug.Print "Blabla".   Je voudrais que ma DLL puisse faire la même chose et que l'output arrive dans la Debug Window de Excel.

Quelqu'un a-t-il une idée ?

Merci.

Christophe

10 réponses

drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
19 mars 2007 à 13:34
Salut, si j'ai bien compris tu cherches un handle! Si tu connais le titre de cette fenêtre cette API devrai suffir:

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

· lpClassName
Points to a null-terminated string that specifies the class name or is an atom that identifies the class-name string. If this parameter is an atom, it must be a global atom created by a previous call to the GlobalAddAtom function. The atom, a 16-bit value, must be placed in the low-order word of lpClassName; the high-order word must be zero.


· lpWindowName
Points to a null-terminated string that specifies the window name (the window’s title). If this parameter is NULL, all window names match.

Exemple:
FindWindow(vbNullString, "PDFCreator 0.9.0")





 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
19 mars 2007 à 13:35
petite erreur, exemple:

Dim Hwnd as Long
Hwnd = FindWindow(vbNullString, "PDFCreator 0.9.0")

 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
cavo789 Messages postés 168 Date d'inscription vendredi 9 janvier 2004 Statut Membre Dernière intervention 28 juillet 2009 1
20 mars 2007 à 13:05
Merci Drikce06.    Tu as bien compris.   Le stud', c'est que j'ai réussi à trouver le handle de la fenêtre (ainsi j'arrive à changer le Caption "Debug Window" vers autre chose).

Ce que je n'arrive pas à faire, c'est de capturer le handle de la zone texte : cette fenêtre semble n'avoir qu'un seul contrôle et c'est une zone texte.   C'est la zone dans laquelle il faut que je puisse écrire.   J'ai déjà essayé avec un SendMessage et un WM_SETTEXT mais sans succès.

Si quelqu'un avait un truc qui me permettrait de commencer...  

Christophe
0
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
20 mars 2007 à 13:16
Salut, mon exemple servait à trouver le handle de la fenêtre mère à partie du titre, maintenant il faut récupérer le handle du contrôle soit une fenêtre enfant! J'ai déjà fait ce genre de truc, je recherhce ce que j'avais fait et je vois ça, après de là à ce que ça marche!

 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
20 mars 2007 à 13:35
Voici un exemple c'est en .Net donc peut-être des modifs à faire pour VB6 notament pour les API remplacer les Integer par des Long.

Ici je cherchai la fenêtre PDF Creator et appuyer sur le bouton "enregistrer"! Pour plus de précision sur les api va sur www.allapi.net et télécharge APIGuide.

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, _
 ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Object) As Integer

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)

Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
    (ByVal hwnd As Integer) As Integer
    
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, _
    ByVal lpString As String, ByVal cch As Integer) As Integer

Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Integer) As Integer

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

Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Integer, _
    ByVal lpString As String) As Integer

Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Integer, _
    ByVal wFlag As Integer) As Integer
    
Sub recherche()

Dim hwnd, hwnd1 As Integer
Dim NbChr As Integer

'cherche la fenêtre parent par son titre
hwnd = FindWindow(vbNullString, "PDFCreator 0.9.0")

'la met au premier plan
SetForegroundWindow (hwnd)

'pause
Sleep (100)

'cherhce les fenêtres enfants (contrôle)
hwnd1 = GetWindow(hwnd, GW_CHILD)

'pause
Sleep (100)

'Boucle sur tous les contrôles
Do While hwnd <> 0

'pause
Sleep (100)

Dim MyStr As String
MyStr = ""

'cherche le nombre de caractère du titre du contrôle
NbChr = GetWindowTextLength(hwnd1)

'création buffer
MyStr = MyStr.PadLeft(NbChr)

'cherche son titre
Call GetWindowText(hwnd1, MyStr, NbChr + 1)

'si le titre correspond
If MyStr = "Enregistrer" Then

'mettre la fenêtre enfant au premier plan (ici focus sur un boutton)
SetForegroundWindow (hwnd1)

'simulation d'un click
Call SendMessage(hwnd1, WM_LBUTTONDOWN, 0, 0)
Call SendMessage(hwnd1, WM_LBUTTONUP, 0, 0)

Exit Do

End If

'cherhce une autre fenêtre enfant
hwnd1 = GetNextWindow(hwnd1, GW_HWNDNEXT)

 Loop
 
End Sub,

----

(Coloration syntaxique automatique par Kenji)











 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
cavo789 Messages postés 168 Date d'inscription vendredi 9 janvier 2004 Statut Membre Dernière intervention 28 juillet 2009 1
20 mars 2007 à 13:50
Je vais essayer.   MERCI !

Christophe
0
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
20 mars 2007 à 14:03
  Désolé, j'avais oublié pas mal de truc et là je l'ai arangé pour qu'il soit compatible avec VB6 (je l'ai fais en VBA), j'ai essayé en lançant la commande: démarrer > executé. ça ouvre la fenêtre et à partir de là je cherche à appuyer sur le boutton OK. 

 Const GW_HWNDFIRST = 0
    Const GW_HWNDLAST = 1
    Const GW_HWNDNEXT = 2
    Const GW_HWNDPREV = 3
    Const GW_CHILD = 5
    Const WM_LBUTTONDOWN = 513
    Const WM_LBUTTONUP = 514
    
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
    (ByVal hwnd As Long) As Long
    
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
    ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

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

Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, _
    ByVal lpString As String) As Long

Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, _
    ByVal wFlag As Long) As Long
        
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal wCmd As Long) As Long
    
Sub recherche()

Dim hwnd, hwnd1 As Long
Dim NbChr As Long

'cherche la fenêtre parent par son titre
hwnd = Int(FindWindow(vbNullString, "Exécuter"))

'la met au premier plan
SetForegroundWindow (hwnd)

'pause
Sleep (100)

'cherhce les fenêtres enfants (contrôle)
hwnd1 = GetWindow(hwnd, GW_CHILD)

'pause
Sleep (100)

'Boucle sur tous les contrôles
Do While hwnd <> 0

'pause
Sleep (100)

Dim MyStr As String

'cherche le nombre de caractère du titre du contrôle
NbChr = GetWindowTextLength(hwnd1)

MyStr = String(NbChr + 1, Chr$(0))

'cherche son titre
Call GetWindowText(hwnd1, MyStr, NbChr + 1)

'si le titre correspond
If Left(MyStr, 2) = "OK" Then

'mettre la fenêtre enfant au premier plan (ici focus sur un boutton)
SetForegroundWindow (hwnd1)

'simulation d'un click
Call SendMessage(hwnd1, WM_LBUTTONDOWN, 0, 0)
Call SendMessage(hwnd1, WM_LBUTTONUP, 0, 0)

Exit Do

End If

'cherhce une autre fenêtre enfant
hwnd1 = GetNextWindow(hwnd1, GW_HWNDNEXT)

 Loop
 
End Sub

Private Sub CommandButton1_Click()
Call recherche
End Sub,

----

(Coloration syntaxique automatique par Kenji)







 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
cavo789 Messages postés 168 Date d'inscription vendredi 9 janvier 2004 Statut Membre Dernière intervention 28 juillet 2009 1
22 mars 2007 à 11:57
Drikce

J'ai utilisé ton code et l'ai un tout petit peu adapté.    Il retrouve bien le handle de la fenêtre et, malheureusement, aucun autre handle ==> il semble ne pas y avoir de fils or cette fenêtre contient une zone texte.

Voici comme j'ai testé :
<li>Je lance Excel</li><li>J'appuie sur ALT-F11 pour passer en VBA</li><li>Je crée un nouveau module</li><li>Je copy/paste le code ci-dessous</li><li>J'appuie sur CTRL-G pour afficher la "Immediate" window (c'est ce que j'appelais à tort la Debug window)</li><li>Je lance la subroutine Recherche</li>Le handle de la Immediate window est bien trouvé et pas celui de la zone texte dans cette fenêtre.

Pour rappel, j'aimerais justement pouvoir récupérer cette zone texte de telle manière qu'avec l'API SetWindowText ou SendMessage je puisse écrire dans données dans cette fenêtre; exactement comme le fait Debug.Print en VBA.

Je ne peux pas utiliser Debug.Print car c'est une DLL VB que j'ai développé qui doit pouvoir écrire dans cette fenêtre.

Une fois encore, un très grand merci pour l'aide déjà apportée.

Christophe

Option Explicit

Const GW_HWNDNEXT = 2
Const GW_CHILD = 5

Public Declare Function lstrlen Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
    (ByVal hwnd As Long) As Long
    
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
    ByVal lpString As String, ByVal cch As Long) As Long

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

Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, _
    ByVal wFlag As Long) As Long
        
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal wCmd As Long) As Long
    
Private Function TrimNull(sTemp As String) As String
   TrimNull = Left$(sTemp, lstrlen(StrPtr(sTemp)))
End Function
    
Sub recherche()

Dim hwnd, hwnd1 As Long
Dim NbChr As Long
Dim MyStr As String

   ' Cherche la fenêtre parent par son titre

   hwnd = Int(FindWindow(vbNullString, "Immediate"))

   ' Cherche les fenêtres enfants (contrôle)
   
   hwnd1 = GetWindow(hwnd, GW_CHILD)

   ' Pause
   
   Sleep (100)

   ' Boucle sur tous les contrôles
   
   Do While hwnd1 <> 0

      ' Pause
      
      Sleep (100)

      ' Cherche le nombre de caractère du titre du contrôle
      
      NbChr = GetWindowTextLength(hwnd1)

      MyStr = String(NbChr + 1, Chr$(0))

      ' Cherche son titre
      
      Call GetWindowText(hwnd1, MyStr, NbChr + 1)

      Debug.Print hwnd1 & "*" & TrimNull(MyStr) & "__" & Now()
      
      ' Cherche une autre fenêtre enfant
      
      hwnd1 = GetNextWindow(hwnd1, GW_HWNDNEXT)

   Loop
 
End Sub(Coloration syntaxique automatique par Kenji)
0
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
22 mars 2007 à 13:05
Il faudrai essayer de passer par la recherche de la classe de la zone de text avec Classename! Je regarde ça.

 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
drikce06 Messages postés 2236 Date d'inscription lundi 29 mai 2006 Statut Membre Dernière intervention 29 mai 2008 10
22 mars 2007 à 13:33
'Toujours mon exemple avec la fenêtre exécuter dans démarrer > exécuter
'je cherche la combobox par le nom de sa classe
'je suppose que pour toi la classe que tu cherche est de type TextBox


Const GW_HWNDNEXT = 2
Const GW_CHILD = 5


Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long


Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _
ByVal lpClassName As String, ByVal nMaxCount As Long) As Long


Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
   
Private Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, _
    ByVal wFlag As Long) As Long
   
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal wCmd As Long) As Long
   
Private Sub CommandButton1_Click()


Dim hwnd, hwnd1 As Long
Dim NbChr As Long
Dim MyStr As String
Dim lpClassName As String


' Cherche la fenêtre parent par son titre
 hwnd = Int(FindWindow(vbNullString, "Exécuter"))
  
   hwnd1 = GetWindow(hwnd, GW_CHILD)


   Sleep (100)


   Do While hwnd1 <> 0


      Sleep (100)


    lpClassName = Space(256)
    NbChr = GetClassName(hwnd1, lpClassName, 256)
    lpClassName = Left$(lpClassName, NbChr)


If lpClassName = "ComboBox" Then


     SetForegroundWindow (hwnd1)


End If
 
      hwnd1 = GetNextWindow(hwnd1, GW_HWNDNEXT)


   Loop
 
End Sub

 Drikce 06

Si la réponse vous convient: Réponse acceptée. Si la réponse vous convient pas:
0
Rejoignez-nous