Reputation: 213
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
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