Pobieranie tekstu z okna dialogowego, które nie używa formantu etykiety?

To jest kontynuacja mojego poprzedniego pytaniaJak wyłączyć okno dialogowe, zostanie wyświetlony serwer Inproc COM Server.

Tło:

Podsumowanie mojej sytuacji: Mam serwer COM Inproc napisany w Delphi z innej firmy. Jedna z wywoływanych funkcji wyświetli okno dialogowe z komunikatem o błędzie, jeśli przechwyci określony typ błędu. Problem polega na tym, że próbuję przetwarzać dane luzem, a źródło danych, z którego korzystam, powoduje, że okno dialogowe błędu pojawia się bardzo często (dzięki odpowiedzi z mojego poprzedniego pytania jest teraz automatycznie zamykane i mogłem go uruchomić wypełnienie, pokazałoby okno dialogowe i wymagało od kogoś naciśnięcia OK 9923 razy). Proces blokuje się, dopóki okno komunikatu nie zostanie zamknięte.

Pytanie:

Chciałbym mieć lepszą rejestrację tego, co powiedział dialog błędu. Jednak każda próba uzyskania tekstu głównego okna dialogowego nie powiodła się.

//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();

Pomyślałem, że mogłem przerwać okno dialogowe, zanim dodam do niego tekst (nie jest jeszcze w pełni pomalowany, gdy łamiemy powyższy kod). Jednak wprowadzenieApplication.DoEvents wewnątrz StartWindowListener przed uruchomieniem wyliczenie pozwala na pełne wyświetlenie okna dialogowego, ale nadal uzyskuję takie same wyniki, jak w przypadku powyższego kodu.

Wykonanie Ctrl-C działa poprawnie w oknie dialogowym, więc mógłbym użyć tego w szczyptę, ale ponieważ muszę powtórzyć to 9923 razy, chciałbym uniknąć używania tego programowo.

Czy są jakieś inne metody, które mogę spróbować pobrać z okna wiadomości?

questionAnswers(1)

yourAnswerToTheQuestion