Abrufen des Texts aus einem Dialogfeld, in dem kein Beschriftungssteuerelement verwendet wird?

Dies ist eine Fortsetzung meiner vorherigen FrageSo unterdrücken Sie ein Dialogfeld, das von einem Inproc COM-Server angezeigt wird.

Hintergrund:

Ein Rückblick auf meine Situation: Ich habe einen Inproc COM Server von einem Drittanbieter in Delphi geschrieben. Bei einer der von mir aufgerufenen Funktionen wird ein Dialogfeld mit einer Fehlermeldung angezeigt, wenn eine bestimmte Art von Fehler auftritt. Das Problem ist, dass ich versuche, Daten in großen Mengen zu verarbeiten, und die von mir verwendete Datenquelle dazu führt, dass das Fehlerdialogfeld häufig angezeigt wird (dank der Antwort auf meine vorherige Frage wird es jetzt automatisch geschlossen und ich konnte es ausführen) Nach Abschluss des Vorgangs hätte das Dialogfeld angezeigt und es wurde verlangt, dass jemand 9923-mal auf OK drückt. Der Prozess wird blockiert, bis das Meldungsfeld geschlossen wird.

Frage:

Ich hätte gerne eine bessere Protokollierung dessen, was der Fehlerdialog sagte. Der Versuch, den Nachrichtentext des Dialogfelds abzurufen, ist jedoch fehlgeschlagen.

//Snip

private void StartWindowListener()
{
    //Queue the watcher on the message pump if we are not watching.
    if (_watcherRunning == false)
    {
        _watcherRunning = true;
        _dummyForm.BeginInvoke(new Action(() =>
        {
            _watcherRunning = false;

            //If we are not inside the com object don't enumerate.
            if (_insideCom == false) return;

            // Enumerate windows to find dialogs
            EnumThreadWndProc callback = new EnumThreadWndProc(CheckWindow);
            EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
            GC.KeepAlive(callback);
        }));
    }
}

private bool CheckWindow(IntPtr hWnd, IntPtr lp)
{
    // Checks if hWnd is the expected dialog
    StringBuilder sb = new StringBuilder(260);
    GetClassName(hWnd, sb, sb.Capacity);
    if (sb.ToString() == "TMessageForm")
    {
        //This returns the dialog box's title
        GetWindowText(hWnd, sb, sb.Capacity);

        //This returns IntPtr.Zero
        var hDialogText = GetDlgItem(hWnd, 0xFFFF);
        if (hDialogText != IntPtr.Zero)
            GetWindowText(hDialogText, sb, sb.Capacity);

        //This returns a empty string
        GetDlgItemText(hWnd, 0xFFFF, sb, sb.Capacity);


        //Only sees the OK button.
        IntPtr hCtl = IntPtr.Zero;
        HashSet<IntPtr> seen = new HashSet<IntPtr>();
        while ((hCtl = GetNextDlgGroupItem(hWnd, hCtl, false)) != IntPtr.Zero)
        {
            //When we see the same control twice, break out of the loop.
            if (seen.Add(hCtl) == false)
                break;

            GetClassName(hCtl, sb, sb.Capacity);
            SendMessage(hCtl, WM_GETTEXT, sb.Capacity, sb)

            //Close the dialog by sending WM_CLOSE to the window
            SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }

         //Snip...
    }
    return true;
}

//Snip...

// P/Invoke declarations
const int WM_CLOSE = 0x0010;
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();

Ich dachte, ich hätte das Dialogfeld möglicherweise unterbrochen, bevor der Text hinzugefügt werden konnte (es ist noch nicht vollständig gezeichnet, wenn ich den obigen Code einsetze). Putting aApplication.DoEvents In StartWindowListener, bevor die Aufzählung gestartet wird, kann das Dialogfeld vollständig gezeichnet werden. Es werden jedoch immer noch die gleichen Ergebnisse wie mit dem obigen Code angezeigt.

Das Ausführen von Strg-C funktioniert im Dialogfeld ordnungsgemäß, sodass ich es zur Not verwenden kann. Da ich dies jedoch 9923 Mal wiederholen muss, möchte ich die programmgesteuerte Verwendung vermeiden.

Gibt es andere Methoden, mit denen ich versuchen kann, den Text aus dem Nachrichtenfeld abzurufen?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage