2009-08-19 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripDropDown.cs
1 //
2 // ToolStripDropDown.cs
3 //
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:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
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.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 #if NET_2_0
30 using System.Drawing;
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
33
34 namespace System.Windows.Forms
35 {
36         [ClassInterface (ClassInterfaceType.AutoDispatch)]
37         [ComVisible (true)]
38         [Designer ("System.Windows.Forms.Design.ToolStripDropDownDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
39         public class ToolStripDropDown : ToolStrip
40         {
41                 private bool allow_transparency;
42                 private bool auto_close;
43                 private bool can_overflow;
44                 private bool drop_shadow_enabled = true;
45                 private double opacity = 1D;
46                 private ToolStripItem owner_item;
47
48                 #region Public Constructor
49                 public ToolStripDropDown () : base ()
50                 {
51                         SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
52                         SetStyle (ControlStyles.ResizeRedraw, true);
53
54                         this.auto_close = true;
55                         is_visible = false;
56                         this.DefaultDropDownDirection = ToolStripDropDownDirection.Right;
57                         this.GripStyle = ToolStripGripStyle.Hidden;
58                         this.is_toplevel = true;
59                 }
60                 #endregion
61
62                 #region Public Properties
63                 [Browsable (false)]
64                 [EditorBrowsable (EditorBrowsableState.Never)]
65                 public new bool AllowItemReorder {
66                         get { return base.AllowItemReorder; }
67                         set { base.AllowItemReorder = value; }
68                 }
69                 
70                 [Browsable (false)]
71                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
72                 public bool AllowTransparency {
73                         get { return allow_transparency; }
74                         set {
75                                 if (value == allow_transparency)
76                                         return;
77
78                                 if ((XplatUI.SupportsTransparency () & TransparencySupport.Set) != 0) {
79                                         allow_transparency = value;
80
81                                         if (this.IsHandleCreated) {
82                                                 if (value) 
83                                                         XplatUI.SetWindowTransparency (Handle, Opacity, Color.Empty);
84                                                 else
85                                                         UpdateStyles (); // Remove the WS_EX_LAYERED style
86                                         }
87                                 }
88                         }
89                 }
90
91                 [Browsable (false)]
92                 [EditorBrowsable (EditorBrowsableState.Never)]
93                 public override AnchorStyles Anchor {
94                         get { return base.Anchor; }
95                         set { base.Anchor = value; }
96                 }
97
98                 [DefaultValue (true)]
99                 public bool AutoClose
100                 {
101                         get { return this.auto_close; }
102                         set { this.auto_close = value; }
103                 }
104
105                 [DefaultValue (true)]
106                 public override bool AutoSize {
107                         get { return base.AutoSize; }
108                         set { base.AutoSize = value; }
109                 }
110
111                 [Browsable (false)]
112                 [DefaultValue (false)]
113                 [EditorBrowsable (EditorBrowsableState.Never)]
114                 public new bool CanOverflow {
115                         get { return this.can_overflow; }
116                         set { this.can_overflow = value; }
117                 }
118                 
119                 [Browsable (false)]
120                 [EditorBrowsable (EditorBrowsableState.Never)]
121                 public new ContextMenu ContextMenu {
122                         get { return null; }
123                         set { }
124                 }
125
126                 [Browsable (false)]
127                 [EditorBrowsable (EditorBrowsableState.Never)]
128                 public new ContextMenuStrip ContextMenuStrip {
129                         get { return null; }
130                         set { }
131                 }
132
133                 public override ToolStripDropDownDirection DefaultDropDownDirection {
134                         get { return base.DefaultDropDownDirection; }
135                         set { base.DefaultDropDownDirection = value; }
136                 }
137                 
138                 [Browsable (false)]
139                 [EditorBrowsable (EditorBrowsableState.Always)]
140                 [DefaultValue (DockStyle.None)]
141                 public override DockStyle Dock {
142                         get { return base.Dock; }
143                         set { base.Dock = value; }
144                 }
145                 
146                 public bool DropShadowEnabled {
147                         get { return this.drop_shadow_enabled; }
148                         set {
149                                 if (this.drop_shadow_enabled == value)
150                                         return;
151                                         
152                                 this.drop_shadow_enabled = value;
153                                 UpdateStyles ();        // Re-CreateParams
154                         }
155                 }
156
157                 public override Font Font {
158                         get { return base.Font; }
159                         set { base.Font = value; }
160                 }
161
162                 [Browsable (false)]
163                 [EditorBrowsable (EditorBrowsableState.Never)]
164                 public new ToolStripGripDisplayStyle GripDisplayStyle {
165                         get { return ToolStripGripDisplayStyle.Vertical; }
166                 }
167
168                 [Browsable (false)]
169                 [EditorBrowsable (EditorBrowsableState.Never)]
170                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
171                 public new Padding GripMargin {
172                         get { return Padding.Empty; }
173                         set { }
174                 }
175
176                 [Browsable (false)]
177                 [EditorBrowsable (EditorBrowsableState.Never)]
178                 public new Rectangle GripRectangle {
179                         get { return Rectangle.Empty; }
180                 }
181
182                 [Browsable (false)]
183                 [EditorBrowsable (EditorBrowsableState.Never)]
184                 [DefaultValue (ToolStripGripStyle.Hidden)]
185                 public new ToolStripGripStyle GripStyle {
186                         get { return base.GripStyle; }
187                         set { base.GripStyle = value; }
188                 }
189
190                 [Browsable (false)]
191                 public bool IsAutoGenerated {
192                         get { return this is ToolStripOverflow; }
193                 }
194                 
195                 [Browsable (false)]
196                 [EditorBrowsable (EditorBrowsableState.Never)]
197                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
198                 public new Point Location {
199                         get { return base.Location; }
200                         set { base.Location = value; }
201                 }
202
203                 [DefaultValue (1D)]
204                 [TypeConverter (typeof (OpacityConverter))]
205                 [Browsable (false)]
206                 [EditorBrowsable (EditorBrowsableState.Advanced)]
207                 public double Opacity {
208                         get { return this.opacity; }
209                         set {
210                                         if (this.opacity == value)
211                                                 return;
212                                                 
213                                         this.opacity = value;
214                                         this.allow_transparency = true;
215                                         
216                                         if (this.IsHandleCreated) {
217                                                 UpdateStyles ();
218                                                 XplatUI.SetWindowTransparency (Handle, opacity, Color.Empty);
219                                         }
220                         }
221                 }
222
223                 [Browsable (false)]
224                 [EditorBrowsable (EditorBrowsableState.Never)]
225                 public new ToolStripOverflowButton OverflowButton {
226                         get { return base.OverflowButton; }
227                 }
228
229                 [Browsable (false)]
230                 [DefaultValue (null)]
231                 public ToolStripItem OwnerItem {
232                         get { return this.owner_item; }
233                         set { this.owner_item = value; 
234                                 
235                                 if (this.owner_item != null) {
236                                         if (this.owner_item.Owner != null && this.owner_item.Owner.RenderMode != ToolStripRenderMode.ManagerRenderMode)
237                                                 this.Renderer = this.owner_item.Owner.Renderer;
238
239                                         Font = owner_item.Font;
240                                 }
241                         }
242                 }
243
244                 [Browsable (false)]
245                 [EditorBrowsable (EditorBrowsableState.Always)]
246                 public new Region Region {
247                         get { return base.Region; }
248                         set { base.Region = value; }
249                 }
250
251                 [Localizable (true)]
252                 [AmbientValue (RightToLeft.Inherit)]
253                 public override RightToLeft RightToLeft {
254                         get { return base.RightToLeft; }
255                         set { base.RightToLeft = value; }
256                 }
257
258                 [Browsable (false)]
259                 [EditorBrowsable (EditorBrowsableState.Never)]
260                 public new bool Stretch {
261                         get { return false; }
262                         set { }
263                 }
264
265                 [Browsable (false)]
266                 [EditorBrowsable (EditorBrowsableState.Never)]
267                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
268                 public new int TabIndex {
269                         get { return 0; }
270                         set { }
271                 }
272
273                 [Browsable (false)]
274                 [DefaultValue (ToolStripTextDirection.Horizontal)]
275                 public override ToolStripTextDirection TextDirection {
276                         get { return base.TextDirection; }
277                         set { base.TextDirection = value; }
278                 }
279
280                 [Browsable (false)]
281                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
282                 [EditorBrowsable (EditorBrowsableState.Advanced)]
283                 public bool TopLevel {
284                         get { return GetTopLevel (); }
285                         set { SetTopLevel (value); }
286                 }
287                 
288                 [Browsable (false)]
289                 [Localizable (true)]
290                 [DefaultValue (false)]
291                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
292                 public new bool Visible {
293                         get { return base.Visible; }
294                         set { base.Visible = value; }
295                 }
296                 #endregion
297
298                 #region Protected Properties
299                 protected override CreateParams CreateParams {
300                         get {
301                                 CreateParams cp = base.CreateParams;
302
303                                 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_CLIPCHILDREN));
304                                 cp.ClassStyle |= (int)XplatUIWin32.ClassStyle.CS_DROPSHADOW;
305                                 cp.ExStyle |= (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST);
306
307                                 if (Opacity < 1.0 && allow_transparency)
308                                         cp.ExStyle |= (int)WindowExStyles.WS_EX_LAYERED;
309                                 if (TopMost)
310                                         cp.ExStyle |= (int) WindowExStyles.WS_EX_TOPMOST;
311
312                                 return cp;
313                         }
314                 }
315
316                 protected override DockStyle DefaultDock {
317                         get { return DockStyle.None; }
318                 }
319
320                 protected override Padding DefaultPadding {
321                         get { return new Padding (1, 2, 1, 2); }
322                 }
323
324                 protected override bool DefaultShowItemToolTips {
325                         get { return true; }
326                 }
327
328                 protected internal override Size MaxItemSize {
329                         get { return new Size (Screen.PrimaryScreen.Bounds.Width - 2, Screen.PrimaryScreen.Bounds.Height - 34); }
330                 }
331
332                 protected virtual bool TopMost {
333                         get { return true; }
334                 }
335                 #endregion
336
337                 #region Public Methods
338                 public void Close ()
339                 {
340                         this.Close (ToolStripDropDownCloseReason.CloseCalled);
341                 }
342
343                 public void Close (ToolStripDropDownCloseReason reason)
344                 {
345                         if (!this.Visible)
346                                 return;
347                                 
348                         // Give users a chance to cancel the close
349                         ToolStripDropDownClosingEventArgs e = new ToolStripDropDownClosingEventArgs (reason);
350                         this.OnClosing (e);
351
352                         if (e.Cancel)
353                                 return;
354
355                         // Don't actually close if AutoClose == true unless explicitly called
356                         if (!this.auto_close && reason != ToolStripDropDownCloseReason.CloseCalled)
357                                 return;
358
359                         // Detach from the tracker
360                         ToolStripManager.AppClicked -= new EventHandler (ToolStripMenuTracker_AppClicked); ;
361                         ToolStripManager.AppFocusChange -= new EventHandler (ToolStripMenuTracker_AppFocusChange);
362
363                         // Hide this dropdown
364                         this.Hide ();
365
366                         // Owner MenuItem needs to be told to redraw (it's no longer selected)
367                         if (owner_item != null)
368                                 owner_item.Invalidate ();
369
370                         // Recursive hide all child dropdowns
371                         foreach (ToolStripItem tsi in this.Items)
372                                 tsi.Dismiss (reason);
373                         
374                         this.OnClosed (new ToolStripDropDownClosedEventArgs (reason));
375                 }
376
377                 [Browsable (false)]
378                 [EditorBrowsable (EditorBrowsableState.Never)]
379                 public new void Show ()
380                 {
381                         Show (Location, DefaultDropDownDirection);
382                 }
383                 
384                 public void Show (Point screenLocation)
385                 {
386                         Show (screenLocation, DefaultDropDownDirection);
387                 }
388                 
389                 public void Show (Control control, Point position)
390                 {
391                         if (control == null)
392                                 throw new ArgumentNullException ("control");
393                         
394                         XplatUI.SetOwner (Handle, control.Handle);
395                         Show (control.PointToScreen (position), DefaultDropDownDirection);
396                 }
397                 
398                 public void Show (int x, int y)
399                 {
400                         Show (new Point (x, y), DefaultDropDownDirection);
401                 }
402                 
403                 public void Show (Point position, ToolStripDropDownDirection direction)
404                 {
405                         this.PerformLayout ();
406                         
407                         Point show_point = position;
408                         Point max_screen = new Point (SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
409                         
410                         if (this is ContextMenuStrip) {
411                                 // If we are going to go offscreen, adjust our direction so we don't...
412                                 // X direction
413                                 switch (direction) {
414                                         case ToolStripDropDownDirection.AboveLeft:
415                                                 if (show_point.X - this.Width < 0)
416                                                         direction = ToolStripDropDownDirection.AboveRight;
417                                                 break;
418                                         case ToolStripDropDownDirection.BelowLeft:
419                                                 if (show_point.X - this.Width < 0)
420                                                         direction = ToolStripDropDownDirection.BelowRight;
421                                                 break;
422                                         case ToolStripDropDownDirection.Left:
423                                                 if (show_point.X - this.Width < 0)
424                                                         direction = ToolStripDropDownDirection.Right;
425                                                 break;
426                                         case ToolStripDropDownDirection.AboveRight:
427                                                 if (show_point.X + this.Width > max_screen.X)
428                                                         direction = ToolStripDropDownDirection.AboveLeft;
429                                                 break;
430                                         case ToolStripDropDownDirection.BelowRight:
431                                         case ToolStripDropDownDirection.Default:
432                                                 if (show_point.X + this.Width > max_screen.X)
433                                                         direction = ToolStripDropDownDirection.BelowLeft;
434                                                 break;
435                                         case ToolStripDropDownDirection.Right:
436                                                 if (show_point.X + this.Width > max_screen.X)
437                                                         direction = ToolStripDropDownDirection.Left;
438                                                 break;
439                                 }
440
441                                 // Y direction
442                                 switch (direction) {
443                                         case ToolStripDropDownDirection.AboveLeft:
444                                                 if (show_point.Y - this.Height < 0)
445                                                         direction = ToolStripDropDownDirection.BelowLeft;
446                                                 break;
447                                         case ToolStripDropDownDirection.AboveRight:
448                                                 if (show_point.Y - this.Height < 0)
449                                                         direction = ToolStripDropDownDirection.BelowRight;
450                                                 break;
451                                         case ToolStripDropDownDirection.BelowLeft:
452                                                 if (show_point.Y + this.Height > max_screen.Y)
453                                                         direction = ToolStripDropDownDirection.AboveLeft;
454                                                 break;
455                                         case ToolStripDropDownDirection.BelowRight:
456                                         case ToolStripDropDownDirection.Default:
457                                                 if (show_point.Y + this.Height > max_screen.Y)
458                                                         direction = ToolStripDropDownDirection.AboveRight;
459                                                 break;
460                                         case ToolStripDropDownDirection.Left:
461                                                 if (show_point.Y + this.Height > max_screen.Y)
462                                                         direction = ToolStripDropDownDirection.AboveLeft;
463                                                 break;
464                                         case ToolStripDropDownDirection.Right:
465                                                 if (show_point.Y + this.Height > max_screen.Y)
466                                                         direction = ToolStripDropDownDirection.AboveRight;
467                                                 break;
468                                 }
469                         }
470                 
471                         switch (direction) {
472                                 case ToolStripDropDownDirection.AboveLeft:
473                                         show_point.Y -= this.Height;
474                                         show_point.X -= this.Width;
475                                         break;
476                                 case ToolStripDropDownDirection.AboveRight:
477                                         show_point.Y -= this.Height;
478                                         break;
479                                 case ToolStripDropDownDirection.BelowLeft:
480                                         show_point.X -= this.Width;
481                                         break;
482                                 case ToolStripDropDownDirection.Left:
483                                         show_point.X -= this.Width;
484                                         break;
485                                 case ToolStripDropDownDirection.Right:
486                                         break;
487                         }
488
489                         // Fix offscreen positions
490                         if ((show_point.X + this.Width) > max_screen.X)
491                                 show_point.X = max_screen.X - this.Width;
492                         if (show_point.X < 0)
493                                 show_point.X = 0;
494                         
495                         if (this.Location != show_point)
496                                 this.Location = show_point;
497
498                         CancelEventArgs e = new CancelEventArgs ();
499                         this.OnOpening (e);
500
501                         if (e.Cancel)
502                                 return;
503
504                         // The tracker lets us know when the form is clicked or loses focus
505                         ToolStripManager.AppClicked += new EventHandler (ToolStripMenuTracker_AppClicked);
506                         ToolStripManager.AppFocusChange += new EventHandler (ToolStripMenuTracker_AppFocusChange);
507
508                         base.Show ();
509
510                         ToolStripManager.SetActiveToolStrip (this, ToolStripManager.ActivatedByKeyboard);
511
512                         this.OnOpened (EventArgs.Empty);
513                 }
514                 
515                 public void Show (Control control, int x, int y)
516                 {
517                         if (control == null)
518                                 throw new ArgumentNullException ("control");
519
520                         Show (control, new Point (x, y));
521                 }
522                 
523                 public void Show (Control control, Point position, ToolStripDropDownDirection direction)
524                 {
525                         if (control == null)
526                                 throw new ArgumentNullException ("control");
527
528                         XplatUI.SetOwner (Handle, control.Handle);
529                         Show (control.PointToScreen (position), direction);
530                 }
531                 #endregion
532
533                 #region Protected Methods
534                 protected override AccessibleObject CreateAccessibilityInstance ()
535                 {
536                         return new ToolStripDropDownAccessibleObject (this);
537                 }
538                 
539                 protected override void CreateHandle ()
540                 {
541                         base.CreateHandle ();
542                 }
543
544                 protected override LayoutSettings CreateLayoutSettings (ToolStripLayoutStyle style)
545                 {
546                         return base.CreateLayoutSettings (style);
547                 }
548                 
549                 protected override void Dispose (bool disposing)
550                 {
551                         base.Dispose (disposing);
552                 }
553
554                 protected virtual void OnClosed (ToolStripDropDownClosedEventArgs e)
555                 {
556                         ToolStripDropDownClosedEventHandler eh = (ToolStripDropDownClosedEventHandler)(Events [ClosedEvent]);
557                         if (eh != null)
558                                 eh (this, e);
559                 }
560
561                 protected virtual void OnClosing (ToolStripDropDownClosingEventArgs e)
562                 {
563                         ToolStripDropDownClosingEventHandler eh = (ToolStripDropDownClosingEventHandler)(Events [ClosingEvent]);
564                         if (eh != null)
565                                 eh (this, e);
566                 }
567
568                 protected override void OnHandleCreated (EventArgs e)
569                 {
570                         base.OnHandleCreated (e);
571
572                         if (Application.MWFThread.Current.Context != null && Application.MWFThread.Current.Context.MainForm != null)
573                                 XplatUI.SetOwner (this.Handle, Application.MWFThread.Current.Context.MainForm.Handle);
574                 }
575
576                 protected override void OnItemClicked (ToolStripItemClickedEventArgs e)
577                 {
578                         base.OnItemClicked (e);
579                 }
580
581                 protected override void OnLayout (LayoutEventArgs e)
582                 {
583                         // Find the widest menu item, so we know how wide to make our dropdown
584                         int widest = 0;
585
586                         foreach (ToolStripItem tsi in this.Items) {
587                                 if (!tsi.Available) 
588                                         continue;
589                                         
590                                 tsi.SetPlacement (ToolStripItemPlacement.Main);
591                                 
592                                 widest = Math.Max (widest, tsi.GetPreferredSize (Size.Empty).Width + tsi.Margin.Horizontal);
593                         }
594                         
595                         // Add any padding our dropdown has set
596                         widest += this.Padding.Horizontal;
597                         
598                         int x = this.Padding.Left;
599                         int y = this.Padding.Top;
600
601                         foreach (ToolStripItem tsi in this.Items) {
602                                 if (!tsi.Available)
603                                         continue;
604
605                                 y += tsi.Margin.Top;
606
607                                 int height = 0;
608
609                                 Size preferred_size = tsi.GetPreferredSize (Size.Empty);
610
611                                 if (preferred_size.Height > 22)
612                                         height = preferred_size.Height;
613                                 else if (tsi is ToolStripSeparator)
614                                         height = 7;
615                                 else
616                                         height = 22;
617
618                                 tsi.SetBounds (new Rectangle (x, y, preferred_size.Width, height));
619                                 y += height + tsi.Margin.Bottom;
620                         }
621
622                         this.Size = new Size (widest, y + this.Padding.Bottom);
623                         this.SetDisplayedItems ();
624                         this.OnLayoutCompleted (EventArgs.Empty);
625                         this.Invalidate ();
626                 }
627
628                 protected override void OnMouseUp (MouseEventArgs mea)
629                 {
630                         base.OnMouseUp (mea);
631                 }
632
633                 protected virtual void OnOpened (EventArgs e)
634                 {
635                         EventHandler eh = (EventHandler)(Events [OpenedEvent]);
636                         if (eh != null)
637                                 eh (this, e);
638                 }
639
640                 protected virtual void OnOpening (CancelEventArgs e)
641                 {
642                         CancelEventHandler eh = (CancelEventHandler)(Events [OpeningEvent]);
643                         if (eh != null)
644                                 eh (this, e);
645                 }
646
647                 protected override void OnParentChanged (EventArgs e)
648                 {
649                         base.OnParentChanged (e);
650                         
651                         if (Parent is ToolStrip)
652                                 this.Renderer = (Parent as ToolStrip).Renderer;
653                 }
654
655                 protected override void OnVisibleChanged (EventArgs e)
656                 {
657                         base.OnVisibleChanged (e);
658
659                         if (owner_item != null && owner_item is ToolStripDropDownItem) {
660                                 ToolStripDropDownItem dropdown_owner = (ToolStripDropDownItem)owner_item;
661                                 if (Visible)
662                                         dropdown_owner.OnDropDownOpened (EventArgs.Empty);
663                                 else
664                                         dropdown_owner.OnDropDownClosed (EventArgs.Empty);
665                         }
666                 }
667
668                 [EditorBrowsable (EditorBrowsableState.Advanced)]
669                 protected override bool ProcessDialogChar (char charCode)
670                 {
671                         return base.ProcessDialogChar (charCode);
672                 }
673
674                 protected override bool ProcessDialogKey (Keys keyData)
675                 {
676                         // We don't want to let our base change the active ToolStrip
677                         switch (keyData) {
678                                 case Keys.Control | Keys.Tab:
679                                 case Keys.Control | Keys.Shift | Keys.Tab:
680                                         return true;
681                         }
682                         
683                         return base.ProcessDialogKey (keyData);
684                 }
685
686                 protected override bool ProcessMnemonic (char charCode)
687                 {
688                         return base.ProcessMnemonic (charCode);
689                 }
690
691                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
692                 {
693                         base.ScaleControl (factor, specified);
694                 }
695                 
696                 [EditorBrowsable (EditorBrowsableState.Never)]
697                 protected override void ScaleCore (float dx, float dy)
698                 {
699                         base.ScaleCore (dx, dy);
700                 }
701
702                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
703                 {
704                         base.SetBoundsCore (x, y, width, height, specified);
705                 }
706
707                 protected override void SetVisibleCore (bool visible)
708                 {
709                         base.SetVisibleCore (visible);
710                 }
711
712                 protected override void WndProc (ref Message m)
713                 {
714                         const int MA_NOACTIVATE = 0x0003;
715
716                         // Don't activate when the WM tells us to
717                         if ((Msg)m.Msg == Msg.WM_MOUSEACTIVATE) {
718                                 m.Result = (IntPtr)MA_NOACTIVATE;
719                                 return;
720                         }
721
722                         base.WndProc (ref m);
723                 }
724                 #endregion
725
726                 #region Public Events
727                 static object ClosedEvent = new object ();
728                 static object ClosingEvent = new object ();
729                 static object OpenedEvent = new object ();
730                 static object OpeningEvent = new object ();
731                 static object ScrollEvent = new object ();
732
733                 [Browsable (false)]
734                 public new event EventHandler BackgroundImageChanged {
735                         add { base.BackgroundImageChanged += value; }
736                         remove { base.BackgroundImageChanged -= value; }
737                 }
738
739                 [Browsable (false)]
740                 public new event EventHandler BackgroundImageLayoutChanged {
741                         add { base.BackgroundImageLayoutChanged += value; }
742                         remove { base.BackgroundImageLayoutChanged -= value; }
743                 }
744
745                 [Browsable (false)]
746                 public new event EventHandler BindingContextChanged {
747                         add { base.BindingContextChanged += value; }
748                         remove { base.BindingContextChanged -= value; }
749                 }
750
751                 [Browsable (false)]
752                 [EditorBrowsable (EditorBrowsableState.Always)]
753                 public new event UICuesEventHandler ChangeUICues {
754                         add { base.ChangeUICues += value; }
755                         remove { base.ChangeUICues -= value; }
756                 }
757
758                 public event ToolStripDropDownClosedEventHandler Closed {
759                         add { Events.AddHandler (ClosedEvent, value); }
760                         remove { Events.RemoveHandler (ClosedEvent, value); }
761                 }
762
763                 public event ToolStripDropDownClosingEventHandler Closing {
764                         add { Events.AddHandler (ClosingEvent, value); }
765                         remove { Events.RemoveHandler (ClosingEvent, value); }
766                 }
767
768                 [Browsable (false)]
769                 [EditorBrowsable (EditorBrowsableState.Never)]
770                 public new event EventHandler ContextMenuChanged {
771                         add { base.ContextMenuChanged += value; }
772                         remove { base.ContextMenuChanged -= value; }
773                 }
774
775                 [Browsable (false)]
776                 [EditorBrowsable (EditorBrowsableState.Always)]
777                 public new event EventHandler ContextMenuStripChanged {
778                         add { base.ContextMenuStripChanged += value; }
779                         remove { base.ContextMenuStripChanged -= value; }
780                 }
781
782                 [Browsable (false)]
783                 [EditorBrowsable (EditorBrowsableState.Always)]
784                 public new event EventHandler DockChanged {
785                         add { base.DockChanged += value; }
786                         remove { base.DockChanged -= value; }
787                 }
788
789                 [Browsable (false)]
790                 [EditorBrowsable (EditorBrowsableState.Always)]
791                 public new event EventHandler Enter {
792                         add { base.Enter += value; }
793                         remove { base.Enter -= value; }
794                 }
795
796                 [Browsable (false)]
797                 [EditorBrowsable (EditorBrowsableState.Always)]
798                 public new event EventHandler FontChanged {
799                         add { base.FontChanged += value; }
800                         remove { base.FontChanged -= value; }
801                 }
802
803                 [Browsable (false)]
804                 [EditorBrowsable (EditorBrowsableState.Never)]
805                 public new event EventHandler ForeColorChanged {
806                         add { base.ForeColorChanged += value; }
807                         remove { base.ForeColorChanged -= value; }
808                 }
809
810                 [Browsable (false)]
811                 [EditorBrowsable (EditorBrowsableState.Never)]
812                 public new event GiveFeedbackEventHandler GiveFeedback {
813                         add { base.GiveFeedback += value; }
814                         remove { base.GiveFeedback -= value; }
815                 }
816
817                 [Browsable (false)]
818                 [EditorBrowsable (EditorBrowsableState.Always)]
819                 public new event HelpEventHandler HelpRequested {
820                         add { base.HelpRequested += value; }
821                         remove { base.HelpRequested -= value; }
822                 }
823
824                 [Browsable (false)]
825                 [EditorBrowsable (EditorBrowsableState.Always)]
826                 public new event EventHandler ImeModeChanged {
827                         add { base.ImeModeChanged += value; }
828                         remove { base.ImeModeChanged -= value; }
829                 }
830
831                 [Browsable (false)]
832                 [EditorBrowsable (EditorBrowsableState.Always)]
833                 public new event KeyEventHandler KeyDown {
834                         add { base.KeyDown += value; }
835                         remove { base.KeyDown -= value; }
836                 }
837
838                 [Browsable (false)]
839                 [EditorBrowsable (EditorBrowsableState.Always)]
840                 public new event KeyPressEventHandler KeyPress {
841                         add { base.KeyPress += value; }
842                         remove { base.KeyPress -= value; }
843                 }
844
845                 [Browsable (false)]
846                 [EditorBrowsable (EditorBrowsableState.Always)]
847                 public new event KeyEventHandler KeyUp {
848                         add { base.KeyUp += value; }
849                         remove { base.KeyUp -= value; }
850                 }
851
852                 [Browsable (false)]
853                 [EditorBrowsable (EditorBrowsableState.Always)]
854                 public new event EventHandler Leave {
855                         add { base.Leave += value; }
856                         remove { base.Leave -= value; }
857                 }
858
859                 public event EventHandler Opened {
860                         add { Events.AddHandler (OpenedEvent, value); }
861                         remove { Events.RemoveHandler (OpenedEvent, value); }
862                 }
863
864                 public event CancelEventHandler Opening {
865                         add { Events.AddHandler (OpeningEvent, value); }
866                         remove { Events.RemoveHandler (OpeningEvent, value); }
867                 }
868
869                 [Browsable (false)]
870                 [EditorBrowsable (EditorBrowsableState.Always)]
871                 public new event EventHandler RegionChanged {
872                         add { base.RegionChanged += value; }
873                         remove { base.RegionChanged -= value; }
874                 }
875
876                 [Browsable (false)]
877                 [EditorBrowsable (EditorBrowsableState.Never)]
878                 public new event ScrollEventHandler Scroll {
879                         add { Events.AddHandler (ScrollEvent, value); }
880                         remove { Events.RemoveHandler (ScrollEvent, value); }
881                 }
882
883                 [Browsable (false)]
884                 [EditorBrowsable (EditorBrowsableState.Always)]
885                 public new event EventHandler StyleChanged {
886                         add { base.StyleChanged += value; }
887                         remove { base.StyleChanged -= value; }
888                 }
889
890                 [Browsable (false)]
891                 [EditorBrowsable (EditorBrowsableState.Never)]
892                 public new event EventHandler TabIndexChanged {
893                         add { base.TabIndexChanged += value; }
894                         remove { base.TabIndexChanged -= value; }
895                 }
896
897                 [Browsable (false)]
898                 [EditorBrowsable (EditorBrowsableState.Never)]
899                 public new event EventHandler TabStopChanged {
900                         add { base.TabStopChanged += value; }
901                         remove { base.TabStopChanged -= value; }
902                 }
903
904                 [Browsable (false)]
905                 [EditorBrowsable (EditorBrowsableState.Never)]
906                 public new event EventHandler TextChanged {
907                         add { base.TextChanged += value; }
908                         remove { base.TextChanged -= value; }
909                 }
910
911                 [Browsable (false)]
912                 [EditorBrowsable (EditorBrowsableState.Never)]
913                 public new event EventHandler Validated {
914                         add { base.Validated += value; }
915                         remove { base.Validated -= value; }
916                 }
917
918                 [Browsable (false)]
919                 [EditorBrowsable (EditorBrowsableState.Never)]
920                 public new event CancelEventHandler Validating {
921                         add { base.Validating += value; }
922                         remove { base.Validating -= value; }
923                 }
924                 #endregion
925
926                 #region Private Methods
927                 internal override void Dismiss (ToolStripDropDownCloseReason reason)
928                 {
929                         this.Close (reason);
930                         base.Dismiss (reason);
931                 }
932
933                 internal override ToolStrip GetTopLevelToolStrip ()
934                 {
935                         if (this.OwnerItem == null)
936                                 return this;
937                                 
938                         return this.OwnerItem.GetTopLevelToolStrip ();
939                 }
940
941                 internal override bool ProcessArrowKey (Keys keyData)
942                 {
943                         switch (keyData) {
944                                 case Keys.Down:
945                                 case Keys.Tab:
946                                         this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), true);
947                                         return true;
948                                 case Keys.Up:
949                                 case Keys.Shift | Keys.Tab:
950                                         this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), false);
951                                         return true;
952                                 case Keys.Right:
953                                         this.GetTopLevelToolStrip ().SelectNextToolStripItem (this.TopLevelOwnerItem, true);
954                                         return true;
955                                 case Keys.Left:
956                                 case Keys.Escape:
957                                         this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
958                                         
959                                         // ContextMenuStrip won't have a parent
960                                         if (this.OwnerItem == null)
961                                                 return true;
962                                                 
963                                         ToolStrip parent_strip = this.OwnerItem.Parent;
964                                         ToolStripManager.SetActiveToolStrip (parent_strip, true);
965                                         
966                                         if (parent_strip is MenuStrip && keyData == Keys.Left) {
967                                                 parent_strip.SelectNextToolStripItem (this.TopLevelOwnerItem, false);
968                                                 this.TopLevelOwnerItem.Invalidate ();
969                                         } else if (parent_strip is MenuStrip && keyData == Keys.Escape) {
970                                                 (parent_strip as MenuStrip).MenuDroppedDown = false;
971                                                 this.TopLevelOwnerItem.Select ();
972                                         }                               
973                                         return true;
974                         }
975                         
976                         return false;
977                 }
978
979                 internal override ToolStripItem SelectNextToolStripItem (ToolStripItem start, bool forward)
980                 {
981                         ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Down : ArrowDirection.Up);
982
983                         if (next_item != null)
984                                 this.ChangeSelection (next_item);
985                                 
986                         return (next_item);
987                 }
988                 
989                 private void ToolStripMenuTracker_AppFocusChange (object sender, EventArgs e)
990                 {
991                         this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
992                 }
993
994                 private void ToolStripMenuTracker_AppClicked (object sender, EventArgs e)
995                 {
996                         this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppClicked);
997                 }
998                 #endregion
999
1000                 #region Internal Properties
1001                 internal override bool ActivateOnShow { get { return false; } }
1002                 
1003                 internal ToolStripItem TopLevelOwnerItem {
1004                         get {
1005                                 ToolStripItem owner_item = this.OwnerItem;
1006                                 ToolStrip ts = null;
1007
1008                                 while (owner_item != null) {
1009                                         ts = owner_item.Owner;
1010
1011                                         if (ts != null && (ts is ToolStripDropDown))
1012                                                 owner_item = (ts as ToolStripDropDown).OwnerItem;
1013                                         else
1014                                                 return owner_item;
1015                                 }
1016
1017                                 return null;
1018                         }
1019                 }
1020                 #endregion
1021
1022                 #region ToolStripDropDownAccessibleObject
1023                 [ComVisible (true)]
1024                 public class ToolStripDropDownAccessibleObject : ToolStripAccessibleObject
1025                 {
1026                         #region Public Constructor
1027                         public ToolStripDropDownAccessibleObject (ToolStripDropDown owner) : base (owner)
1028                         {
1029                         }
1030                         #endregion
1031                         
1032                         #region Public Properties
1033                         public override string Name {
1034                                 get { return base.Name; }
1035                                 set { base.Name = value; }
1036                         }
1037
1038                         public override AccessibleRole Role {
1039                                 get { return AccessibleRole.MenuPopup; }
1040                         }
1041                         #endregion
1042                 }
1043                 #endregion
1044         }
1045 }
1046 #endif