Live-Forum - Die aktuellen Beiträge
Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Probleme mit FindwindowEx

Forumthread: Probleme mit FindwindowEx

Probleme mit FindwindowEx
30.11.2018 16:47:40
Theo
Hallo liebe Experten,
irgendwie bringt mich das automatisieren von Nicht-Office Anwendungen noch an den Rande des Wahnsinns. Ich nutze folgendes Macro um auf einem externen Fenster den "No" Knopf zu drücken:
Private Declare Function FindWindow Lib "user32.dll" _
Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32.dll" _
Alias "FindWindowExA" ( _
ByVal hWndParent As Long, _
ByVal hwndChildAfter As Long, _
ByVal lpszClass As String, _
ByVal lpszWindow As String) As Long
Sub CloseAutoLogoutMessages()
Dim hWnd As Long
Dim hbnd As Long
Dim blWindow As Boolean
blWindow = False
Do
hWnd = GetWindowHandle("SAP GUI for")
If hWnd > 0 Then
blWindow = True
BringWindowToTop (hWnd)
hbnd = FindWindowEx(hWnd, 0, "Button", "&No")
If hbnd > 0 Then
SendMessage hbnd, BM_CLICK, 0, 0
End If
End If
Loop While hWnd > 0
If blWindow Then
Application.Wait Now + TimeSerial(0, 0, 3)
End If
End Sub
Das Fensterhandle hWnd wird korrekt gefunden (deswegen habe ich Euch auch die Funktion GetWindowhandle erspart) - lediglich das FindWindowEx liefert 0 zurück. WinSpy++ liefert für den "No"-Button folgende Werte:
Userbild
Was mache ich falsch?
Vielen Dank im Voraus an dieses tolle Forum!
Theo
Anzeige

6
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Probleme mit FindwindowEx
30.11.2018 21:36:22
Karl-Heinz
Hallo Theo,
ich bin der Meinung, dass Du nichts falsch machst.
Aber ich erinnere mich daran, dass auch ich in früherer Zeit ebenfalls schon kurz vor dem Wahnsinn war mit dieser Funktion. (auch außerhalb von VBA)
Heute verwende ich die nur noch in bestimmten Fällen, also eher selten.
Um die/das Handle von Childwindows zu erhalten, gehe ich fast nur noch über EnumChildWindows.
Hierbei werden alle Child-Handles in ein Array geschafft und dann je nach Bedarf ausgewertet.
Das funktioniert wenigstens.
Vorerst aber auch mal der Tipp; versuch's auch mal über die ID (lt. Win-Spy ID=2):
hWndBtn = GetDlgItem(hWnd, ID)
Eigentlich für Dialogboxen vorgesehen, klappt das auch für andere Fenster, oft zumindest :-).
viele Grüße
Karl-Heinz
Anzeige
AW: Probleme mit FindwindowEx
01.12.2018 14:22:17
Theo
Hallo Karl-Heinz,
leider hat der Tipp mit der ID auch nicht geholfen :-(.
Wie machst Du das mit EnumChildWindows?
Gruß
Theo
AW: Probleme mit FindwindowEx
01.12.2018 16:16:52
Karl-Heinz
Hallo Theo,
mal ein Ansatz (direkt und ohne Array und ungetestet):
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal _
lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, _
ByVal wIndx As Long) As Long
Const GWL_ID = -12
Global bCheck As Boolean
Sub CloseAutoLogoutMessages()
Dim hWnd As Long
Dim hbnd As Long
Dim blWindow As Boolean
blWindow = False
bCheck = False
Do
hWnd = GetWindowHandle("SAP GUI for")
If hWnd > 0 Then
blWindow = True
BringWindowToTop (hWnd)
Call EnumChildWindows(hWnd, AddressOf EnumChilds, 0)
End If
If bCheck Then Exit Do
Loop While hWnd > 0
If blWindow Then
Application.Wait Now + TimeSerial(0, 0, 3)
End If
End Sub
Public Function EnumChilds(ByVal ChWnd&, ByVal lParam&) As Long
'Diese Funktion wird für jedes Child einmal direkt von Windows aufgerufen
If GetWindowLong(ChWnd, GWL_ID) = "2" Then
SendMessage ChWnd, BM_CLICK, 0, 0
End If
EnumChilds = 1
End Function
Hintergrund ist, dass nach Aufruf der Enum-Funktion für jedes Child von Windows die angegebene Callbackfunktion angesteuert wird.
Mit dem Handle kannst Du jetzt machen, was Du möchtest. In unserem Fall fische ich über GetWindowlong die ID des Childs raus und wenn sie passt, kommt der BM-Click. Fertig.
Natürlich kannst Du auch den Buttontext abfischen; ist aber ein wenig umfangreicher.
Schau mal, ob das jetzt klappt. Ich konnte es nicht testen.
VG KH
Anzeige
AW: Probleme mit FindwindowEx
01.12.2018 18:25:35
Karl-Heinz
Edit:
Public Function EnumChilds(ByVal ChWnd&, ByVal lParam&) As Long
'Diese Funktion wird für jedes Child einmal direkt von Windows aufgerufen
If GetWindowLong(ChWnd, GWL_ID) = 2 Then
SendMessage ChWnd, BM_CLICK, 0, 0
bCheck=true: EnumChilds = 0: Exit Function
End If
EnumChilds = 1
End Function
PS: ID muss natürlich eine Zahl und kein String sein, sorry.
Und müsste das nicht 'Loop While hWnd = 0' in Deiner Sub heißen. Sonst haut er doch ständig die Button-Clicks raus, oder?
VG KH
Anzeige
AW: Probleme mit FindwindowEx
01.12.2018 22:19:01
Theo
Hallo Karl-Heinz,
Dein PS hat mich auf die richtige Idee gebracht! Das Loop While hwnd > 0 war schon richtig, weil es mehrere SAP GUI Fenster geben kann, die alle durch den Click auf den No Button geschlossen werden. Der Fehler lag daran, dass ich das Fenster handle nicht durch exakte Übereinstimmung des Fenstertextes gesucht hatte, sondern auch einen partiellen Text erlaubt hatte. Die zu schliessenden Fenster hatten als Titel "SAP GUI for Windows 750" , offensichtlich gab es aber auch ein Fenster mit dem Titel: "SAP GUI for Windows 750 [/M/......". Das Findwindow hatte also immer nur dieses falsche Fenster gefunden, darauf keinen Button gefunden und deshalb das Fenster nicht geschlossen. Im nächsten Durchlauf wurde dann wieder das gleiche Fenster gefunden und nichts passierte. Nach der Änderung von GethandlefrompartialCaption auf die neue Funktion GetHandlefromFullCaption funkioniert mein ursprünglicher Code also einwandfrei!
Der Vollständigkeithalber hier die Funktionen die ich ursprünglich nicht mitgepostet hatte:
Public Function GetWindowHandle(WindowCaption As String) As Long
Dim lhWndP As Long
If GetHandleFromFullCaption(lhWndP, WindowCaption) = True Then
If IsWindowVisible(lhWndP) = True Then
'MsgBox "Found VISIBLE Window Handle: " & lhWndP, vbOKOnly + vbInformation
GetWindowHandle = lhWndP
Else
'MsgBox "Found INVISIBLE Window Handle: " & lhWndP, vbOKOnly + vbInformation
GetWindowHandle = lhWndP
End If
Else
'MsgBox "Window 'Window Caption' not found!", vbOKOnly + vbExclamation
End If
End Function
'hier die nue Function
Private Function GetHandleFromFullCaption(ByRef lWnd As Long, ByVal sCaption As String) As  _
Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromFullCaption = False
lhWndP = FindWindow(vbNullString, vbNullString)    'PARENT WINDOW
Do While lhWndP  0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
sStr = Left$(sStr, Len(sStr) - 1)
If sStr = sCaption Then
GetHandleFromFullCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
'das war die alte Funktion
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As  _
Boolean
Dim lhWndP As Long
Dim sStr As String
GetHandleFromPartialCaption = False
lhWndP = FindWindow(vbNullString, vbNullString)    'PARENT WINDOW
Do While lhWndP  0
sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
GetWindowText lhWndP, sStr, Len(sStr)
sStr = Left$(sStr, Len(sStr) - 1)
If InStr(1, sStr, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
Vielen Dank für die Bemühungen - ich denke ich habe viel gelernt!
Danke
Theo
Anzeige
AW: Probleme mit FindwindowEx
01.12.2018 22:39:06
Karl-Heinz
Hallo Theo,
vielen Dank für die Rückmeldung.
Ich sehe hier im Forum, war lange nicht dabei, auch immer wieder mal was Interessantes, was meine eigene Denkweise verbessern kann.
Und mit dem SAP R3 hatte ich mich auch bis 2010 herumgeschlagen. :-)
Eine gute Nacht noch. KH
;
Anzeige

Infobox / Tutorial

Probleme mit FindWindowEx in VBA


Schritt-für-Schritt-Anleitung

Hier ist eine einfache Schritt-für-Schritt-Anleitung, um das Problem mit FindWindowEx in VBA zu lösen:

  1. Füge die erforderlichen Deklarationen hinzu: Du solltest sicherstellen, dass die richtigen Funktionen deklariert sind, um auf die Windows API zuzugreifen.

    Private Declare Function FindWindow Lib "user32.dll" _
    Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
    
    Private Declare Function FindWindowEx Lib "user32.dll" _
    Alias "FindWindowExA" ( _
    ByVal hWndParent As Long, _
    ByVal hwndChildAfter As Long, _
    ByVal lpszClass As String, _
    ByVal lpszWindow As String) As Long
  2. Verwende die GetWindowHandle Funktion: Diese Funktion hilft dir, das Handle des gewünschten Fensters zu finden. Stelle sicher, dass du den vollständigen Fenstertitel verwendest.

    Public Function GetWindowHandle(WindowCaption As String) As Long
       Dim lhWndP As Long
       If GetHandleFromFullCaption(lhWndP, WindowCaption) = True Then
           GetWindowHandle = lhWndP
       End If
    End Function
  3. Implementiere die CloseAutoLogoutMessages Subroutine: Hier ist ein Beispiel, wie du die Subroutine implementieren kannst, um auf den "No"-Button zu klicken.

    Sub CloseAutoLogoutMessages()
       Dim hWnd As Long
       Dim hbnd As Long
       Do
           hWnd = GetWindowHandle("SAP GUI for Windows 750")
           If hWnd > 0 Then
               hbnd = FindWindowEx(hWnd, 0, "Button", "&No")
               If hbnd > 0 Then
                   SendMessage hbnd, BM_CLICK, 0, 0
               End If
           End If
       Loop While hWnd > 0
    End Sub

Häufige Fehler und Lösungen

  • Fehler: FindWindowEx gibt 0 zurück: Dies kann passieren, wenn das Fensterhandle nicht korrekt gefunden wird. Überprüfe, ob der Fenstertitel exakt mit dem übereinstimmt, was du suchst.

  • Lösung: Verwende die vollständige Beschreibung des Fensters: Oftmals ist es notwendig, die genaue Bezeichnung des Fensters zu verwenden, um sicherzustellen, dass FindWindowEx den richtigen Button findet.

  • Fehler bei der ID des Buttons: Wenn die ID des Buttons nicht korrekt ist, funktioniert der Klick nicht. Stelle sicher, dass du die richtige ID abfragst, indem du GetWindowLong verwendest.


Alternative Methoden

Eine häufige Alternative zu FindWindowEx ist die Verwendung der Funktion EnumChildWindows. Diese Methode ermöglicht es dir, alle Kindfenster eines bestimmten Fensters zu enumerieren und spezifische Aktionen auszuführen. Hier ist ein Beispiel:

Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

Public Function EnumChilds(ByVal ChWnd As Long, ByVal lParam As Long) As Long
   If GetWindowLong(ChWnd, GWL_ID) = 2 Then
       SendMessage ChWnd, BM_CLICK, 0, 0
   End If
   EnumChilds = 1
End Function

Praktische Beispiele

Hier sind einige praktische Beispiele, die dir helfen, FindWindowEx und EnumChildWindows erfolgreich anzuwenden:

  1. Schließen eines SAP-Fensters: Wenn du ein SAP-Fenster schließen möchtest, kannst du das folgende Beispiel verwenden:

    Sub CloseSAPWindow()
       Dim hWnd As Long
       hWnd = GetWindowHandle("SAP GUI for Windows 750")
       If hWnd > 0 Then
           ' Hier kannst du weitere Aktionen durchführen
       End If
    End Sub
  2. Verwenden von EnumChildWindows: Hier ist ein Beispiel, wie du alle Kindfenster durchlaufen kannst, um einen bestimmten Button zu klicken:

    Sub ClickButtonInChildWindows()
       Dim hWnd As Long
       hWnd = GetWindowHandle("Parent Window Title")
       Call EnumChildWindows(hWnd, AddressOf EnumChilds, 0)
    End Sub

Tipps für Profis

  • Verwende WinSpy++: Ein nützliches Tool, um die Fensterhierarchie und die Eigenschaften von Fenstern zu analysieren. Dies hilft dir, die richtigen Fenster-Handles und Button-IDs zu finden.

  • Optimierung der Fensterabfrage: Stelle sicher, dass du die Fensterabfragen optimierst, indem du die richtige Funktion für das Fensterhandle verwendest. Manchmal kann FindWindow effektiver sein als FindWindowEx.

  • Überprüfe die Sichtbarkeit von Fenstern: Manchmal sind Fenster nicht sichtbar, was bedeutet, dass du sie nicht ansprechen kannst. Verwende IsWindowVisible, um sicherzustellen, dass das Fenster sichtbar ist.


FAQ: Häufige Fragen

1. Was ist der Unterschied zwischen FindWindow und FindWindowEx?
FindWindow sucht nach einem Fenster mit einem bestimmten Titel, während FindWindowEx nach einem Kindfenster innerhalb eines bestimmten Elternfensters sucht.

2. Wie kann ich sicherstellen, dass mein Button-Klick funktioniert?
Überprüfe die ID und den Text des Buttons mit WinSpy++. Wenn diese korrekt sind, sollte der Klick erfolgreich sein.

3. Was tun, wenn EnumChildWindows nicht alle Fenster auflistet?
Stelle sicher, dass das Parent-Fenster korrekt identifiziert wird und dass es tatsächlich Kindfenster gibt, die aufgelistet werden können.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Entdecke mehr
Finde genau, was du suchst

Die erweiterte Suchfunktion hilft dir, gezielt die besten Antworten zu finden

Suche nach den besten Antworten
Unsere beliebtesten Threads

Entdecke unsere meistgeklickten Beiträge in der Google Suche

Top 100 Threads jetzt ansehen
Anzeige