How to suppress a dialog box displayed by code that I can't change?

前端 未结 2 1124
一个人的身影
一个人的身影 2020-11-28 15:36

I have a Inproc COM Server from a 3rd party. One of the functions I call will display a error message dialog box if it traps a specific type of error. The issue is I am tryi

相关标签:
2条回答
  • 2020-11-28 15:57

    First of all, it would certainly be better if the COM server itself could be turned into mode when it does not let caller down with undesired UI action. Provided that you cannot alter third party component behavior, what you still can do is hooking message processing and forced closing of the message box.

    Before doing the call on the third party server, you can install a message hook with SetWindowsHookEx and WH_CALLWNDPROC and your callback will be able to monitor the messages. In particular you will be able to post messages, hook dialog's WindowProc etc. Including certainly programmatic closing of the message box.

    0 讨论(0)
  • 2020-11-28 16:05

    A message box pumps a message loop. That's something you can take advantage of, it allows you to inject code with Control.BeginInvoke() that runs as soon as the message box appears. You can then use that code to find the dialog window and close it. Add a new class to your project and paste this code:

    using System;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    public class DialogCloser : IDisposable {
        public DialogCloser() {
            if (Application.OpenForms.Count == 0) throw new InvalidOperationException();
            Application.OpenForms[0].BeginInvoke(new Action(() => {
                // Enumerate windows to find dialogs
                if (cancelled) return;
                EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
                EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
                GC.KeepAlive(callback);
            }));
        }
    
        public void Dispose() {
            cancelled = true;
        }
    
        private static bool checkWindow(IntPtr hWnd, IntPtr lp) {
            // Checks if <hWnd> is a Windows dialog
            StringBuilder sb = new StringBuilder(260);
            GetClassName(hWnd, sb, sb.Capacity);
            if (sb.ToString() == "#32770") {
                // Close it by sending WM_CLOSE to the window
                SendMessage(hWnd, 0x0010, IntPtr.Zero, IntPtr.Zero);
            }
            return true;
        }
    
        private bool cancelled;
    
        // P/Invoke declarations
        private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
        [DllImport("user32.dll")]
        private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();
        [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);
    }
    

    Sample usage:

    private void button1_Click(object sender, EventArgs e) {
        using (new DialogCloser()) {
            // Replace this with the call to the COM server method:
            MessageBox.Show("you never see this");
        }
    }
    
    0 讨论(0)
提交回复
热议问题