Use C # and local Windows APIs to manipulate system menus

Source: Internet
Author: User

I. Preface

The. NET Framework is a very new technology in the Windows application field. It is certain that in the future,. NET applications must interact with existing Windows technologies. This interaction is mainly reflected in two areas: COM and application programming interfaces (APIS ). To this end, the. NET Framework provides an OO layer on Windows APIs, but sometimes it may need to be called using an API that is not reachable by. NET. In this case, you can use the. NET platform call (P/Invoke) mechanism to call C or C ++ functions from. NET. Because Windows API functions are in DLL, P/Invoke provides a general mechanism for Calling C or C ++ functions in DLL from. NET code.

This article targets C #. NET does not provide direct SystemMenu-like attributes or GetSystemMenu-like member functions, compile a C # class SystemMenu to implement traditional operations on the system menu, this is done by calling the local Windows API.

  II. Introduction to system menus

When you click the window icon or right-click the window title bar, the system menu is displayed. It contains the default behavior of the current window. The system menu of different windows looks a little different, for example, the system menu of a normal window looks different from the menu of a toolbar subdialog box.

Benefits of modifying the system menu:

· Add menu items defined by the application.

· When WW is minimized, SS is a good place to place actions and can be accessed, Because SS can be displayed by right-clicking the taskbar window icon.

· Deploy a menu item, for example, remove "maximize" from the system menu, "minimize", and "close. This change also affects the three buttons in the upper-right corner of the window, so this is a good way to make the "X" in the upper-right corner of the window lose its capacity.

Operating System Menu

By calling the API function GetSystemMenu, you can retrieve a copy of the System menu. The second parameter of the function indicates whether you want to reset the system menu to its default state. With the addition of several API menu functions such as AppendMenu and InsertMenu, You can flexibly control the system menu.

Next I will only briefly introduce how to add menu items and how to implement interaction between new projects and users.

Iii. Introduction to the SystemMenu class


The implementation of the SystemMenu class makes it much easier to access the entire system menu. You can use this class to modify the menu of a window. You get an object by calling the static member function FromForm. This function requires a Form object or a class inherited from Form as its parameter. Then it creates a new object. Of course, if the GetSystemMenu API call fails, a NoSystemMenuException will be thrown.

Note that each Windows API menu function requires a menu handle to facilitate operations. Because the menu handle is actually a C ++ pointer, you need to use IntPtr to operate it in. NET. Many functions also require a single bit mask to indicate the actions or forms of a single dish. Fortunately, you don't have to use a series of bitmask flag definitions through the inclusion of a header file, as in VC ++ ,. NET provides a ready-made public enumeration class ItemFlags. The following describes several important members of this class:

· MfString-indicates that the subsystem displays the string passed by the "Item" parameter in the menu Item.

· MfSeparator-the "ID" and "Item" parameters are ignored.
  
· MfBarBreak-this function is the same as mfBreak when used for menu bar. When used for drop-down menus, submenus, or shortcut menus, the new column and the old one are separated by a vertical line.

· MfBreak-place the current project in a new line (menu bar) or a new column (drop-down menu, sub menu or shortcut menu ).

NOTE: If multiple flag is specified, use the bitwise operator | (OR) to connect. For example:

// A menu item "Test" will be created and this item will be selected (checked)

MySystemMenu. AppendMenu (myID, "Test", ItemFlags. mfString | ItemFlags. mfChecked );

The "Item" parameter specifies the text to be displayed in the new Item. Its ID must be a unique number to mark this menu Item.

Note: Make sure that the ID of the new item is greater than 0 and less than 0XF000. Because the range greater than or equal to 0XF000 is reserved for system commands. You can also call the static VerifyItemID method of SystemMenu to verify whether your ID is correct.

In addition, there are two constants to be interpreted: mfByCommand and mfByPosition.

First, mfByCommand is used by default. Second, the explanation of "Pos" depends on these flags: If you specify mfByCommand, the "Pos" parameter is the ID of the previous item inserted in the new project; if you specify mfByPosition, the "Pos" parameter is the relative position of the new item starting with 0 index. If it is-1 and mfByPosition is specified, the item will be inserted to the end. This is why AppendMenu () can be replaced by InsertMenu.



   Iv. SystemMenu code analysis

Using System;
Using System. Windows. Forms;
Using System. Diagnostics;
Using System. Runtime. InteropServices;

Public class NoSystemMenuException: System. Exception
{}

// These values are from MSDN

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

// 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
}

//
// Helps to define the class of the Operating System Menu
///.
// Note: when using P/Invoke to call a non-hosted function in the dynamic link library, perform the following steps:
// 1. Locate the DLL that contains the function.
// 2. Load the DLL library into the memory.
// 3. Find the address of the function to be called and press all the functions into the stack.
// 4. Call the function.
//

Public class SystemMenu
{
// Tip: C # declare the function as external and use the DllImport attribute to specify the DLL
// And any other parameters that may be required.
// First, we need the GetSystemMenu () function.
// Note that this function does not have a Unicode version

[DllImport ("USER32", EntryPoint = "GetSystemMenu", SetLastError = true,
CharSet = CharSet. Unicode, ExactSpelling = true,
CallingConvention = CallingConvention. Winapi)]
Private static extern IntPtr apiGetSystemMenu (IntPtr restart whandle,
Int bReset );



// AppendMenu () is also required (). Since. NET uses Unicode,
// We should select its Unicode version.

[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 );

// You may also need InsertMenu ()

[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; // System menu handle

Public SystemMenu ()
{}

// Insert a separator at a given position (starting with 0 as the index value)

Public bool InsertSeparator (int Pos)
{
Return (InsertMenu (Pos, ItemFlags. mfSeparator | ItemFlags. mfByPosition, 0 ,""));
}

// Simplified InsertMenu (), provided that the Pos parameter is a relative index position starting with 0

Public bool InsertMenu (int Pos, int ID, String Item)
{
Return (InsertMenu (Pos, ItemFlags. mfByPosition | ItemFlags. mfString, ID, Item ));
}

// Insert a menu item at a specified position. The specific Insert Location depends on Flags.

Public bool InsertMenu (int Pos, ItemFlags Flags, int ID, String Item)
{
Return (apiInsertMenu (m_SysMenu, Pos, (Int32) Flags, ID, Item) = 0 );
}

// Add a separator

Public bool AppendSeparator ()
{
Return AppendMenu (0, "", ItemFlags. mfSeparator );
}

// Use ItemFlags. mfString as the default value

Public bool AppendMenu (int ID, String Item)
{
Return AppendMenu (ID, Item, ItemFlags. mfString );
}

// The replaced Function

Public bool AppendMenu (int ID, String Item, ItemFlags Flags)
{
Return (apiAppendMenu (m_SysMenu, (int) Flags, ID, Item) = 0 );
}

// Retrieve 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)
{
// If a failure occurs, an exception is thrown.
Throw new NoSystemMenuException ();
}
Return cSysMenu;
}

// Restore public static void ResetSystemMenu (Form Frm) in the current window menu)
{
ApiGetSystemMenu (Frm. Handle, 1

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.