none
How to make MessageBox.Show() always on top on Windows Desktop?

    Question

  • I've an UI having CodeDom which calls my C# containing the MessageBox.Show().

     

    With this, somehow the MessageBox.Show() is not always on top but just like one of the window which my main UI can cover this message box.

     

    How can I make the MessageBox always on top even calling from another thread? Please help.

     

    If you have better idea to make my a.dll message box always on top, please share your idea as well.

     

    Any advice.

    Friday, May 23, 2008 10:51 AM

All replies

  • In order to ensure that MessageBox is on top of another specific window, you need to specify something for the IWin32Window owner parameter.

     

    In a multithreaded scenario, you could use Control.Invoke to run the code that shows the message box in the context of the GUI thread.

     

    Another technique would be to somehow pass the numeric window handle to the other thread.  Here is an example of this.  Note that using the Form directly in the thread (substitute this for nw in the call to MessageBox.Show) will not work due to a "Cross-thread operation not valid" error.

     

    Window handle example:

     

    Code Snippet

    private void button1_Click(object sender, EventArgs e)

    {

    System.Threading.Thread t = new System.Threading.Thread(Proc);

    t.Start(this.Handle);

    }

     

    private void Proc(object s)

    {

    NativeWindow nw = new NativeWindow();

    nw.AssignHandle((IntPtr)s);

    try

    {

    MessageBox.Show(nw, "Hello");

    }

    finally

    {

    nw.ReleaseHandle();

    }

    }

     

     

    Control.Invoke example:

     

    Code Snippet

    private void button2_Click(object sender, EventArgs e)

    {

    System.Threading.Thread t = new System.Threading.Thread(Proc2);

    t.Start();

    }

     

    private void Proc2()

    {

    this.Invoke((MethodInvoker) Invoker);

    }

     

    private void Invoker()

    {

    MessageBox.Show(this, "Hello");

    }

     

     

     

     

     

    Friday, May 23, 2008 2:21 PM
  • My MessageBox.Show() actually in csharpAssembly assembly (Main()) which gets executed by backgroundWorker.RunWorkerAsync().

     

    In csharpAssembly assembly, I tried to add this.Invoke() to csharpAssembly source code but this.Invoke() is not available.  I'm not too sure if it's because it's not the Form class.

     

    How to make the MessageBox.Show() always on top in this case?

     

    Thanks.  

     

    Code Snippet

    public class FormMain

    {

            private System.ComponentModel.BackgroundWorker backgroundWorker;

            private Assembly csharpAssembly;

     

           ....

            private bool Run()
            {
                bool runOk = false;

                object objToInvoke = csharpAssembly.CreateInstance(AssemblyEntryPointType);
                Type t = objToInvoke.GetType();
                MethodInfo mi = t.GetMethod("Main", BindingFlags.Static | BindingFlags.NonPublic);
                 

                 AddParams ap = new AddParams(mi, objToInvoke, null);
                 backgroundWorker.RunWorkerAsync(ap); 

                 

                 runOk = true;

     

                 return runOk;
               }

     

         private string AssemblyEntryPointType
            {
                get
                {
                    foreach (Type t in csharpAssembly.GetTypes())
                    {
                        if (t.GetMethod(SCRIPT_ENTRYPOINT, SCRIPT_BINDINGFLAGS) != null)
                            return t.FullName;
                    }

                }
            }

           ...

    }

     

     

     

    Saturday, May 24, 2008 9:33 AM
  • To use Control.Invoke, you need to pass a UI object (e.g., a reference to your main form) to the thread so that the thread can call Invoke using that UI object.

     

    An application can actually have more than one UI thread.  To perform an Invoke, the system needs a UI object so that it can identify which user interface thread should be used.

     

    Saturday, May 24, 2008 2:44 PM
  • One thing I am confused is where your suggestion should be coded, in csharpassembly assembly or in my FormMain class?

     

    If in FormMain, it has no info when MessageBox.Show() is called in csharpassembly assembly.

     

    If in the csharpassembly assembly, I don't know how to get UI object from the caller, i.e. FormMain class, to the csharpassembly assembly.  

     

    Do you have sample of your suggestion?

     

    Thanks.

     

    Saturday, May 24, 2008 3:23 PM