I want to add the age old About menu item to my application. I want to add it to the 'system menu' of the application (the one which pops up when we click the application icon in the top-left corner). So, how can I do it in .NET?
Windows makes it fairly easy to get a handle to a copy of the form's system menu for customization purposes with the GetSystemMenu
function. The hard part is that you're on your own to perform the appropriate modifications to the menu it returns, using functions such as AppendMenu
, InsertMenu
, and DeleteMenu
just as you would if you were programming directly against the Win32 API.
However, if all you want to do is add a simple menu item, it's really not all that difficult. For example, you would only need to use the AppendMenu
function because all you want to do is add an item or two to the end of the menu. Doing anything more advanced (like inserting an item in the middle of the menu, displaying a bitmap on the menu item, showing menu items checked, setting a default menu item, etc.) requires a bit more work. But once you know how it's done, you can go wild. The documentation on menu-related functions tells all.
Here's the complete code for a form that adds a separator line and an "About" item to the bottom of its system menu (also called a window menu):
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class CustomForm : Form
{
// P/Invoke constants
private const int WM_SYSCOMMAND = 0x112;
private const int MF_STRING = 0x0;
private const int MF_SEPARATOR = 0x800;
// P/Invoke declarations
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);
// ID for the About item on the system menu
private int SYSMENU_ABOUT_ID = 0x1;
public CustomForm()
{
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
// Get a handle to a copy of this form's system (window) menu
IntPtr hSysMenu = GetSystemMenu(this.Handle, false);
// Add a separator
AppendMenu(hSysMenu, MF_SEPARATOR, 0, string.Empty);
// Add the About menu item
AppendMenu(hSysMenu, MF_STRING, SYSMENU_ABOUT_ID, "&About…");
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// Test if the About item was selected from the system menu
if ((m.Msg == WM_SYSCOMMAND) && ((int)m.WParam == SYSMENU_ABOUT_ID))
{
MessageBox.Show("Custom About Dialog");
}
}
}
And here's what the finished product looks like: