Вам для работы необходимо добавить класс SystemMenu.cs. Ну или взять код приведенный ниже и добавить его в форму(окно) в котором вы хотите добавить свои пункты! Но тут возникает два момента:
1) При добавлении класса SystemMenu.cs вы можете обращаться к нему из любой формы.
2) При добавлении кода показанного ниже, его необходимо будет добавлять в каждую форму где вы хотите добавить пункты меню!
3) Вам необходимо будет подключить пространства имен:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
Вот сам класс:
public class SystemMenu
{
public enum ItemFlags
{ // The item ...
mfUnchecked = 0x00000000, // ... is not checked
mfString = 0x00000000, // ... contains a string as label
mfDisabled = 0x00000002, // ... is disabled
mfGrayed = 0x00000001, // ... is grayed
mfChecked = 0x00000008, // ... is checked
mfPopup = 0x00000010, // ... Is a popup menu. Pass the
// menu handle of the popup
// menu into the ID parameter.
mfBarBreak = 0x00000020, // ... is a bar break
mfBreak = 0x00000040, // ... is a break
mfByPosition = 0x00000400, // ... is identified by the position
mfByCommand = 0x00000000, // ... is identified by its ID
mfSeparator = 0x00000800 // ... is a seperator (String and
// ID parameters are ignored).
}
public enum WindowMessages
{
wmSysCommand = 0x0112
}
// I havn't found any other solution than using plain old
// WinAPI to get what I want.
// If you need further information on these functions, their
// parameters, and their meanings, you should look them up in
// the MSDN.
// All parameters in the [DllImport] should be self explanatory.
// NOTICE: Use never stdcall as a calling convention, since Winapi
// is used.
// If the underlying structure changes, your program might cause
// errors that are hard to find.
// First, we need the GetSystemMenu() function.
// This function does not have an Unicode counterpart
[DllImport("USER32", EntryPoint = "GetSystemMenu", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr apiGetSystemMenu(IntPtr WindowHandle,
int bReset);
// And we need the AppendMenu() function. Since .NET uses Unicode,
// we pick the unicode solution.
[DllImport("USER32", EntryPoint = "AppendMenuW", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.Winapi)]
private static extern int apiAppendMenu(IntPtr MenuHandle, int Flags,
int NewID, String Item);
// And we also may need the InsertMenu() function.
[DllImport("USER32", EntryPoint = "InsertMenuW", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.Winapi)]
private static extern int apiInsertMenu(IntPtr hMenu, int Position,
int Flags, int NewId,
String Item);
private IntPtr m_SysMenu = IntPtr.Zero; // Handle to the System Menu
public SystemMenu()
{
}
// Insert a separator at the given position index starting at zero.
public bool InsertSeparator(int Pos)
{
return (InsertMenu(Pos, ItemFlags.mfSeparator |
ItemFlags.mfByPosition, 0, ""));
}
// Simplified InsertMenu(), that assumes that Pos is a relative
// position index starting at zero
public bool InsertMenu(int Pos, int ID, String Item)
{
return (InsertMenu(Pos, ItemFlags.mfByPosition |
ItemFlags.mfString, ID, Item));
}
// Insert a menu at the given position. The value of the position
// depends on the value of Flags. See the article for a detailed
// description.
public bool InsertMenu(int Pos, ItemFlags Flags, int ID, String Item)
{
return (apiInsertMenu(m_SysMenu, Pos, (Int32)Flags, ID, Item) == 0);
}
// Appends a seperator
public bool AppendSeparator()
{
return AppendMenu(0, "", ItemFlags.mfSeparator);
}
// This uses the ItemFlags.mfString as default value
public bool AppendMenu(int ID, String Item)
{
return AppendMenu(ID, Item, ItemFlags.mfString);
}
// Superseded function.
public bool AppendMenu(int ID, String Item, ItemFlags Flags)
{
return (apiAppendMenu(m_SysMenu, (int)Flags, ID, Item) == 0);
}
// Retrieves a new object from a Form object
public static SystemMenu FromForm(Form Frm)
{
SystemMenu cSysMenu = new SystemMenu();
cSysMenu.m_SysMenu = apiGetSystemMenu(Frm.Handle, 0);
if (cSysMenu.m_SysMenu == IntPtr.Zero)
{ // Throw an exception on failure
return null;
}
return cSysMenu;
}
// Reset's the window menu to it's default
public static void ResetSystemMenu(Form Frm)
{
apiGetSystemMenu(Frm.Handle, 1);
}
// Checks if an ID for a new system menu item is OK or not
public static bool VerifyItemID(int ID)
{
return (bool)(ID < 0xF000 && ID > 0);
}
}
Примеры как можно использовать данный класс:
private SystemMenu m_SystemMenu = null;
public const Int32 WM_SYSCOMMAND = 0x112;
private const int m_AboutID = 0x100;
private const int menu0 = 0x101;
private void frmMain_Load(object sender, System.EventArgs e)
{
m_SystemMenu = SystemMenu.FromForm(this);
m_SystemMenu.AppendSeparator();
m_SystemMenu.AppendMenu(m_AboutID, "About this...");
}
Далее работаем по образу и по подобию верхнего примера!
m_SystemMenu.InsertSeparator(0); m_SystemMenu.InsertMenu(0, menu0, "Menu");
m_SystemMenu.InsertMenu(menu1, SystemMenu.ItemFlags.mfBarBreak, 1, "ButtonBar1"); m_SystemMenu.AppendSeparator(); m_SystemMenu.InsertMenu(menu2, SystemMenu.ItemFlags.mfByPosition, 2, "ButtonBar2");
m_SystemMenu.InsertMenu(menu0, SystemMenu.ItemFlags.mfDisabled, 3, "ButtonBar3");

m_SystemMenu = SystemMenu.FromForm(this); m_SystemMenu.InsertMenu(m_AboutID, SystemMenu.ItemFlags.mfChecked, 3, "ButtonBar3");
Думаю примеров достаточно, теперь необходимо поймать события нажатия наших созданных пунктов меню! Смотрите пример ниже:
protected override void WndProc(ref Message msg)
{
if (msg.Msg == (int)SystemMenu.WindowMessages.wmSysCommand)
{
switch (msg.WParam.ToInt32())
{
case 3:
{
MessageBox.Show(this, "Test", "Menu3");
} break;
}
}
base.WndProc(ref msg);
}
Обратите внимание, если вы хотите поймать нажатие пункта меню созданной конструкцией:
m_SystemMenu.InsertMenu(menu0, SystemMenu.ItemFlags.mfDisabled, 3, "ButtonBar3");
То в конструкции switch-CASE вы указываете место(цифру) куда добавили пункт:
Если вы воспользовались конструкцией:
m_SystemMenu = SystemMenu.FromForm(this); m_SystemMenu.AppendSeparator(); m_SystemMenu.AppendMenu(m_AboutID, "About this...");
То указываете m_AboutID!
Также в каждой форме необходимо добавить класс обработки ошибок:
public class NoSystemMenuException : System.Exception
{
}
Исходник скачиваем тут: http://csharpcoderr.rusfolder.net/files/38306596
0.00 (0%) 0 votes















