Домой WINAPI Добавляем свои кнопки в заголовок окна Windows Form(WinAPI): Справочник по C#

Добавляем свои кнопки в заголовок окна Windows Form(WinAPI): Справочник по C#

1015
0



Вам для работы необходимо добавить класс 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!

ЧИТАТЬ ТАКЖЕ:  Перезагрузка удалённой ПЭВМ через shutdown.exe: Справочник по C#

Также в каждой форме необходимо добавить класс обработки ошибок:

public class NoSystemMenuException : System.Exception
{
}

Исходник скачиваем тут: http://csharpcoderr.rusfolder.net/files/38306596

Добавляем свои кнопки в заголовок окна Windows Form(WinAPI): Справочник по C#

0.00 (0%) 0 votes

ОСТАВЬТЕ ОТВЕТ

Пожалуйста, введите ваш комментарий!
пожалуйста, введите ваше имя здесь