Ich habe eine Lösung für das Problem gefunden. Erscheint mir zwar etwas umständlich, aber es funktioniert. Ich nutze EnumWindows anstelle von EnumChildWindows und vergleiche die Prozess-ID, um eine eindeutige Zugehörigkeit des Dialogs zur eigentlichen Anwendung festzustellen.
Ich habe das ganze mal am Beispiel von Notepad getestet, in dem ich über das Menü den Öffnen-Dialog geöffnet und das Handle ermittelt habe. Damit konnte ich dann einen Dateinamen angeben und den Dialog bestätigen, so dass die Datei automatisch geöffnet wurde.
Auf dieser Grundlage schaffe ich es die gewünschte Anwendung teilweise fernzusteuern.
' API Deklarationen entfernt, weil ansonsten Nachricht zu groß ist.
Private hDialog As IntPtr
Private processId As Integer
Private Function EnumAllWindows(ByVal hWnd As IntPtr, ByRef lpData As _
IntPtr) As Boolean
Dim className As New System.Text.StringBuilder("", 256)
Dim windowName As New System.Text.StringBuilder("", 256)
Dim handleProcessId As Integer = 0
' ClassName, Titel und Prozess-ID des Handles ermitteln.
GetClassName(hWnd, className, 256)
GetWindowText(hWnd, windowName, 256)
GetWindowThreadProcessId(hWnd, handleProcessId)
If className.ToString = "#32770" AndAlso windowName.ToString = "Öffnen" _
AndAlso processId = handleProcessId Then
hDialog = hWnd
Return False
Else
Return True
End If
End Function
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles btnTest.Click
Dim p As Process = Process.GetProcessesByName("notepad")(0)
If p IsNot Nothing Then
processId = p.Id
hDialog = IntPtr.Zero
' Prozess-Handle und Handle des MenuItems ermitteln.
Dim hMain As IntPtr = p.MainWindowHandle
Dim hMenuItem As IntPtr = GetSubMenu(GetMenu(hMain), 0)
Dim hMenuItemId As IntPtr = GetMenuItemID(hMenuItem, 1)
' Fenster in den Vordergrund holen und MenuItem "klicken".
SetForegroundWindow(p.MainWindowHandle)
PostMessage(hMain, &H111, hMenuItemId, IntPtr.Zero)
' Zeit für einen TimeOut festlegen, da nicht garantiert ist, dass
' das Handle des Dialogs
' beim ersten Aufruf von EnumWindows erzeugt wurde.
Dim endTime As DateTime = Date.Now.AddMilliseconds(100)
Do While Date.Now < endTime AndAlso hDialog = IntPtr.Zero
EnumWindows(New EnumWindowsDelegate(AddressOf EnumAllWindows), _
IntPtr.Zero)
Loop
' Handle des Dialogs wurde gefunden.
If hDialog <> IntPtr.Zero Then
Debug.WriteLine(hDialog.ToString)
' Sonstiger Code zum Öffnen der Datei. (Dateiname in das
' Textfeld eingeben, Dialog bestätigen.)
End If
End If
End Sub |