There is no DotNet Native way to manipulate the Window Menu. You must do it all via InterOp.
You can add existing Menuitems though.
The instructions shown here detail the steps necessary to achieve the menu as shown above.
by: Mick Dohertys'
You can add existing Menuitems though.
The instructions shown here detail the steps necessary to achieve the menu as shown above.
VB net Sample:
'Create a New Windows Form Project. 'Add the following line of code before Public Class Form1: ' Imports System.Runtime.InteropServices 'Add a ContextMenu to the Form and name it PopUpMenu. 'Add a MenuItem to PopUpMenu and call it sysPopUp. 'Add a MainMenu to the form and add a MenuItem to that which you should name MenuHelpAbout. 'Finally, Add the following code to the Form. <DllImport("user32.dll", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function GetSystemMenu(ByVal hWnd As IntPtr, ByVal bRevert As Boolean) As IntPtr End Function <DllImport("user32.dll", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function AppendMenu(ByVal hMenu As IntPtr, ByVal uFlags As Int32, ByVal uIDNewItem As IntPtr, ByVal lpNewItem As String) As Boolean End Function <DllImport("user32", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function InsertMenu(ByVal hMenu As IntPtr, ByVal uPosition As Integer, ByVal uFlags As Integer, ByVal uIDNewItem As IntPtr, ByVal lpNewItem As String) As Boolean End Function <DllImport("user32", CallingConvention:=CallingConvention.Cdecl)> _ Private Shared Function SetMenuItemBitmaps(ByVal hMenu As IntPtr, ByVal uPosition As Integer, ByVal uFlags As Integer, ByVal hBitmapUnchecked As IntPtr, ByVal hBitmapChecked As IntPtr) As Boolean End Function Private Const MF_STRING As Integer = &H0 Private Const MF_SEPARATOR As Integer = &H800& Private Const MF_BYCOMMAND As Integer = &H0 Private Const MF_BYPOSITION As Integer = &H400 Private Const MF_POPUP As Integer = &H10 Private Const WM_SYSCOMMAND As Integer = &H112 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load AddSysMenuItems() End Sub Private Sub AddSysMenuItems() 'Create a glyph for About MenuItem Dim bmpGlyph As New Bitmap(16, 16) Dim g As Graphics = Graphics.FromImage(bmpGlyph) g.Clear(Color.White) Dim sf As New StringFormat sf.LineAlignment = StringAlignment.Center sf.Alignment = StringAlignment.Center g.DrawString("?", New Font(FontFamily.GenericMonospace, 16, FontStyle.Bold, GraphicsUnit.Pixel), SystemBrushes.WindowText, New RectangleF(0, 0, 16, 16), sf) g.Dispose() 'Get a gdi bitmap object from our bitmap. Dim hbmp As IntPtr = bmpGlyph.GetHbitmap bmpGlyph.Dispose() 'Get the System Menus Handle. Dim hSysMenu As IntPtr = GetSystemMenu(Me.Handle, False) 'Add a standard Separator Item. AppendMenu(hSysMenu, MF_SEPARATOR, IntPtr.Zero, Nothing) 'Add an About Menu Item. AppendMenu(hSysMenu, MF_STRING, MenuHelpAbout.Handle, MenuHelpAbout.Text) 'Add our Glyph to the About MenuItem. SetMenuItemBitmaps(hSysMenu, MenuHelpAbout.Handle.ToInt32, MF_BYCOMMAND, hbmp, hbmp) 'Finally we'll insert an existing Popup Menu at position 0 InsertMenu(hSysMenu, 0, MF_BYPOSITION Or MF_POPUP, PopupMenu.Handle, "Popup Item") 'and a separator at position 1. InsertMenu(hSysMenu, 1, MF_BYPOSITION Or MF_SEPARATOR, IntPtr.Zero, Nothing) End Sub Private Sub MenuHelpAbout_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuHelpAbout.Click Dim id As String If TypeOf sender Is Menu Then id = "Forms" Else id = "Window Menus" End If MessageBox.Show(String.Format("This message was initiated from the {0} About Menu", id)) End Sub Private Sub sysPopUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles sysPopUp.Click MessageBox.Show(DirectCast(sender, MenuItem).Text) End Sub Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 'MenuItems added directly to the System menu do not fire the 'Menuitems default event, so we need to call this ourselves. 'Popupmenus will fire their default events though as can be 'seen by the fact that we do not call sysPopUp_Click() here. MyBase.WndProc(m) If m.Msg = WM_SYSCOMMAND Then If m.WParam.Equals(MenuHelpAbout.Handle) Then MenuHelpAbout_Click(Me, EventArgs.Empty) End If End If End Sub
CSharp Sample:
//Create a New Windows Form Project. //Add the following line of code before public class form1: // using System.Runtime.InteropServices; //Add a ContextMenu to the Form and name it PopUpMenu. //Add a MenuItem to PopUpMenu and call it sysPopUp. //Add a MainMenu to the form and add a MenuItem to that which you should name MenuHelpAbout. //Finally, Add the following code to the Form. [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)] private static extern IntPtr GetSystemMenu(IntPtr hWnd , bool bRevert); [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)] private static extern bool AppendMenu(IntPtr hMenu, Int32 uFlags, IntPtr uIDNewItem, String lpNewItem ); [DllImport("user32", CallingConvention=CallingConvention.Cdecl)] private static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, IntPtr uIDNewItem, String lpNewItem); [DllImport("user32", CallingConvention=CallingConvention.Cdecl)] private static extern bool SetMenuItemBitmaps(IntPtr hMenu, int uPosition, int uFlags, IntPtr hBitmapUnchecked, IntPtr hBitmapChecked); private const int MF_STRING = 0; private const int MF_SEPARATOR = 0x800; private const int MF_BYCOMMAND = 0; private const int MF_BYPOSITION = 0x400; private const int MF_POPUP = 0x10; private System.Windows.Forms.ContextMenu PopUpMenu; private System.Windows.Forms.MenuItem menuItem1; private System.Windows.Forms.MenuItem menuItem2; private System.Windows.Forms.MainMenu mainMenu1; private System.Windows.Forms.MenuItem menuItem3; private System.Windows.Forms.MenuItem MenuHelpAbout; private const int WM_SYSCOMMAND = 0x112; private void Form1_Load(object sender, System.EventArgs e) { AddSysMenuItems(); } private void AddSysMenuItems() { //Create a glyph for About MenuItem Bitmap bmpGlyph = new Bitmap(16, 16); Graphics g = Graphics.FromImage(bmpGlyph); g.Clear(Color.White); StringFormat sf = new StringFormat(); sf.LineAlignment = StringAlignment.Center; sf.Alignment = StringAlignment.Center; g.DrawString("?", new Font(FontFamily.GenericMonospace, 16, FontStyle.Bold, GraphicsUnit.Pixel), SystemBrushes.WindowText, new RectangleF(0, 0, 16, 16), sf); g.Dispose(); //Get a gdi bitmap object from our bitmap. IntPtr hbmp = bmpGlyph.GetHbitmap(); bmpGlyph.Dispose(); //Get the System Menus Handle. IntPtr hSysMenu = GetSystemMenu(Handle, false); //Add a standard Separator Item. AppendMenu(hSysMenu, MF_SEPARATOR, IntPtr.Zero, null); //Add an About Menu Item. AppendMenu(hSysMenu, MF_STRING, MenuHelpAbout.Handle, MenuHelpAbout.Text); //Add our Glyph to the About MenuItem. SetMenuItemBitmaps(hSysMenu, MenuHelpAbout.Handle.ToInt32(), MF_BYCOMMAND, hbmp, hbmp); //Finally we'll insert an existing Popup Menu at position 0 InsertMenu(hSysMenu, 0, MF_BYPOSITION | MF_POPUP, PopUpMenu.Handle, "Popup Item"); //and a separator at position 1. InsertMenu(hSysMenu, 1, MF_BYPOSITION | MF_SEPARATOR, IntPtr.Zero, null); } #endregion private void MenuHelpAbout_Click(object sender, System.EventArgs e) { String id; if (sender is Menu) id = "Forms"; else id = "Window Menus"; MessageBox.Show(String.Format("This message was initiated from the {0} About Menu", id)); } private void sysPopUp_Click(object sender, System.EventArgs e) { MessageBox.Show(((MenuItem)sender).Text); } protected override void WndProc(ref Message m) { //MenuItems added directly to the System menu do not fire the //Menuitems default event, so we need to call this ourselves. //Popupmenus will fire their default events though as can be //seen by the fact that we do not call sysPopUp_Click() here. base.WndProc (ref m); if (m.Msg == WM_SYSCOMMAND) if (m.WParam.Equals(MenuHelpAbout.Handle)) MenuHelpAbout_Click(this, EventArgs.Empty); }
No comments:
Post a Comment