2 // ToolStripDropDownItem.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)
31 using System.ComponentModel;
32 using System.Threading;
34 namespace System.Windows.Forms
36 [DefaultProperty ("DropDownItems")]
37 [Designer ("System.Windows.Forms.Design.ToolStripMenuItemDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
38 public abstract class ToolStripDropDownItem : ToolStripItem
40 internal ToolStripDropDown drop_down;
41 private ToolStripDropDownDirection drop_down_direction;
43 #region Protected Constructors
44 protected ToolStripDropDownItem () : this (string.Empty, null, null, string.Empty)
48 protected ToolStripDropDownItem (string text, Image image, EventHandler onClick)
49 : this (text, image, onClick, string.Empty)
53 protected ToolStripDropDownItem (string text, Image image, params ToolStripItem[] dropDownItems)
54 : this (text, image, null, string.Empty)
58 protected ToolStripDropDownItem (string text, Image image, EventHandler onClick, string name)
59 : base (text, image, onClick, name)
64 #region Public Properties
65 [TypeConverter (typeof (ReferenceConverter))]
66 public ToolStripDropDown DropDown {
68 if (this.drop_down == null) {
69 this.drop_down = CreateDefaultDropDown ();
70 this.drop_down.ItemAdded += new ToolStripItemEventHandler (DropDown_ItemAdded);
73 return this.drop_down;
76 this.drop_down = value;
77 this.drop_down.OwnerItem = this;
82 public ToolStripDropDownDirection DropDownDirection {
83 get { return this.drop_down_direction; }
85 if (!Enum.IsDefined (typeof (ToolStripDropDownDirection), value))
86 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripDropDownDirection", value));
88 this.drop_down_direction = value;
92 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
93 public ToolStripItemCollection DropDownItems {
94 get { return this.DropDown.Items; }
98 public virtual bool HasDropDownItems {
99 get { return this.drop_down != null && this.DropDown.Items.Count != 0; }
103 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
104 public override bool Pressed {
105 get { return base.Pressed || (this.drop_down != null && this.DropDown.Visible); }
109 #region Protected Properties
110 protected internal virtual Point DropDownLocation {
114 if (this.IsOnDropDown) {
115 p = Parent.PointToScreen (new Point (this.Bounds.Left, this.Bounds.Top - 1));
116 p.X += this.Bounds.Width;
117 p.Y += this.Bounds.Left;
121 p = new Point (this.Bounds.Left, this.Bounds.Bottom - 1);
123 return Parent.PointToScreen (p);
128 #region Public Methods
129 public void HideDropDown ()
131 if (this.drop_down == null || !this.DropDown.Visible)
134 // OnDropDownHide is called before actually closing DropDown
135 this.OnDropDownHide (EventArgs.Empty);
136 this.DropDown.Close (ToolStripDropDownCloseReason.CloseCalled);
137 this.is_pressed = false;
141 public void ShowDropDown ()
143 // Don't go through this whole deal if
144 // the DropDown is already visible
145 if (this.DropDown.Visible)
148 // Call this before the HasDropDownItems check to give
149 // users a chance to handle it and add drop down items
150 this.OnDropDownShow (EventArgs.Empty);
152 if (!this.HasDropDownItems)
156 this.DropDown.Show (this.DropDownLocation);
160 #region Protected Methods
161 protected override AccessibleObject CreateAccessibilityInstance ()
163 return new ToolStripDropDownItemAccessibleObject (this);
166 protected virtual ToolStripDropDown CreateDefaultDropDown ()
168 ToolStripDropDown tsdd = new ToolStripDropDown ();
169 tsdd.OwnerItem = this;
173 protected override void Dispose (bool disposing)
176 if (this.HasDropDownItems)
177 foreach (ToolStripItem tsi in this.DropDownItems)
178 if (tsi is ToolStripMenuItem)
179 ToolStripManager.RemoveToolStripMenuItem ((ToolStripMenuItem)tsi);
181 if (drop_down != null)
182 ToolStripManager.RemoveToolStrip (drop_down);
184 base.Dispose (disposing);
188 protected override void OnBoundsChanged ()
190 base.OnBoundsChanged ();
193 protected internal virtual void OnDropDownClosed (EventArgs e)
195 EventHandler eh = (EventHandler)(Events [DropDownClosedEvent]);
200 protected virtual void OnDropDownHide (EventArgs e)
204 protected internal virtual void OnDropDownItemClicked (ToolStripItemClickedEventArgs e)
206 ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [DropDownItemClickedEvent]);
211 protected internal virtual void OnDropDownOpened (EventArgs e)
213 EventHandler eh = (EventHandler)(Events [DropDownOpenedEvent]);
218 protected virtual void OnDropDownShow (EventArgs e)
220 EventHandler eh = (EventHandler)(Events[DropDownOpeningEvent]);
225 protected override void OnFontChanged (EventArgs e)
227 base.OnFontChanged (e);
229 // don't use DropDown directly, since doing that
230 // would created the DropDown control
231 if (drop_down != null)
232 drop_down.Font = Font;
235 protected override void OnRightToLeftChanged (EventArgs e)
237 base.OnRightToLeftChanged (e);
240 protected internal override bool ProcessCmdKey (ref Message m, Keys keyData)
242 if (this.HasDropDownItems)
243 foreach (ToolStripItem tsi in this.DropDownItems)
244 if (tsi.ProcessCmdKey (ref m, keyData) == true)
247 return base.ProcessCmdKey (ref m, keyData);
250 protected internal override bool ProcessDialogKey (Keys keyData)
252 if (!this.Selected || !this.HasDropDownItems)
253 return base.ProcessDialogKey (keyData);
255 if (!this.IsOnDropDown) {
256 if (this.Parent.Orientation == Orientation.Horizontal) {
257 if (keyData == Keys.Down || keyData == Keys.Enter) {
258 if (this.Parent is MenuStrip)
259 (this.Parent as MenuStrip).MenuDroppedDown = true;
260 this.ShowDropDown ();
261 this.DropDown.SelectNextToolStripItem (null, true);
265 if (keyData == Keys.Right || keyData == Keys.Enter) {
266 if (this.Parent is MenuStrip)
267 (this.Parent as MenuStrip).MenuDroppedDown = true;
268 this.ShowDropDown ();
269 this.DropDown.SelectNextToolStripItem (null, true);
274 if (keyData == Keys.Right || keyData == Keys.Enter) {
275 if (this.HasDropDownItems) {
276 this.ShowDropDown ();
277 this.DropDown.SelectNextToolStripItem (null, true);
284 return base.ProcessDialogKey (keyData);
288 #region Public Events
289 static object DropDownClosedEvent = new object ();
290 static object DropDownItemClickedEvent = new object ();
291 static object DropDownOpenedEvent = new object ();
292 static object DropDownOpeningEvent = new object ();
294 public event EventHandler DropDownClosed {
295 add { Events.AddHandler (DropDownClosedEvent, value); }
296 remove { Events.RemoveHandler (DropDownClosedEvent, value); }
299 public event ToolStripItemClickedEventHandler DropDownItemClicked {
300 add { Events.AddHandler (DropDownItemClickedEvent, value); }
301 remove { Events.RemoveHandler (DropDownItemClickedEvent, value); }
304 public event EventHandler DropDownOpened {
305 add { Events.AddHandler (DropDownOpenedEvent, value); }
306 remove { Events.RemoveHandler (DropDownOpenedEvent, value); }
309 public event EventHandler DropDownOpening {
310 add { Events.AddHandler (DropDownOpeningEvent, value); }
311 remove { Events.RemoveHandler (DropDownOpeningEvent, value); }
315 #region Internal Methods
316 internal override void Dismiss (ToolStripDropDownCloseReason reason)
318 if (this.HasDropDownItems && this.DropDown.Visible)
319 this.DropDown.Dismiss (reason);
321 base.Dismiss (reason);
324 internal override void HandleClick (int mouse_clicks, EventArgs e)
329 internal void HideDropDown (ToolStripDropDownCloseReason reason)
331 if (this.drop_down == null || !this.DropDown.Visible)
334 // OnDropDownHide is called before actually closing DropDown
335 this.OnDropDownHide (EventArgs.Empty);
336 this.DropDown.Close (reason);
337 this.is_pressed = false;
341 private void DropDown_ItemAdded (object sender, ToolStripItemEventArgs e)
343 e.Item.owner_item = this;