* TabControl.cs: Show the tooltip depending on the value
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripManager.cs
1 //
2 // ToolStripManager.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 using System.Collections.Generic;
34
35 namespace System.Windows.Forms
36 {
37         public sealed class ToolStripManager
38         {
39                 private static ToolStripRenderer renderer = new ToolStripProfessionalRenderer ();
40                 private static ToolStripManagerRenderMode render_mode = ToolStripManagerRenderMode.Professional;
41                 private static bool visual_styles_enabled = Application.RenderWithVisualStyles;
42                 private static List<WeakReference> toolstrips = new List<WeakReference> ();
43                 private static List<ToolStripMenuItem> menu_items = new List<ToolStripMenuItem> ();
44                 private static bool activated_by_keyboard;
45                 
46                 #region Private Constructor
47                 private ToolStripManager ()
48                 {
49                 }
50                 #endregion
51
52                 #region Public Properties
53                 public static ToolStripRenderer Renderer {
54                         get { return ToolStripManager.renderer; }
55                         set {
56                                 if (ToolStripManager.Renderer != value) {
57                                         ToolStripManager.renderer = value;
58                                         ToolStripManager.OnRendererChanged (EventArgs.Empty);
59                                 }
60                         }
61                 }
62
63                 public static ToolStripManagerRenderMode RenderMode {
64                         get { return ToolStripManager.render_mode; }
65                         set {
66                                 if (!Enum.IsDefined (typeof (ToolStripManagerRenderMode), value))
67                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripManagerRenderMode", value));
68
69                                 if (ToolStripManager.render_mode != value) {
70                                         ToolStripManager.render_mode = value;
71
72                                         switch (value) {
73                                                 case ToolStripManagerRenderMode.Custom:
74                                                         throw new NotSupportedException ();
75                                                 case ToolStripManagerRenderMode.System:
76                                                         ToolStripManager.Renderer = new ToolStripSystemRenderer ();
77                                                         break;
78                                                 case ToolStripManagerRenderMode.Professional:
79                                                         ToolStripManager.Renderer = new ToolStripProfessionalRenderer ();
80                                                         break;
81                                         }
82                                 }
83                         }
84                 }
85
86                 public static bool VisualStylesEnabled {
87                         get { return ToolStripManager.visual_styles_enabled; }
88                         set {
89                                 if (ToolStripManager.visual_styles_enabled != value) {
90                                         ToolStripManager.visual_styles_enabled = value;
91
92                                         if (ToolStripManager.render_mode == ToolStripManagerRenderMode.Professional) {
93                                                 (ToolStripManager.renderer as ToolStripProfessionalRenderer).ColorTable.UseSystemColors = !value;
94                                                 ToolStripManager.OnRendererChanged (EventArgs.Empty);
95                                         }
96                                 }
97                         }
98                 }
99                 #endregion
100
101                 #region Public Methods
102                 public static ToolStrip FindToolStrip (string toolStripName)
103                 {
104                         lock (toolstrips)
105                                 foreach (WeakReference wr in toolstrips) {
106                                         ToolStrip ts = (ToolStrip)wr.Target;
107                                         
108                                         if (ts == null)
109                                                 continue;
110                                 
111                                         if (ts.Name == toolStripName)
112                                                 return ts;
113                                 }
114                                                 
115                         return null;
116                 }
117                 
118                 public static bool IsShortcutDefined (Keys shortcut)
119                 {
120                         lock (menu_items)
121                                 foreach (ToolStripMenuItem tsmi in menu_items)
122                                         if (tsmi.ShortcutKeys == shortcut)
123                                                 return true;
124
125                         return false;
126                 }
127                 
128                 public static bool IsValidShortcut (Keys shortcut)
129                 {
130                         // Anything with an F1 - F12 is a shortcut
131                         if ((shortcut & Keys.F1) == Keys.F1)
132                                 return true;
133                         else if ((shortcut & Keys.F2) == Keys.F2)
134                                 return true;
135                         else if ((shortcut & Keys.F3) == Keys.F3)
136                                 return true;
137                         else if ((shortcut & Keys.F4) == Keys.F4)
138                                 return true;
139                         else if ((shortcut & Keys.F5) == Keys.F5)
140                                 return true;
141                         else if ((shortcut & Keys.F6) == Keys.F6)
142                                 return true;
143                         else if ((shortcut & Keys.F7) == Keys.F7)
144                                 return true;
145                         else if ((shortcut & Keys.F8) == Keys.F8)
146                                 return true;
147                         else if ((shortcut & Keys.F9) == Keys.F9)
148                                 return true;
149                         else if ((shortcut & Keys.F10) == Keys.F10)
150                                 return true;
151                         else if ((shortcut & Keys.F11) == Keys.F11)
152                                 return true;
153                         else if ((shortcut & Keys.F12) == Keys.F12)
154                                 return true;
155                                 
156                         // Modifier keys alone are not shortcuts
157                         switch (shortcut) {
158                                 case Keys.Alt:
159                                 case Keys.Control:
160                                 case Keys.Shift:
161                                 case Keys.Alt | Keys.Control:
162                                 case Keys.Alt | Keys.Shift:
163                                 case Keys.Control | Keys.Shift:
164                                 case Keys.Alt | Keys.Control | Keys.Shift:
165                                         return false;
166                         }
167         
168                         // Anything else with a modifier key is a shortcut
169                         if ((shortcut & Keys.Alt) == Keys.Alt)
170                                 return true;
171                         else if ((shortcut & Keys.Control) == Keys.Control)
172                                 return true;
173                         else if ((shortcut & Keys.Shift) == Keys.Shift)
174                                 return true;
175
176                         // Anything else is not a shortcut
177                         return false;
178                 }
179
180                 [MonoTODO ("Stub, does nothing")]
181                 public static void LoadSettings (Form targetForm)
182                 {
183                         if (targetForm == null)
184                                 throw new ArgumentNullException ("targetForm");
185                 }
186
187                 [MonoTODO ("Stub, does nothing")]
188                 public static void LoadSettings (Form targetForm, string key)
189                 {
190                         if (targetForm == null)
191                                 throw new ArgumentNullException ("targetForm");
192                         if (string.IsNullOrEmpty (key))
193                                 throw new ArgumentNullException ("key");
194                 }
195                 
196                 [MonoLimitation ("Only supports one level of merging, cannot merge the same ToolStrip multiple times")]
197                 public static bool Merge (ToolStrip sourceToolStrip, string targetName)
198                 {
199                         if (string.IsNullOrEmpty (targetName))
200                                 throw new ArgumentNullException ("targetName");
201                                 
202                         return Merge (sourceToolStrip, FindToolStrip (targetName));
203                 }
204                 
205                 [MonoLimitation ("Only supports one level of merging, cannot merge the same ToolStrip multiple times")]
206                 public static bool Merge (ToolStrip sourceToolStrip, ToolStrip targetToolStrip)
207                 {
208                         // Check for exceptions
209                         if (sourceToolStrip == null)
210                                 throw new ArgumentNullException ("sourceToolStrip");
211                                 
212                         if (targetToolStrip == null)
213                                 throw new ArgumentNullException ("targetName");
214                                 
215                         if (targetToolStrip == sourceToolStrip)
216                                 throw new ArgumentException ("Source and target ToolStrip must be different.");
217                         
218                         // If the toolstrips don't allow merging, don't merge them
219                         if (!sourceToolStrip.AllowMerge || !targetToolStrip.AllowMerge)
220                                 return false;
221                         
222                         // We currently can't support merging multiple times
223                         if (sourceToolStrip.IsCurrentlyMerged || targetToolStrip.IsCurrentlyMerged)
224                                 return false;
225                                 
226                         // What I wouldn't give to be able to modify a collection
227                         // while enumerating through it...
228
229                         List<ToolStripItem> items_to_move = new List<ToolStripItem> ();
230                         
231                         // Create a list of every ToolStripItem we plan on moving
232                         foreach (ToolStripItem tsi in sourceToolStrip.Items) {
233                                 switch (tsi.MergeAction) {
234                                         case MergeAction.Append:
235                                         default:
236                                                 items_to_move.Add (tsi);
237                                                 break;
238                                         case MergeAction.Insert:
239                                                 if (tsi.MergeIndex >= 0)
240                                                         items_to_move.Add (tsi);
241                                                 break;
242                                         case MergeAction.Replace:
243                                         case MergeAction.Remove:
244                                         case MergeAction.MatchOnly:
245                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
246                                                         if (tsi.Text == target_tsi.Text) {
247                                                                 items_to_move.Add (tsi);
248                                                                 break;
249                                                         }
250                                                 break;
251                                 }
252                         }
253
254                         // If there was nothing valid to merge, return false
255                         if (items_to_move.Count == 0)
256                                 return false;
257                                 
258                         // Set some state so we can unmerge later
259                         sourceToolStrip.BeginMerge ();
260                         targetToolStrip.BeginMerge ();                  
261
262                         sourceToolStrip.SuspendLayout ();
263                         targetToolStrip.SuspendLayout ();
264         
265                         while (items_to_move.Count > 0) {
266                                 ToolStripItem tsi = items_to_move[0];
267                                 items_to_move.Remove (tsi);
268                                 
269                                 switch (tsi.MergeAction) {
270                                         case MergeAction.Append:
271                                         default:
272                                                 // Just changing the parent will append it to the target
273                                                 // and remove it from the source
274                                                 ToolStrip.SetItemParent (tsi, targetToolStrip);
275                                                 
276                                                 break;
277                                         case MergeAction.Insert:
278                                                 // Do the same work as Append, except Insert it into the
279                                                 // location specified by the MergeIndex
280                                                 RemoveItemFromParentToolStrip (tsi);
281
282                                                 if (tsi.MergeIndex == -1)
283                                                         continue;
284                                                 else if (tsi.MergeIndex >= CountRealToolStripItems (targetToolStrip))
285                                                         targetToolStrip.Items.AddNoOwnerOrLayout (tsi);                                         
286                                                 else
287                                                         targetToolStrip.Items.InsertNoOwnerOrLayout (AdjustItemMergeIndex (targetToolStrip, tsi), tsi);
288
289                                                 tsi.Parent = targetToolStrip;
290                                                 
291                                                 break;
292                                         case MergeAction.Replace:
293                                                 // Find a target ToolStripItem with the same Text, remove it
294                                                 // and replace it with the source one
295                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
296                                                         if (tsi.Text == target_tsi.Text) {
297                                                                 RemoveItemFromParentToolStrip (tsi);
298
299                                                                 // Insert where the old one is, then remove the old one
300                                                                 targetToolStrip.Items.InsertNoOwnerOrLayout (targetToolStrip.Items.IndexOf (target_tsi), tsi);
301                                                                 targetToolStrip.Items.RemoveNoOwnerOrLayout (target_tsi);
302
303                                                                 // Store the replaced one so we can get it back in unmerge
304                                                                 targetToolStrip.HiddenMergedItems.Add (target_tsi);
305                                                                 break;
306                                                         }
307
308                                                 break;
309                                         case MergeAction.Remove:
310                                                 // Find a target ToolStripItem with the same Text, and remove
311                                                 // it from the target, nothing else
312                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
313                                                         if (tsi.Text == target_tsi.Text) {
314                                                                 targetToolStrip.Items.RemoveNoOwnerOrLayout (target_tsi);
315                                                                 
316                                                                 // Store the removed one so we can get it back in unmerge
317                                                                 targetToolStrip.HiddenMergedItems.Add (target_tsi);
318                                                                 break;
319                                                         }
320
321                                                 break;
322                                         case MergeAction.MatchOnly:
323                                                 // Ugh, find the target ToolStripItem with the same Text, and take
324                                                 // all the subitems from the source one, and append it to the target one
325                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
326                                                         if (tsi.Text == target_tsi.Text) {
327                                                                 if (target_tsi is ToolStripMenuItem && tsi is ToolStripMenuItem) {
328                                                                         ToolStripMenuItem source = (ToolStripMenuItem)tsi;
329                                                                         ToolStripMenuItem target = (ToolStripMenuItem)target_tsi;
330                                                                         
331                                                                         ToolStripManager.Merge (source.DropDown, target.DropDown);
332                                                                 }
333                                                                 
334                                                                 break;
335                                                         }
336                                                 
337                                                 break;
338                                 }
339                         }
340                         
341                         sourceToolStrip.ResumeLayout ();
342                         targetToolStrip.ResumeLayout ();
343                         
344                         // Store who we merged with, so we can unmerge when only given the target toolstrip
345                         sourceToolStrip.CurrentlyMergedWith = targetToolStrip;
346                         targetToolStrip.CurrentlyMergedWith = sourceToolStrip;
347                         
348                         return true;
349                 }
350
351                 public static bool RevertMerge (string targetName)
352                 {
353                         return RevertMerge (FindToolStrip (targetName));
354                 }
355                 
356                 public static bool RevertMerge (ToolStrip targetToolStrip)
357                 {
358                         return RevertMerge (targetToolStrip, targetToolStrip.CurrentlyMergedWith);                      
359                 }
360                 
361                 public static bool RevertMerge (ToolStrip targetToolStrip, ToolStrip sourceToolStrip)
362                 {
363                         if (sourceToolStrip == null)
364                                 throw new ArgumentNullException ("sourceToolStrip");
365                                 
366                         List<ToolStripItem> items_to_move = new List<ToolStripItem> ();
367                         
368                         // Find every ToolStripItem who's Owner is the source toolstrip
369                         // - If it's a TSMI, see if any of the subitems need to be moved back
370                         foreach (ToolStripItem tsi in targetToolStrip.Items) {
371                                 if (tsi.Owner == sourceToolStrip)
372                                         items_to_move.Add (tsi);
373                                 else if (tsi is ToolStripMenuItem)
374                                         foreach (ToolStripItem menuitem in (tsi as ToolStripMenuItem).DropDownItems)
375                                                 foreach (ToolStripMenuItem tsmi in sourceToolStrip.Items)
376                                                         if (menuitem.Owner == tsmi.DropDown)
377                                                                 items_to_move.Add (menuitem);   
378                         }
379
380                         // If we didn't find anything, return false
381                         if (items_to_move.Count == 0 && targetToolStrip.HiddenMergedItems.Count == 0)
382                                 return false;
383
384                         // Put back all the target's items removed in the merge
385                         while (targetToolStrip.HiddenMergedItems.Count > 0) {
386                                 targetToolStrip.RevertMergeItem (targetToolStrip.HiddenMergedItems[0]);
387                                 targetToolStrip.HiddenMergedItems.RemoveAt (0);
388                         }
389                                 
390                         sourceToolStrip.SuspendLayout ();
391                         targetToolStrip.SuspendLayout ();
392                         
393                         // Revert everything
394                         while (items_to_move.Count > 0) {
395                                 sourceToolStrip.RevertMergeItem (items_to_move[0]);
396                                 items_to_move.Remove (items_to_move[0]);
397                         }
398
399                         sourceToolStrip.ResumeLayout ();
400                         targetToolStrip.ResumeLayout ();
401                         
402                         sourceToolStrip.IsCurrentlyMerged = false;
403                         targetToolStrip.IsCurrentlyMerged = false;
404
405                         sourceToolStrip.CurrentlyMergedWith = null;
406                         targetToolStrip.CurrentlyMergedWith = null;
407
408                         return true;
409                 }
410
411                 public static void SaveSettings (Form sourceForm)
412                 {
413                         if (sourceForm == null)
414                                 throw new ArgumentNullException ("sourceForm");
415                 }
416
417                 public static void SaveSettings (Form sourceForm, string key)
418                 {
419                         if (sourceForm == null)
420                                 throw new ArgumentNullException ("sourceForm");
421                         if (string.IsNullOrEmpty (key))
422                                 throw new ArgumentNullException ("key");
423                 }
424                 #endregion
425                 
426                 #region Public Events
427                 public static event EventHandler RendererChanged;
428                 #endregion
429
430                 #region Private/Internal Methods
431                 internal static bool ActivatedByKeyboard {
432                         get { return activated_by_keyboard; }
433                         set { activated_by_keyboard = value; }
434                 }
435                 
436                 internal static void AddToolStrip (ToolStrip ts)
437                 {
438                         lock (toolstrips)
439                                 toolstrips.Add (new WeakReference (ts));
440                 }
441
442                 // When we have merged in MDI items like the min/max/close buttons, we
443                 // can't count them for the sake of menu merging or it will mess up
444                 // where people are trying to put them
445                 private static int AdjustItemMergeIndex (ToolStrip ts, ToolStripItem tsi)
446                 {                       
447                         if (ts.Items[0] is MdiControlStrip.SystemMenuItem)
448                                 return tsi.MergeIndex + 1;
449                                 
450                         return tsi.MergeIndex;
451                 }
452                 
453                 private static int CountRealToolStripItems (ToolStrip ts)
454                 {
455                         int count = 0;
456                         
457                         foreach (ToolStripItem tsi in ts.Items)
458                                 if (!(tsi is MdiControlStrip.ControlBoxMenuItem) && !(tsi is MdiControlStrip.SystemMenuItem))
459                                         count++;
460                                         
461                         return count; 
462                 }
463                 
464                 internal static ToolStrip GetNextToolStrip (ToolStrip ts, bool forward)
465                 {
466                         lock (toolstrips) {
467                                 List<ToolStrip> tools = new List<ToolStrip> ();
468                                 
469                                 foreach (WeakReference wr in toolstrips) {
470                                         ToolStrip t = (ToolStrip)wr.Target;
471                                         
472                                         if (t != null)
473                                                 tools.Add (t);
474                                 }
475                                 
476                                 int index = tools.IndexOf (ts);
477
478                                 if (forward) {
479                                         // Look for any toolstrip after this one in the collection
480                                         for (int i = index + 1; i < tools.Count; i++)
481                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
482                                                         return tools[i];
483
484                                         // Look for any toolstrip before this one in the collection
485                                         for (int i = 0; i < index; i++)
486                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
487                                                         return tools[i];
488                                 } else {
489                                         // Look for any toolstrip before this one in the collection
490                                         for (int i = index - 1; i >= 0; i--)
491                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
492                                                         return tools[i];
493
494                                         // Look for any toolstrip after this one in the collection
495                                         for (int i = tools.Count - 1; i > index; i--)
496                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
497                                                         return tools[i];
498                                 }
499                         }
500                         
501                         return null;
502                 }
503                 
504                 internal static bool ProcessCmdKey (ref Message m, Keys keyData)
505                 {
506                         lock (menu_items)
507                                 foreach (ToolStripMenuItem tsmi in menu_items)
508                                         if (tsmi.ProcessCmdKey (ref m, keyData) == true)
509                                                 return true;
510                         
511                         return false;
512                 }
513                 
514                 internal static bool ProcessMenuKey (ref Message m)
515                 {
516                         // If we have a currently active menu, deactivate it
517                         if (Application.KeyboardCapture != null) {
518                                 if (Application.KeyboardCapture.OnMenuKey ())
519                                         return true;
520                         }
521                         
522                         // Get the parent form of this message
523                         Form f = (Form)Control.FromHandle (m.HWnd).TopLevelControl;
524
525                         // If there isn't a Form with this, there isn't much we can do
526                         if (f == null)
527                                 return false;
528                                 
529                         // Check the MainMenuStrip property first
530                         if (f.MainMenuStrip != null)
531                                 if (f.MainMenuStrip.OnMenuKey ())
532                                         return true;
533                                         
534                         // Look for any MenuStrip in the form
535                         lock (toolstrips)
536                                 foreach (WeakReference wr in toolstrips) {
537                                         ToolStrip ts = (ToolStrip)wr.Target;
538
539                                         if (ts == null)
540                                                 continue;
541                                 
542                                         if (ts.TopLevelControl == f)
543                                                 if (ts.OnMenuKey ())
544                                                         return true;
545                                 }
546
547                         return false;
548                 }
549                 
550                 internal static void SetActiveToolStrip (ToolStrip toolStrip, bool keyboard)
551                 {
552                         if (Application.KeyboardCapture != null)
553                                 Application.KeyboardCapture.KeyboardActive = false;
554                                 
555                         if (toolStrip == null) {
556                                 activated_by_keyboard = false;
557                                 return;
558                         }
559                         
560                         activated_by_keyboard = keyboard;
561                                 
562                         toolStrip.KeyboardActive = true;
563                 }
564                 
565                 internal static void AddToolStripMenuItem (ToolStripMenuItem tsmi)
566                 {
567                         lock (menu_items)
568                                 menu_items.Add (tsmi);
569                 }
570                 
571                 internal static void RemoveToolStrip (ToolStrip ts)
572                 {
573                         lock (toolstrips) {
574                                 foreach (WeakReference wr in toolstrips)
575                                         if (wr.Target == ts) {
576                                                 toolstrips.Remove (wr);
577                                                 return;
578                                         }
579                         }
580                 }
581
582                 internal static void RemoveToolStripMenuItem (ToolStripMenuItem tsmi)
583                 {
584                         lock (menu_items)
585                                 menu_items.Remove (tsmi);
586                 }
587
588                 internal static void FireAppClicked ()
589                 {
590                         if (AppClicked != null) AppClicked (null, EventArgs.Empty);
591                         
592                         if (Application.KeyboardCapture != null)
593                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppClicked);
594                 }
595
596                 internal static void FireAppFocusChanged (Form form)
597                 {
598                         if (AppFocusChange != null) AppFocusChange (form, EventArgs.Empty);
599
600                         if (Application.KeyboardCapture != null)
601                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
602                 }
603
604                 internal static void FireAppFocusChanged (object sender)
605                 {
606                         if (AppFocusChange != null) AppFocusChange (sender, EventArgs.Empty);
607
608                         if (Application.KeyboardCapture != null)
609                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
610                 }
611                 
612                 private static void OnRendererChanged (EventArgs e)
613                 {
614                         if (RendererChanged != null) RendererChanged (null, e);
615                 }
616
617                 private static void RemoveItemFromParentToolStrip (ToolStripItem tsi)
618                 {
619                         if (tsi.Owner != null) {
620                                 tsi.Owner.Items.RemoveNoOwnerOrLayout (tsi);
621
622                                 if (tsi.Owner is ToolStripOverflow)
623                                         (tsi.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (tsi);
624                         }
625                 }
626                 
627                 internal static event EventHandler AppClicked;
628                 internal static event EventHandler AppFocusChange;
629                 #endregion
630         }
631 }
632 #endif