2 // ToolStripMenuItem.cs
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
32 using System.ComponentModel;
33 using System.Windows.Forms.Design;
35 namespace System.Windows.Forms
37 [ToolStripItemDesignerAvailability (ToolStripItemDesignerAvailability.MenuStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)]
38 public class ToolStripMenuItem : ToolStripDropDownItem
40 private CheckState checked_state;
41 private bool check_on_click;
42 private string shortcut_display_string;
43 private Keys shortcut_keys = Keys.None;
44 private bool show_shortcut_keys = true;
45 private Form mdi_client_form;
47 #region Public Constructors
48 public ToolStripMenuItem ()
49 : this (null, null, null, string.Empty)
53 public ToolStripMenuItem (Image image)
54 : this (null, image, null, string.Empty)
58 public ToolStripMenuItem (string text)
59 : this (text, null, null, string.Empty)
63 public ToolStripMenuItem (string text, Image image)
64 : this (text, image, null, string.Empty)
68 public ToolStripMenuItem (string text, Image image, EventHandler onClick)
69 : this (text, image, onClick, string.Empty)
73 public ToolStripMenuItem (string text, Image image, params ToolStripItem[] dropDownItems)
74 : this (text, image, null, string.Empty)
76 if (dropDownItems != null)
77 foreach (ToolStripItem tsi in dropDownItems)
78 this.DropDownItems.Add (tsi);
81 public ToolStripMenuItem (string text, Image image, EventHandler onClick, Keys shortcutKeys)
82 : this (text, image, onClick, string.Empty)
86 public ToolStripMenuItem (string text, Image image, EventHandler onClick, string name)
87 : base (text, image, onClick, name)
89 base.Overflow = ToolStripItemOverflow.Never;
93 #region Public Properties
95 [DefaultValue (false)]
96 [RefreshProperties (RefreshProperties.All)]
99 switch (this.checked_state) {
100 case CheckState.Unchecked:
103 case CheckState.Checked:
104 case CheckState.Indeterminate:
109 if (this.checked_state != (value ? CheckState.Checked : CheckState.Unchecked)) {
110 this.checked_state = value ? CheckState.Checked : CheckState.Unchecked;
112 this.OnCheckedChanged (EventArgs.Empty);
117 [DefaultValue (false)]
118 public bool CheckOnClick {
119 get { return this.check_on_click; }
120 set { this.check_on_click = value; }
124 [DefaultValue (CheckState.Unchecked)]
125 [RefreshProperties (RefreshProperties.All)]
126 public CheckState CheckState {
127 get { return this.checked_state; }
130 if (!Enum.IsDefined (typeof (CheckState), value))
131 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for CheckState", value));
133 this.checked_state = value;
135 this.OnCheckStateChanged (EventArgs.Empty);
139 public override bool Enabled {
140 get { return base.Enabled; }
141 set { base.Enabled = value; }
145 public bool IsMdiWindowListEntry {
146 get { return this.mdi_client_form != null; }
149 [DefaultValue (ToolStripItemOverflow.Never)]
150 public new ToolStripItemOverflow Overflow {
151 get { return base.Overflow; }
152 set { base.Overflow = value; }
156 [DefaultValue (true)]
157 public bool ShowShortcutKeys {
158 get { return this.show_shortcut_keys; }
159 set { this.show_shortcut_keys = value; }
163 [DefaultValue (null)]
164 public string ShortcutKeyDisplayString {
165 get { return this.shortcut_display_string; }
166 set { this.shortcut_display_string = value; }
170 [DefaultValue (Keys.None)]
171 public Keys ShortcutKeys {
172 get { return this.shortcut_keys; }
174 if (this.shortcut_keys != value) {
175 this.shortcut_keys = value;
177 if (this.Parent != null)
178 ToolStripManager.AddToolStripMenuItem (this);
184 #region Protected Properties
185 protected internal override Padding DefaultMargin {
186 get { return new Padding (0); }
189 protected override Padding DefaultPadding {
190 get { return new Padding (4, 0, 4, 0); }
193 protected override Size DefaultSize {
194 get { return new Size (32, 19); }
198 #region Protected Methods
199 protected override ToolStripDropDown CreateDefaultDropDown ()
201 ToolStripDropDownMenu tsddm = new ToolStripDropDownMenu ();
202 tsddm.OwnerItem = this;
206 protected override void Dispose (bool disposing)
208 base.Dispose (disposing);
211 protected virtual void OnCheckedChanged (EventArgs e)
213 EventHandler eh = (EventHandler)Events [CheckedChangedEvent];
218 protected virtual void OnCheckStateChanged (EventArgs e)
220 EventHandler eh = (EventHandler)Events [CheckStateChangedEvent];
225 protected override void OnClick (EventArgs e)
230 if (this.IsOnDropDown) {
231 if (this.HasDropDownItems)
234 this.HideDropDown (ToolStripDropDownCloseReason.ItemClicked);
236 (this.Parent as ToolStripDropDown).Close (ToolStripDropDownCloseReason.ItemClicked);
237 ToolStripManager.FireAppFocusChanged (this.Parent);
239 Object parent = this.Parent;
241 // Find the top level MenuStrip to inform it to close all open
242 // dropdowns because this one was clicked
243 while (parent != null) {
244 if (parent is MenuStrip)
245 (parent as MenuStrip).HideMenus (true, ToolStripDropDownCloseReason.ItemClicked);
247 if (parent is ToolStripDropDown)
248 parent = (parent as ToolStripDropDown).OwnerItem;
249 else if (parent is ToolStripItem)
250 parent = (parent as ToolStripItem).Parent;
256 if (this.IsMdiWindowListEntry) {
257 this.mdi_client_form.MdiParent.MdiContainer.ActivateChild (this.mdi_client_form);
261 if (this.check_on_click)
262 this.Checked = !this.Checked;
267 protected override void OnDropDownHide (EventArgs e)
269 base.OnDropDownHide (e);
272 protected override void OnDropDownShow (EventArgs e)
274 base.OnDropDownShow (e);
277 protected override void OnFontChanged (EventArgs e)
279 base.OnFontChanged (e);
282 protected override void OnMouseDown (MouseEventArgs e)
284 if (this.HasDropDownItems && Enabled)
285 if (!this.DropDown.Visible)
286 this.ShowDropDown ();
288 base.OnMouseDown (e);
291 protected override void OnMouseEnter (EventArgs e)
293 if (this.IsOnDropDown && this.HasDropDownItems && Enabled)
294 this.ShowDropDown ();
296 base.OnMouseEnter (e);
299 protected override void OnMouseLeave (EventArgs e)
301 base.OnMouseLeave (e);
304 protected override void OnMouseUp (MouseEventArgs e)
306 if (!this.HasDropDownItems && Enabled)
310 protected override void OnOwnerChanged (EventArgs e)
312 base.OnOwnerChanged (e);
315 protected override void OnPaint (System.Windows.Forms.PaintEventArgs e)
319 if (this.Owner != null) {
320 Color font_color = this.Enabled ? this.ForeColor : SystemColors.GrayText;
321 Image draw_image = this.Enabled ? this.Image : ToolStripRenderer.CreateDisabledImage (this.Image);
323 if (this.IsOnDropDown)
324 this.Owner.Renderer.DrawMenuItemBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
326 this.Owner.Renderer.DrawButtonBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
328 Rectangle text_layout_rect;
329 Rectangle image_layout_rect;
331 this.CalculateTextAndImageRectangles (out text_layout_rect, out image_layout_rect);
333 if (this.IsOnDropDown) {
334 text_layout_rect = new Rectangle (35, text_layout_rect.Top, text_layout_rect.Width, text_layout_rect.Height);
335 if (image_layout_rect != Rectangle.Empty)
336 image_layout_rect = new Rectangle (new Point (4, 3), base.GetImageSize ());
339 this.Owner.Renderer.DrawItemCheck (new ToolStripItemImageRenderEventArgs (e.Graphics, this, new Rectangle (2, 1, 19, 19)));
341 if (text_layout_rect != Rectangle.Empty)
342 this.Owner.Renderer.DrawItemText (new System.Windows.Forms.ToolStripItemTextRenderEventArgs (e.Graphics, this, this.Text, text_layout_rect, font_color, this.Font, this.TextAlign));
344 string key_string = GetShortcutDisplayString ();
346 if (!string.IsNullOrEmpty (key_string) && !this.HasDropDownItems) {
348 Size key_string_size = TextRenderer.MeasureText (key_string, this.Font);
349 Rectangle key_string_rect = new Rectangle (this.ContentRectangle.Right - key_string_size.Width - offset, text_layout_rect.Top, key_string_size.Width, text_layout_rect.Height);
350 this.Owner.Renderer.DrawItemText (new System.Windows.Forms.ToolStripItemTextRenderEventArgs (e.Graphics, this, key_string, key_string_rect, font_color, this.Font, this.TextAlign));
353 if (image_layout_rect != Rectangle.Empty)
354 this.Owner.Renderer.DrawItemImage (new System.Windows.Forms.ToolStripItemImageRenderEventArgs (e.Graphics, this, draw_image, image_layout_rect));
356 if (this.IsOnDropDown && this.HasDropDownItems)
357 this.Owner.Renderer.DrawArrow (new ToolStripArrowRenderEventArgs (e.Graphics, this, new Rectangle (this.Bounds.Width - 17, 2, 10, 20), Color.Black, ArrowDirection.Right));
362 protected internal override bool ProcessCmdKey (ref Message m, Keys keyData)
364 if (this.Enabled && keyData == this.shortcut_keys) {
365 this.FireEvent (EventArgs.Empty, ToolStripItemEventType.Click);
369 return base.ProcessCmdKey (ref m, keyData);
372 protected internal override void SetBounds (Rectangle bounds)
374 base.SetBounds (bounds);
378 #region Public Events
379 static object CheckedChangedEvent = new object ();
380 static object CheckStateChangedEvent = new object ();
382 public event EventHandler CheckedChanged {
383 add { Events.AddHandler (CheckedChangedEvent, value); }
384 remove {Events.RemoveHandler (CheckedChangedEvent, value); }
387 public event EventHandler CheckStateChanged {
388 add { Events.AddHandler (CheckStateChangedEvent, value); }
389 remove {Events.RemoveHandler (CheckStateChangedEvent, value); }
393 #region Internal Properties
394 internal Form MdiClientForm {
395 get { return this.mdi_client_form; }
396 set { this.mdi_client_form = value; }
400 #region Internal Methods
401 internal override Size CalculatePreferredSize (Size constrainingSize)
403 Size base_size = base.CalculatePreferredSize (constrainingSize);
405 string key_string = GetShortcutDisplayString ();
407 if (string.IsNullOrEmpty (key_string))
410 Size text_size = TextRenderer.MeasureText (key_string, this.Font);
412 return new Size (base_size.Width + text_size.Width - 25, base_size.Height);
415 internal string GetShortcutDisplayString ()
417 if (this.show_shortcut_keys == false)
420 string key_string = string.Empty;
422 if (!string.IsNullOrEmpty (this.shortcut_display_string))
423 key_string = this.shortcut_display_string;
424 else if (this.shortcut_keys != Keys.None) {
425 KeysConverter kc = new KeysConverter ();
426 key_string = kc.ConvertToString (this.shortcut_keys);