//將創建一個菜單項 "Test" ,且該項被選中(checked) mySystemMenu.AppendMenu(myID, "Test", ItemFlags.mfString|ItemFlags.mfChecked); |
using System; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; public class NoSystemMenuException : System.Exception {} //這些值來自于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 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 } // // 幫助實現操作系統菜單的類的定義 ///. //注意:用P/Invoke調用動態鏈接庫中非托管函數時,應執行如下步驟: //1,定位包含該函數的DLL。 //2,把該DLL庫裝載入內存。 //3,找到即將調用的函數地址,并將所有的現場壓入堆棧。 //4,調用函數。 // public class SystemMenu { // 提示:C#把函數聲明為外部的,而且使用屬性DllImport來指定DLL //和任何其他可能需要的參數。 // 首先,我們需要GetSystemMenu() 函數 // 注意這個函數沒有Unicode 版本 [DllImport("USER32", EntryPoint="GetSystemMenu", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.Winapi)] private static extern IntPtr apiGetSystemMenu(IntPtr WindowHandle, int bReset); // 還需要AppendMenu()。 既然 .NET 使用Unicode, // 我們應該選取它的Unicode版本。 [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 ); //還可能需要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; // 系統菜單句柄 public SystemMenu( ) {} // 在給定的位置(以0為索引開始值)插入一個分隔條 public bool InsertSeparator ( int Pos ) { return ( InsertMenu(Pos, ItemFlags.mfSeparator |ItemFlags.mfByPosition, 0, "") ); } // 簡化的InsertMenu(),前提――Pos參數是一個0開頭的相對索引位置 public bool InsertMenu ( int Pos, int ID, String Item ) { return ( InsertMenu(Pos, ItemFlags.mfByPosition |ItemFlags.mfString, ID, Item) ); } // 在給定位置插入一個菜單項。具體插入的位置取決于Flags public bool InsertMenu ( int Pos, ItemFlags Flags, int ID, String Item ) { return ( apiInsertMenu(m_SysMenu, Pos, (Int32)Flags, ID, Item) == 0); } // 添加一個分隔條 public bool AppendSeparator ( ) { return AppendMenu(0, "", ItemFlags.mfSeparator); } // 使用ItemFlags.mfString 作為缺省值 public bool AppendMenu ( int ID, String Item ) { return AppendMenu(ID, Item, ItemFlags.mfString); } // 被取代的函數 public bool AppendMenu ( int ID, String Item, ItemFlags Flags ) { return ( apiAppendMenu(m_SysMenu, (int)Flags, ID, Item) == 0 ); } //從一個Form對象檢索一個新對象 public static SystemMenu FromForm ( Form Frm ) { SystemMenu cSysMenu = new SystemMenu(); cSysMenu.m_SysMenu = apiGetSystemMenu(Frm.Handle, 0); if ( cSysMenu.m_SysMenu == IntPtr.Zero ) { // 一旦失敗,引發一個異常 throw new NoSystemMenuException(); } return cSysMenu; } // 當前窗口菜單還原 public static void ResetSystemMenu ( Form Frm ) { apiGetSystemMenu(Frm.Handle, 1); } // 檢查是否一個給定的ID在系統菜單ID范圍之內 public static bool VerifyItemID ( int ID ) { return (bool)( ID < 0xF000 && ID > 0 ); } } |
// SystemMenu 對象 private SystemMenu m_SystemMenu = null; // ID 常數定義 private const int m_AboutID = 0x100; private const int m_ResetID = 0x101; private void frmMain_Load(object sender, System.EventArgs e) { try { m_SystemMenu = SystemMenu.FromForm(this); // 添加一個separator ... m_SystemMenu.AppendSeparator(); // 添加"關于" 菜單項 m_SystemMenu.AppendMenu(m_AboutID, "關于"); // 在菜單頂部加上"復位"菜單項 m_SystemMenu.InsertSeparator(0); m_SystemMenu.InsertMenu(0, m_ResetID, "復位系統菜單"); } catch ( NoSystemMenuException /* err */ ) { // 建立你的錯誤處理器 } } |
protected override void WndProc ( ref Message msg ) { base.WndProc(ref msg); } |
protected override void WndProc ( ref Message msg ) { // 通過截取WM_SYSCOMMAND消息并進行處理 // 注意,消息WM_SYSCOMMAND被定義在WindowMessages枚舉類中 // 消息的WParam參數包含點擊的項的ID // 該值與通過上面類的InsertMenu()或AppendMenu()成員函數傳遞的一樣 if ( msg.Msg == (int)WindowMessages.wmSysCommand ) { switch ( msg.WParam.ToInt32() ) { case m_ResetID: // reset菜單項的ID { if ( MessageBox.Show(this, "\tAre you sure?","Question", MessageBoxButtons.YesNo) == DialogResult.Yes ) { // 復位系統菜單 SystemMenu.ResetSystemMenu(this); } } break; case m_AboutID: { // “關于”菜單項 MessageBox.Show(this, "作者: 朱先中 \n\n "+"e-mail: sdmyzxz@163.com", "關于"); } break; // 這里可以針對另外的菜單項設計處理過程 } } // 調用基類函數 base.WndProc(ref msg); } |
原文轉自:http://www.anti-gravitydesign.com