Library code snippets

System Menu Classes

These two classes provide system menu functionality similar to the regular Menu and MenuItem classes so that you can use regular Click events instead of overriding WndProc when trying to modify a windows System menu. You should be able to figure out how to use SystemMenu and SystemMenuItem by looking at the constructors.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows;
using System.Collections;

public class SystemMenu : ArrayList {
   
   public const int BYPOSITION = 0x400;
   public const int REMOVE     = 0x1000;
   public const int CHECKED    = 0x8;
   public const int APPEND     = 0x100;
   public const int SEPERATOR  = 0x800;
   public const int GRAYED     = 0x1;
   public const int DISABLED   = 0x2;
   public const int BITMAP     = 0x4;
   public const int RADIOCHECK = 0x200;
   public const int BREAK      = 0x40;
   public const int BARBREAK   = 0x20;

   [DllImport("user32.dll")]
   private static extern int GetSystemMenu(int HWND);
   [DllImport("user32.dll")]
   private static extern int AppendMenu(int MenuHandle, int Props, int FlagsW, string text);
   [DllImport("user32.dll")]
   private static extern int RemoveMenu(int MenuHandle, int pos, int Flags);
   [DllImport("user32.dll")]
   private static extern int GetMenuItemID(int Menuhandle, int pos);
   [DllImport("user32.dll")]
   private static extern int ModifyMenu(int MHandle, int pos,int flags,int newPos,string text);

   private Form form;
   private int SystemMenuHandle;
   
   public int Handle {
       get { return SystemMenuHandle; }
   }

   public SystemMenu(Form f) : base(0) {
       form = f;
       SystemMenuHandle = GetSystemMenu(form.Handle.ToInt32());
   }
   
   public void Add(SystemMenuItem MI) {
       base.Add(MI);
       if(MI.Text == "-") {
           AppendMenu(SystemMenuHandle,SystemMenu.SEPERATOR,MI.MenuID,null);
       } else {
           AppendMenu(SystemMenuHandle,MI.Flags,MI.MenuID,MI.Text);
       }
   }

   public void Remove(SystemMenuItem MI) {
       base.Remove(MI);
       RemoveMenu(SystemMenuHandle, MI.MenuID, 0);
   }

   public void ModifyMenuPosition(int pos, int flags, string text) {
       ModifyMenu(this.Handle, pos, flags|SystemMenu.BYPOSITION, pos, text);
   }

   public new SystemMenuItem this[int index] {
       get { return (SystemMenuItem)base[index]; }
       set {
           if(value!=null) {
           SystemMenuItem MI = (SystemMenuItem)value;
           ModifyMenu(this.Handle, this[index].MenuID, MI.Flags, MI.MenuID, MI.Text); }
           base[index] = (object)value;
       }
   }

}// end of class SystemMenu

public class SystemMenuItem : MenuItem {
   [DllImport("user32.dll")]
   private static extern int GetSystemMenu(int HWND);
   [DllImport("user32.dll")]
   private static extern int AppendMenu(int MenuHandle, int Props, int FlagsW, string text);
   [DllImport("user32.dll")]
   private static extern int RemoveMenu(int MenuHandle, int pos, int Flags);
   [DllImport("user32.dll")]
   private static extern int GetMenuItemID(int Menuhandle, int pos);
   [DllImport("user32.dll")]
   private static extern int ModifyMenu(int MHandle, int pos,int flags,int newPos,string text);
   [DllImport("user32.dll")]
   private static extern int CheckMenuItem(int HMenu, int pos, int flags);

   private int flags = 0;
   public int Flags {
       get { return flags; }
   }

   private SystemMenu menu;    
   public SystemMenuItem(string text, SystemMenu SM) {
       base.Text = text;
       menu = SM;
       if(text == "-")
           this.flags = SystemMenu.SEPERATOR;
   }

   public new int MenuID {
       get { return base.MenuID; }
   }

   public SystemMenuItem CloneMenu(int should_be_null) {
       should_be_null = 0;
       return new SystemMenuItem(this.Text, menu);
   }

   public new bool Checked {
       get { return base.Checked; }
       set {
           base.Checked = value;
           if(base.Checked) {
               flags = (flags|SystemMenu.CHECKED);
               CheckMenuItem(menu.Handle, this.MenuID, flags);
           } else {
               flags = (flags&(~SystemMenu.CHECKED));
               CheckMenuItem(menu.Handle, this.MenuID, flags);
           }    
       }
   }

   public new string Text {
       get { return base.Text; }
       set {
           base.Text = value;
           ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
       }
   }
   
   public new bool Break {
       get { return base.Break; }
       set {
           base.Break = value;
           if(base.Break) {
               flags = flags|SystemMenu.BREAK;
               ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
           } else {
               flags = flags&(~SystemMenu.BREAK);
               ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
           }
       }
   }

   public new bool BarBreak {
       get { return base.BarBreak; }
       set {
           base.BarBreak = value;
           if(base.BarBreak) {
               flags = flags|SystemMenu.BARBREAK;
               ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
           } else {
               flags = flags&(~SystemMenu.BARBREAK);
               ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
           }
       }
   }

   
}//end of class SystemMenuItem

Comments

  1. 10 Oct 2007 at 19:16

    Hi,

    I know this is an old post, but in case anyone else has the same problem...  I believe what is happening is that you are probably declaring the SystemMenu object in a member function and then letting it go out of scope.  The garbage collector comes up behind at an unspecified time later and destroys the object, thereby breaking the link to your callback.

     If you declare the SystemMenu object as a member variable and instantiate it in the form constructor, it should hang around until the form is destroyed.  This should fix your problem.

    Take care.

  2. 27 Oct 2004 at 05:13

    Hi,
    I have a problem with handling system menu item events.
    I have used this wrapper in a standard form.
    I have added one menuitem into a system menu and I have
    a one button in my form. When I click this button a child dialog appears
    and then is closed in standard manner. After that, the event handler for the
    menuitem doesn't work. It is not called anymore.
    But if I click this menuitem before showing a child dialog all works fine.
    I dont know, where is problem ?


    Please help.


  3. 01 Jan 1999 at 00:00

    This thread is for discussions of System Menu Classes.

Leave a comment

Sign in or Join us (it's free).

Michael H

Related podcasts

  • Object-Oriented Programming in Ruby

    In this episode, I talk with Scott Bellware about object-oriented programming in Ruby, and Ruby's object model. This is taken from a private conversation, and the audio quality suffers at times. Much thanks to Scott for allowing this to be released.This episode of the Alt.NET Podcast is bro...

Want to stay in touch with what's going on? Follow us on twitter!