Adrian Savage
Adrian Savage

Reputation: 213

Form that was hidden on creation does not receive broadcast messages

I created a program intended to run a single instance, with a form that is hidden until a broadcast message is received. The bug is that the message is not received unless the form is shown on creation. Why is it necessary to show the form at this stage? I have knocked an example together. The first running instance of the program creates the form, further instances broadcast a message to it.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace HiddenProgram
{
public class Program : ApplicationContext
{
    [DllImport("user32")]
    static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

    [DllImport("user32")]
    static extern int RegisterWindowMessage(string message);

    const int HWND_BROADCAST = 0xffff;

    public static readonly int WM_SHOWME = Program.RegisterWindowMessage("com.holroyd.Gateway.Show");

    public static Program Instance;
    static Mutex mutex = new Mutex(true, "{9BFB3652-CCE9-42A2-8CDE-BBC40A0F5213}");

    MyForm form;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        if (!mutex.WaitOne(TimeSpan.Zero, true))
        {
            // Show the single instance window
            PostMessage(
                (IntPtr)HWND_BROADCAST,
                WM_SHOWME,
                IntPtr.Zero,
                IntPtr.Zero);
        }
        else
        {
            // Create the hidden window
            Instance = new Program();
            Application.Run(Instance);
            mutex.ReleaseMutex();
        }
    }

    Program()
    {
        form = new MyForm();
        form.FormClosing += form_FormClosing;

        // One of the following two seem necessary to get the broadcast message
        form.Show();
        //MainForm = form;
    }

    void form_FormClosing(object sender, FormClosingEventArgs e)
    {
        ExitThread();
    }
}

public class MyForm : Form
{
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Program.WM_SHOWME)
            Visible = !Visible;
        else
            base.WndProc(ref m);
    }
}
}

Upvotes: 0

Views: 606

Answers (1)

Adrian Savage
Adrian Savage

Reputation: 213

To create a form that remains hidden until a broadcast message is received, CreateHandle() is called from the form's constructor, in order to create the underlying window so that broadcast messages from other instances of the program are received.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace HiddenProgram
{
public class Program : ApplicationContext
{
    [DllImport("user32")]
    static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

    [DllImport("user32")]
    static extern int RegisterWindowMessage(string message);

    const int HWND_BROADCAST = 0xffff;

    public static readonly int WM_SHOWME = Program.RegisterWindowMessage("com.holroyd.Gateway.Show");

    static Mutex mutex = new Mutex(true, "{9BFB3652-CCE9-42A2-8CDE-BBC40A0F5213}");

    MyForm form;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        if (!mutex.WaitOne(TimeSpan.Zero, true))
        {
            // Show the single instance window
            PostMessage(
                (IntPtr)HWND_BROADCAST,
                WM_SHOWME,
                IntPtr.Zero,
                IntPtr.Zero);
        }
        else
        {
            // Create the hidden window
            Application.Run(new Program());
            mutex.ReleaseMutex();
        }
    }

    Program()
    {
        form = new MyForm();
        form.FormClosing += form_FormClosing;
    }

    void form_FormClosing(object sender, FormClosingEventArgs e)
    {
        ExitThread();
    }
}

public class MyForm : Form
{
    public MyForm()
    {
        CreateHandle();
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Program.WM_SHOWME)
            Visible = !Visible;
        else
            base.WndProc(ref m);
    }
}
}

Upvotes: 2

Related Questions