1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 using System;
   7 using System.Collections;
   8 using System.Windows.API;
   9 
  10 namespace System.Windows
  11 {
  12     public nothrow Color DefaultMenuBackgroundColor()
  13     {
  14         return GetSystemColor(SystemColor.COLOR_MENU);
  15     }
  16 
  17     public nothrow Color DefaultMenuTextColor()
  18     {
  19         return GetSystemColor(SystemColor.COLOR_MENUTEXT);
  20     }
  21 
  22     public nothrow Color DefaultDisabledMenuTextColor()
  23     {
  24         Color color = GetSystemColor(SystemColor.COLOR_GRAYTEXT);
  25         if (color == Color.Black())
  26         {
  27             return Color(195u195u198u);
  28         }
  29         return color;
  30     }
  31 
  32     public nothrow Color DefaultMenuMouseOverColor()
  33     {
  34         return Color(201u222u245u);
  35     }
  36 
  37     public nothrow Color DefaultMenuOpenColor()
  38     {
  39         return Color.White();
  40     }
  41 
  42     public nothrow ControlCreateParams& MenuControlControlCreateParams(ControlCreateParams& controlCreateParams)
  43     {
  44         return controlCreateParams.SetWindowClassBackgroundColor(SystemColor.COLOR_MENU).SetBackgroundColor(DefaultMenuBackgroundColor());
  45     }
  46 
  47     public class MenuControlCreateParams
  48     {
  49         public nothrow MenuControlCreateParams(ControlCreateParams& controlCreateParams_) : 
  50             controlCreateParams(controlCreateParams_)
  51             fontFamilyName("Segoe UI")
  52             fontSize(9.0f)
  53             textColor(DefaultMenuTextColor())
  54             disabledTextColor(DefaultDisabledMenuTextColor())
  55             mouseOverColor(DefaultMenuMouseOverColor())
  56             menuOpenColor(DefaultMenuOpenColor())
  57         {
  58         }
  59         public nothrow MenuControlCreateParams& Defaults()
  60         {
  61             return *this;
  62         }
  63         public ControlCreateParams& controlCreateParams;
  64         public string fontFamilyName;
  65         public float fontSize;
  66         public Color textColor;
  67         public Color disabledTextColor;
  68         public Color mouseOverColor;
  69         public Color menuOpenColor;
  70     }
  71 
  72     public abstract class MenuControl : Control
  73     {
  74         public MenuControl(const Font& font_const string& windowClassNameWindowClassStyle windowClassStyleWindowStyle style
  75             ExtendedWindowStyle exStyle
  76             const Color& backgroundColorconst string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
  77             base(windowClassNamewindowClassStylestyleexStylebackgroundColortextlocationsizedockanchors)
  78             font(font_)textColor(DefaultMenuTextColor())disabledTextColor(DefaultDisabledMenuTextColor())mouseOverColor(201u222u245u)
  79             menuOpenColor(Color.White())shadowColor(ShadowColor())textBrush(textColor)disabledTextBrush(disabledTextColor)
  80             backgroundBrush(BackgroundColor())mouseOverBrush(mouseOverColor)menuOpenBrush(menuOpenColor)
  81             shadowBrush(shadowColor)blackBrush(Color.Black())blackPen(Color.Black())darkPen(Color.DarkGray())
  82             format(StringAlignment.nearStringAlignment.nearHotKeyPrefix.show)
  83         {
  84         }
  85         public MenuControl(MenuControlCreateParams& createParams) : 
  86             base(createParams.controlCreateParams)
  87             font(FontFamily(createParams.fontFamilyName)createParams.fontSize)
  88             textColor(createParams.textColor)
  89             disabledTextColor(createParams.disabledTextColor)
  90             mouseOverColor(createParams.mouseOverColor)
  91             menuOpenColor(createParams.menuOpenColor)
  92             shadowColor(ShadowColor())
  93             textBrush(textColor)disabledTextBrush(disabledTextColor)
  94             backgroundBrush(BackgroundColor())mouseOverBrush(mouseOverColor)menuOpenBrush(menuOpenColor)
  95             shadowBrush(shadowColor)blackBrush(Color.Black())blackPen(Color.Black())darkPen(Color.DarkGray())
  96             format(StringAlignment.nearStringAlignment.nearHotKeyPrefix.show)
  97         {
  98         }
  99         public override nothrow Padding DefaultPadding() const
 100         {
 101             return Padding(6262);
 102         }
 103         public inline nothrow const Font& GetFont() const
 104         {
 105             return font;
 106         }
 107         public inline nothrow const Color& TextColor() const
 108         {
 109             return textColor;
 110         }
 111         public inline nothrow const Color& DisabledTextColor() const
 112         {
 113             return disabledTextColor;
 114         }
 115         public inline nothrow const Color& MouseOverColor() const
 116         {
 117             return mouseOverColor;
 118         }
 119         public inline nothrow const Color& MenuOpenColor() const
 120         {
 121             return menuOpenColor;
 122         }
 123         public inline nothrow const Color& ShadowColor() const
 124         {
 125             return shadowColor;
 126         }
 127         public inline nothrow const Brush& TextBrush() const
 128         {
 129             return textBrush;
 130         }
 131         public inline nothrow const Brush& DisabledTextBrush() const
 132         {
 133             return disabledTextBrush;
 134         }
 135         public inline nothrow const Brush& BackgroundBrush() const
 136         {
 137             return backgroundBrush;
 138         }
 139         public inline nothrow const Brush& MouseOverBrush() const
 140         {
 141             return mouseOverBrush;
 142         }
 143         public inline nothrow const Brush& MenuOpenBrush() const
 144         {
 145             return menuOpenBrush;
 146         }
 147         public inline nothrow const Brush& ShadowBrush() const
 148         {
 149             return shadowBrush;
 150         }
 151         public inline nothrow const Brush& BlackBrush() const
 152         {
 153             return blackBrush;
 154         }
 155         public inline nothrow const Pen& BlackPen() const
 156         {
 157             return blackPen;
 158         }
 159         public inline nothrow const Pen& DarkPen() const
 160         {
 161             return darkPen;
 162         }
 163         public inline nothrow const StringFormat& Format() const
 164         {
 165             return format;
 166         }
 167         internal virtual nothrow MenuItem* GetMenuItemByAccessKey(wchar accessKey)
 168         {
 169             return null;
 170         }
 171         internal virtual nothrow MenuItem* GetOpenedMenuItem() const
 172         {
 173             return null;
 174         }
 175         internal virtual nothrow MenuItem* GetSelectedMenuItem() const
 176         {
 177             return null;
 178         }
 179         internal virtual nothrow void SetSelectedMenuItem(MenuItem* selectedMenuItem_)
 180         {
 181         }
 182         internal virtual nothrow bool IsOpen() const
 183         {
 184             return false;
 185         }
 186         public virtual nothrow void SetOpen()
 187         {
 188         }
 189         internal virtual nothrow void SetClosed()
 190         {
 191         }
 192         internal virtual nothrow void SetMenuInvalidated()
 193         {
 194         }
 195         internal virtual nothrow MenuItem* GetFirstMenuItem() const
 196         {
 197             return null;
 198         }
 199         internal virtual nothrow MenuItem* GetLastMenuItem() const
 200         {
 201             return null;
 202         }
 203         internal virtual nothrow MenuItem* LatestOpenedMenuItem() const
 204         {
 205             return null;
 206         }
 207         internal virtual nothrow void SetLatestOpenedMenuItem(MenuItem* menuItem)
 208         {
 209         }
 210         internal virtual nothrow MenuItem* GetLatestMouseDownMenuItem() const
 211         {
 212             return null;
 213         }
 214         internal virtual nothrow void SetLatestMouseDownMenuItem(MenuItem* menuItem)
 215         {
 216         }
 217         internal virtual void InvalidateMenu()
 218         {
 219         }
 220         internal virtual nothrow void SetMenuChanged()
 221         {
 222         }
 223         private Font font;
 224         private Color textColor;
 225         private Color disabledTextColor;
 226         private Color mouseOverColor;
 227         private Color menuOpenColor;
 228         private Color shadowColor;
 229         private SolidBrush textBrush;
 230         private SolidBrush disabledTextBrush;
 231         private SolidBrush backgroundBrush;
 232         private SolidBrush mouseOverBrush;
 233         private SolidBrush menuOpenBrush;
 234         private SolidBrush shadowBrush;
 235         private SolidBrush blackBrush;
 236         private Pen blackPen;
 237         private Pen darkPen;
 238         private StringFormat format;
 239     }
 240 
 241     public const int initialMenuBarHeight = 20;
 242 
 243     public nothrow ControlCreateParams& MenuBarControlCreateParams(ControlCreateParams& controlCreateParams)
 244     {
 245         return controlCreateParams.SetWindowClassBackgroundColor(SystemColor.COLOR_MENU).SetBackgroundColor(DefaultMenuBackgroundColor()).
 246             SetWindowClassName("System.Windows.MenuBar").SetDock(Dock.top).SetSize(Size(0initialMenuBarHeight));
 247     }
 248 
 249     public class MenuBarCreateParams
 250     {
 251         public nothrow MenuBarCreateParams(MenuControlCreateParams& menuControlCreateParams_) : menuControlCreateParams(menuControlCreateParams_)
 252         {
 253         }
 254         public nothrow MenuBarCreateParams& Defaults()
 255         {
 256             return *this;
 257         }
 258         public MenuControlCreateParams& menuControlCreateParams;
 259     }
 260 
 261     public class MenuBar : MenuControl
 262     {
 263         private enum Flags : sbyte
 264         {
 265             noneopen = 1 << 0menuChanged = 1 << 1menuBoxAdded = 1 << 2menuInvalidated = 1 << 3menuKeyDisabled = 1 << 4
 266         }
 267 
 268         internal Color ShadowColor()
 269         {
 270             Color shadowColor = GetSystemColor(SystemColor.COLOR_BTNSHADOW);
 271             shadowColor.alpha = 196u;
 272             return shadowColor;
 273         }
 274 
 275         public MenuBar(const Font& font_) : base(font_"System.Windows.MenuBar"DefaultWindowClassStyle()DefaultChildWindowStyle()
 276             DefaultExtendedWindowStyle()DefaultMenuBackgroundColor()"menuBar"Point()Size(0initialMenuBarHeight)Dock.topAnchors.none)
 277             flags(Flags.none)children(this)latestOpenedMenuItem(null)selectedMenuItem(null)latestMouseDownMenuItem(null)
 278         {
 279             SetMenuChanged();
 280         }
 281         public MenuBar() : this(Font(FontFamily("Segoe UI")9.0f))
 282         {
 283         }
 284         public MenuBar(MenuBarCreateParams& createParams) : 
 285             base(createParams.menuControlCreateParams)
 286             flags(Flags.none)children(this)latestOpenedMenuItem(null)selectedMenuItem(null)latestMouseDownMenuItem(null)
 287         {
 288             SetMenuChanged();
 289         }
 290         public void CloseMenu()
 291         {
 292             if (!IsOpen()) return;
 293             SetClosed();
 294             SetLatestOpenedMenuItem(null);
 295             Component* child = children.FirstChild();
 296             while (child != null)
 297             {
 298                 if (child is MenuItem*)
 299                 {
 300                     MenuItem* menuItem = cast<MenuItem*>(child);
 301                     menuItem->SetState(MenuItem.State.closedthis);
 302                 }
 303                 child = child->NextSibling();
 304             }
 305             InvalidateMenu();
 306         }
 307         public void AddMenuItem(MenuItem* menuItem)
 308         {
 309             children.AddChild(menuItem);
 310             SetMenuChanged();
 311         }
 312         public override void PrintWindowTree(int level)
 313         {
 314             LogView* log = Application.GetLogView();
 315             if (log != null)
 316             {
 317                 log->WriteLine(string(' 'level) + "MenuBar." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point()GetSize()).ToString() + "]");
 318             }
 319         }
 320         protected override void OnPaint(PaintEventArgs& args)
 321         {
 322             try
 323             {
 324                 if (Debug.Paint())
 325                 {
 326                     Rect r(Location()GetSize());
 327                     LogView* log = Application.GetLogView();
 328                     if (log != null)
 329                     {
 330                         log->WriteLine("MenuBar.OnPaint: " + r.ToString());
 331                     }
 332                 }
 333                 if (!MenuBoxAdded())
 334                 {
 335                     SetMenuBoxAdded();
 336                     AddMenuBox();
 337                 }
 338                 args.graphics.Clear(BackgroundColor());
 339                 if (MenuChanged())
 340                 {
 341                     ResetMenuChanged();
 342                     CollectShortcuts();
 343                     Size size = GetSize();
 344                     size.h = cast<int>(GetFont().GetHeight(args.graphics));
 345                     size.h = size.h + DefaultPadding().Vertical();
 346                     SetSize(size);
 347                     LocateMenuItems(args.graphicssize);
 348                 }
 349                 DrawMenuItems(argsfalseLocation());
 350                 base->OnPaint(args);
 351             }
 352             catch (const Exception& ex)
 353             {
 354                 MessageBox.Show(ex.Message());
 355             }
 356         }
 357         private void LocateMenuItems(Graphics& graphicsconst Size& size)
 358         {
 359             Rect itemRect(Location()Size(0size.h));
 360             Padding padding = DefaultPadding();
 361             PointF origin(00);
 362             Component* child = children.FirstChild();
 363             while (child != null)
 364             {
 365                 if (child is MenuItem*)
 366                 {
 367                     MenuItem* menuItem = cast<MenuItem*>(child);
 368                     Padding menuItemPadding = menuItem->DefaultPadding();
 369                     RectF r = graphics.MeasureStringChecked(menuItem->Text()GetFont()originFormat());
 370                     int w = cast<int>(r.size.w) + padding.Horizontal() + menuItemPadding.Horizontal();
 371                     itemRect.size.w = w;
 372                     menuItem->SetLocation(itemRect.location);
 373                     menuItem->SetSize(itemRect.size);
 374                     menuItem->CalculateChildRect(graphicsGetFont()Format()Point(itemRect.location.xitemRect.location.y + itemRect.size.h));
 375                     itemRect.location.x = itemRect.location.x + w;
 376                 }
 377                 child = child->NextSibling();
 378             }
 379         }
 380         private nothrow Control* ParentControl() const
 381         {
 382             Container* container = GetContainer();
 383             if (container != null)
 384             {
 385                 Component* parent = container->Parent();
 386                 if (parent != null && (parent is Control*))
 387                 {
 388                     return cast<Control*>(parent);
 389                 }
 390             }
 391             return null;
 392         }
 393         private void InvalidateParentRect(const Rect& parentRect)
 394         {
 395             Control* parentControl = ParentControl();
 396             if (parentControl != null)
 397             {
 398                 parentControl->Invalidate(parentRect.ToWinRect());
 399             }
 400         }
 401         internal void DrawMenuItems(PaintEventArgs& argsbool drawSubItemsconst Point& origin)
 402         {
 403             Padding padding = DefaultPadding();
 404             Size size = GetSize();
 405             Component* child = children.FirstChild();
 406             while (child != null)
 407             {
 408                 if (child is MenuItem*)
 409                 {
 410                     MenuItem* menuItem = cast<MenuItem*>(child);
 411                     menuItem->Draw(
 412                         args.graphicspaddingTextBrush()DisabledTextBrush()BackgroundBrush()MouseOverBrush()MenuOpenBrush()ShadowBrush()BlackBrush()BlackPen()DarkPen()GetFont()Format()
 413                         MenuOpenColor()thisdrawSubItemsorigin);
 414                 }
 415                 child = child->NextSibling();
 416             }
 417         }
 418         internal void DoKeyDown(KeyEventArgs& args)
 419         {
 420             OnKeyDown(args);
 421         }
 422         protected override void OnKeyDown(KeyEventArgs& args)
 423         {
 424             base->OnKeyDown(args);
 425             if (!args.handled)
 426             {
 427                 HashMap<KeysMenuItem*>.ConstIterator it = shortcuts.CFind(args.key);
 428                 if (it != shortcuts.CEnd())
 429                 {
 430                     MenuItem* menuItem = it->second;
 431                     if (menuItem->IsEnabled())
 432                     {
 433                         menuItem->DoClick();
 434                         args.handled = true;
 435                     }
 436                 }
 437             }
 438         }
 439         internal void MouseEnterInternal()
 440         {
 441             OnMouseEnter();
 442         }
 443         protected override void OnMouseEnter()
 444         {
 445             base->OnMouseEnter();
 446         }
 447         internal void MouseMoveInternal(MouseEventArgs& args)
 448         {
 449             OnMouseMove(args);
 450         }
 451         protected override void OnMouseMove(MouseEventArgs& args)
 452         {
 453             ResetMenuInvalidated();
 454             base->OnMouseMove(args);
 455             bool handled = false;
 456             Component* child = children.FirstChild();
 457             while (child != null)
 458             {
 459                 if (child is MenuItem*)
 460                 {
 461                     MenuItem* menuItem = cast<MenuItem*>(child);
 462                     if (!menuItem->Contains(args.location))
 463                     {
 464                         menuItem->ResetSelected(this);
 465                         if (menuItem->MouseInClient())
 466                         {
 467                             menuItem->ResetMouseInClient();
 468                             menuItem->DoMouseLeave(this);
 469                         }
 470                     }
 471                 }
 472                 child = child->NextSibling();
 473             }
 474             child = children.FirstChild();
 475             while (child != null)
 476             {
 477                 if (child is MenuItem*)
 478                 {
 479                     MenuItem* menuItem = cast<MenuItem*>(child);
 480                     if (menuItem->Contains(args.location))
 481                     {
 482                         menuItem->SetSelected(this);
 483                         if (!menuItem->MouseInClient())
 484                         {
 485                             menuItem->SetMouseInClient();
 486                             menuItem->DoMouseEnter(IsOpen()this);
 487                         }
 488                         else
 489                         {
 490                             menuItem->DoMouseMove(args);
 491                         }
 492                         handled = true;
 493                     }
 494                 }
 495                 child = child->NextSibling();
 496             }
 497             if (!handled)
 498             {
 499                 if (IsOpen())
 500                 {
 501                     if (latestOpenedMenuItem != null)
 502                     {
 503                         Component* child = children.FirstChild();
 504                         while (child != null && !handled)
 505                         {
 506                             if (child is MenuItem*)
 507                             {
 508                                 MenuItem* menuItem = cast<MenuItem*>(child);
 509                                 if (menuItem->IsSameOrParentOf(latestOpenedMenuItem))
 510                                 {
 511                                     menuItem->DispatchMouseMove(argshandledthis);
 512                                 }
 513                             }
 514                             child = child->NextSibling();
 515                         }
 516                     }
 517                 }
 518             }
 519             if (MenuInvalidated())
 520             {
 521                 InvalidateMenu();
 522             }
 523         }
 524         internal void MouseLeaveInternal()
 525         {
 526             OnMouseLeave();
 527         }
 528         protected override void OnMouseLeave()
 529         {
 530             ResetMenuInvalidated();
 531             base->OnMouseLeave();
 532             Component* child = children.FirstChild();
 533             while (child != null)
 534             {
 535                 if (child is MenuItem*)
 536                 {
 537                     MenuItem* menuItem = cast<MenuItem*>(child);
 538                     if (menuItem->MouseInClient() || menuItem->Children().IsEmpty())
 539                     {
 540                         menuItem->ResetSelected(this);
 541                         menuItem->ResetMouseInClient();
 542                         Point mousePos;
 543                         WinGetMessagePos(mousePos.xmousePos.y);
 544                         mousePos = ScreenToClient(mousePos);
 545                         if (menuItem != latestOpenedMenuItem || !menuItem->UnionRectContains(mousePos))
 546                         {
 547                             menuItem->DoMouseLeave(this);
 548                         }
 549                     }
 550                     else
 551                     {
 552                         menuItem->ResetSelected(this);
 553                         menuItem->ResetMouseInClient();
 554                     }
 555                 }
 556                 child = child->NextSibling();
 557             }
 558             if (MenuInvalidated())
 559             {
 560                 InvalidateMenu();
 561             }
 562         }
 563         internal override void InvalidateMenu()
 564         {
 565             Invalidate();
 566             Rect menuRect;
 567             Component* child = children.FirstChild();
 568             while (child != null)
 569             {
 570                 if (child is MenuItem*)
 571                 {
 572                     MenuItem* menuItem = cast<MenuItem*>(child);
 573                     if (menuItem->GetState() == MenuItem.State.open)
 574                     {
 575                         menuItem->GetOpenRect(menuRect);
 576                     }
 577                 }
 578                 child = child->NextSibling();
 579             }
 580             if (IsOpen())
 581             {
 582                 if (menuBox != null)
 583                 {
 584                     menuBox->SetPaintThisMenuBox(true);
 585                     menuBox->SetLocation(Point(Location().x + menuRect.location.xLocation().y + menuRect.location.y));
 586                     menuBox->SetSize(menuRect.size);
 587                     Control* parentControl = ParentControl();
 588                     Control* topControl = null;
 589                     if (parentControl != null)
 590                     {
 591                         topControl = parentControl->TopControl();
 592                     }
 593                     menuBox->BringToFront();
 594                     menuBox->Show();
 595                     menuBox->Invalidate();
 596                     menuBox->Update();
 597                     if (topControl != null)
 598                     {
 599                         topControl->BringToFront();
 600                     }
 601                 }
 602             }
 603             else
 604             {
 605                 if (menuBox != null)
 606                 {
 607                     menuBox->SetPaintThisMenuBox(false);
 608                     menuBox->Hide();
 609                 }
 610                 InvalidateParentRect(menuRect);
 611                 Control* parentControl = ParentControl();
 612                 if (parentControl != null)
 613                 {
 614                     parentControl->Update();
 615                 }
 616             }
 617         }
 618         private void CollectShortcuts()
 619         {
 620             shortcuts.Clear();
 621             Component* child = children.FirstChild();
 622             while (child != null)
 623             {
 624                 if (child is MenuItem*)
 625                 {
 626                     MenuItem* menuItem = cast<MenuItem*>(child);
 627                     menuItem->CollectShortcuts(shortcuts);
 628                 }
 629                 child = child->NextSibling();
 630             }
 631         }
 632         internal bool HandleAccessKey(wchar accessKeyKeys keyCodebool& wantsKeys)
 633         {
 634             ResetMenuInvalidated();
 635             LogView* logView = Application.GetLogView();
 636             if (logView != null)
 637             {
 638                 string s = "MENUBAR: access key = '" + ToString(accessKey) + "' " + ToHexString(cast<ushort>(accessKey)) + ", key code = " + string(keyCodeStr[cast<int>(keyCode)]);
 639                 logView->WriteLine(s);
 640             }
 641             if (accessKey == '\0' && keyCode == Keys.none)
 642             {
 643                 if (!MenuKeyDisabled())
 644                 {
 645                     if (selectedMenuItem == null)
 646                     {
 647                         MenuItem* firstMenuItem = GetFirstMenuItem();
 648                         if (firstMenuItem != null)
 649                         {
 650                             SetOpen();
 651                             SetSelectedMenuItem(firstMenuItem);
 652                             wantsKeys = true;
 653                             InvalidateMenu();
 654                             return true;
 655                         }
 656                     }
 657                     else
 658                     {
 659                         SetClosed();
 660                         MenuItem* openedMenuItem = GetOpenedMenuItem();
 661                         if (openedMenuItem != null)
 662                         {
 663                             openedMenuItem->SetState(MenuItem.State.closedthis);
 664                         }
 665                         selectedMenuItem->ResetSelected(this);
 666                         SetSelectedMenuItem(null);
 667                         wantsKeys = false;
 668                         InvalidateMenu();
 669                         return true;
 670                     }
 671                 }
 672             }
 673             else if (accessKey != '\0' && keyCode == Keys.none)
 674             {
 675                 MenuItem* menuItem = GetMenuItemByAccessKey(accessKey);
 676                 if (menuItem != null)
 677                 {
 678                     MenuItem* firstMenuItem = menuItem->GetFirstMenuItem();
 679                     if (firstMenuItem != null)
 680                     {
 681                         if (selectedMenuItem != null)
 682                         {
 683                             MenuItem* openedMenuItem = GetOpenedMenuItem();
 684                             if (openedMenuItem != null)
 685                             {
 686                                 openedMenuItem->SetState(MenuItem.State.closedthis);
 687                             }
 688                         }
 689                         SetOpen();
 690                         menuItem->SetState(MenuItem.State.openthis);
 691                         SetSelectedMenuItem(firstMenuItem);
 692                         wantsKeys = true;
 693                         InvalidateMenu();
 694                         return true;
 695                     }
 696                 }
 697             }
 698             else if (accessKey == '\0' && keyCode != Keys.none)
 699             {
 700                 if (keyCode == Keys.menu)
 701                 {
 702                     wantsKeys = true;
 703                     return true;
 704                 }
 705                 else
 706                 {
 707                     if (selectedMenuItem != null)
 708                     {
 709                         MenuItem* parentItem = selectedMenuItem->GetParentMenuItem();
 710                         bool handled = selectedMenuItem->HandleKey(keyCodewantsKeysparentItemthis);
 711                         if (MenuInvalidated())
 712                         {
 713                             InvalidateMenu();
 714                         }
 715                         return handled;
 716                     }
 717                 }
 718             }
 719             if (MenuInvalidated())
 720             {
 721                 InvalidateMenu();
 722             }
 723             wantsKeys = false;
 724             return false;
 725         }
 726         internal void MouseDownInternal(MouseEventArgs& args)
 727         {
 728             OnMouseDown(args);
 729         }
 730         protected override void OnMouseDown(MouseEventArgs& args)
 731         {
 732             base->OnMouseDown(args);
 733             SetLatestMouseDownMenuItem(null);
 734             bool handled = false;
 735             Component* child = children.FirstChild();
 736             while (child != null)
 737             {
 738                 if (child is MenuItem*)
 739                 {
 740                     MenuItem* menuItem = cast<MenuItem*>(child);
 741                     menuItem->DoMouseDown(argshandledthis);
 742                     if (handled)
 743                     {
 744                         InvalidateMenu();
 745                         return;
 746                     }
 747                 }
 748                 child = child->NextSibling();
 749             }
 750             if (IsOpen())
 751             {
 752                 SetClosed();
 753                 SetLatestOpenedMenuItem(null);
 754                 Component* child = children.FirstChild();
 755                 while (child != null)
 756                 {
 757                     if (child is MenuItem*)
 758                     {
 759                         MenuItem* menuItem = cast<MenuItem*>(child);
 760                         menuItem->SetState(MenuItem.State.closedthis);
 761                     }
 762                     child = child->NextSibling();
 763                 }
 764                 InvalidateMenu();
 765             }
 766         }
 767         internal void MouseUpInternal(MouseEventArgs& args)
 768         {
 769             OnMouseUp(args);
 770         }
 771         protected override void OnMouseUp(MouseEventArgs& args)
 772         {
 773             base->OnMouseUp(args);
 774             bool handled = false;
 775             Component* child = children.FirstChild();
 776             while (child != null)
 777             {
 778                 if (child is MenuItem*)
 779                 {
 780                     MenuItem* menuItem = cast<MenuItem*>(child);
 781                     if (menuItem->IsEnabled())
 782                     {
 783                         menuItem->DoMouseUp(argshandledthis);
 784                         if (handled)
 785                         {
 786                             InvalidateMenu();
 787                             return;
 788                         }
 789                     }
 790                 }
 791                 child = child->NextSibling();
 792             }
 793         }
 794         internal override nothrow void SetLatestOpenedMenuItem(MenuItem* menuItem)
 795         {
 796             latestOpenedMenuItem = menuItem;
 797         }
 798         internal override nothrow MenuItem* LatestOpenedMenuItem() const
 799         {
 800             return latestOpenedMenuItem;
 801         }
 802         internal override nothrow MenuItem* GetOpenedMenuItem() const
 803         {
 804             Component* child = children.FirstChild();
 805             while (child != null)
 806             {
 807                 if (child is MenuItem*)
 808                 {
 809                     MenuItem* childItem = cast<MenuItem*>(child);
 810                     if (childItem->GetState() == MenuItem.State.open)
 811                     {
 812                         return childItem;
 813                     }
 814                 }
 815                 child = child->NextSibling();
 816             }
 817             return null;
 818         }
 819         internal override nothrow MenuItem* GetFirstMenuItem() const
 820         {
 821             Component* child = children.FirstChild();
 822             while (child != null)
 823             {
 824                 if (child is MenuItem*)
 825                 {
 826                     MenuItem* menuItem = cast<MenuItem*>(child);
 827                     return menuItem;
 828                 }
 829                 child = child->NextSibling();
 830             }
 831             return null;
 832         }
 833         internal override nothrow MenuItem* GetLastMenuItem() const
 834         {
 835             Component* child = children.LastChild();
 836             while (child != null)
 837             {
 838                 if (child is MenuItem*)
 839                 {
 840                     MenuItem* menuItem = cast<MenuItem*>(child);
 841                     return menuItem;
 842                 }
 843                 child = child->PrevSibling();
 844             }
 845             return null;
 846         }
 847         internal override nothrow MenuItem* GetMenuItemByAccessKey(wchar accessKey)
 848         {
 849             Component* child = children.FirstChild();
 850             while (child != null)
 851             {
 852                 if (child is MenuItem*)
 853                 {
 854                     MenuItem* menuItem = cast<MenuItem*>(child);
 855                     if (menuItem->AccessKey() == accessKey)
 856                     {
 857                         return menuItem;
 858                     }
 859                 }
 860                 child = child->NextSibling();
 861             }
 862             return null;
 863         }
 864         internal override nothrow MenuItem* GetSelectedMenuItem() const
 865         {
 866             return selectedMenuItem;
 867         }
 868         internal override nothrow void SetSelectedMenuItem(MenuItem* selectedMenuItem_)
 869         {
 870             selectedMenuItem = selectedMenuItem_;
 871         }
 872         internal override nothrow MenuItem* GetLatestMouseDownMenuItem() const
 873         {
 874             return latestMouseDownMenuItem;
 875         }
 876         internal override nothrow void SetLatestMouseDownMenuItem(MenuItem* menuItem)
 877         {
 878             latestMouseDownMenuItem = menuItem;
 879         }
 880         public nothrow void DisableMenuKey()
 881         {
 882             flags = cast<Flags>(flags | Flags.menuKeyDisabled);
 883         }
 884         public inline nothrow bool MenuKeyDisabled() const
 885         {
 886             return (flags & Flags.menuKeyDisabled) != Flags.none;
 887         }
 888         private inline nothrow bool MenuChanged()
 889         {
 890             return (flags & Flags.menuChanged) != Flags.none;
 891         }
 892         internal override nothrow void SetMenuChanged()
 893         {
 894             flags = cast<Flags>(flags | Flags.menuChanged);
 895         }
 896         private inline nothrow void ResetMenuChanged()
 897         {
 898             flags = cast<Flags>(flags & ~Flags.menuChanged);
 899         }
 900         private inline nothrow bool MenuInvalidated() const
 901         {
 902             return (flags & Flags.menuInvalidated) != Flags.none;
 903         }
 904         internal override nothrow void SetMenuInvalidated()
 905         {
 906             flags = cast<Flags>(flags | Flags.menuInvalidated);
 907         }
 908         private inline nothrow void ResetMenuInvalidated()
 909         {
 910             flags = cast<Flags>(flags & ~Flags.menuInvalidated);
 911         }
 912         internal override nothrow bool IsOpen() const
 913         {
 914             return (flags & Flags.open) != Flags.none;
 915         }
 916         public override nothrow void SetOpen()
 917         {
 918             flags = cast<Flags>(flags | Flags.open);
 919         }
 920         public override nothrow void SetClosed()
 921         {
 922             if (IsOpen())
 923             {
 924                 flags = cast<Flags>(flags & ~Flags.open);
 925                 InvalidateMenu();
 926             }
 927         }
 928         private nothrow bool MenuBoxAdded() const
 929         {
 930             return (flags & Flags.menuBoxAdded) != Flags.none;
 931         }
 932         private nothrow void SetMenuBoxAdded()
 933         {
 934             flags = cast<Flags>(flags | Flags.menuBoxAdded);
 935         }
 936         private void AddMenuBox()
 937         {
 938             Control* parentControl = ParentControl();
 939             if (parentControl != null && parentControl is ContainerControl*)
 940             {
 941                 menuBox = new MenuBox(GetFont()thisnull);
 942                 ContainerControl* containerControl = cast<ContainerControl*>(parentControl);
 943                 containerControl->InsertChildAfter(menuBoxthis);
 944             }
 945         }
 946         private Flags flags;
 947         private Container children;
 948         private MenuItem* latestOpenedMenuItem;
 949         private MenuItem* selectedMenuItem;
 950         private MenuItem* latestMouseDownMenuItem;
 951         private HashMap<KeysMenuItem*> shortcuts;
 952         private MenuBox* menuBox;
 953     }
 954 
 955     public nothrow ControlCreateParams& MenuBoxControlCreateParams(ControlCreateParams& controlCreateParams)
 956     {
 957         return controlCreateParams.SetWindowStyle(HiddenChildWindowStyle()).
 958             SetWindowClassBackgroundColor(SystemColor.COLOR_MENU).SetBackgroundColor(DefaultMenuBackgroundColor()).
 959             SetWindowClassName("System.Windows.MenuBox");
 960     }
 961 
 962     public class MenuBoxCreateParams
 963     {
 964         public nothrow MenuBoxCreateParams(MenuControlCreateParams& menuControlCreateParams_) : menuControlCreateParams(menuControlCreateParams_)
 965         {
 966         }
 967         public nothrow MenuBoxCreateParams& Defaults()
 968         {
 969             return *this;
 970         }
 971         public MenuControlCreateParams& menuControlCreateParams;
 972     }
 973 
 974     public class MenuBox : MenuControl
 975     {
 976         public MenuBox(const Font& fontMenuBar* menuBar_MenuItem* rootItem_) : 
 977             base(font"System.Windows.MenuBox"DefaultWindowClassStyle()HiddenChildWindowStyle()DefaultExtendedWindowStyle()
 978             Color.White()"menuBox"Point()Size()Dock.noneAnchors.none)menuBar(menuBar_)rootItem(rootItem_)paintThisMenuBox(false)
 979         {
 980         }
 981         public MenuBox(MenuBoxCreateParams& createParamsMenuBar* menuBar_MenuItem* rootItem_) : 
 982             base(createParams.menuControlCreateParams)menuBar(menuBar_)rootItem(rootItem_)paintThisMenuBox(false)
 983         {
 984         }
 985         public nothrow void SetPaintThisMenuBox(bool paintThisMenuBox_)
 986         {
 987             paintThisMenuBox = paintThisMenuBox_;
 988         }
 989         public inline nothrow bool PaintThisMenuBox() const
 990         {
 991             return paintThisMenuBox;
 992         }
 993         public override void PrintWindowTree(int level)
 994         {
 995             LogView* log = Application.GetLogView();
 996             if (log != null)
 997             {
 998                 log->WriteLine(string(' 'level) + "MenuBox." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point()GetSize()).ToString() + "]");
 999             }
1000         }
1001         protected virtual Point GetBoxLocation() const
1002         {
1003             return Location();
1004         }
1005         protected override void OnPaint(PaintEventArgs& args)
1006         {
1007             try
1008             {
1009                 if (Debug.Paint())
1010                 {
1011                     Rect r(Point()GetSize());
1012                     LogView* log = Application.GetLogView();
1013                     if (log != null)
1014                     {
1015                         log->WriteLine("MenuBox.OnPaint: " + r.ToString());
1016                     }
1017                 }
1018                 Point loc = Location();
1019                 if (!paintMenu)
1020                 {
1021                     if (paintThisMenuBox)
1022                     {
1023                         Control* parentControl = ParentControl();
1024                         if (parentControl != null)
1025                         {
1026                             Bitmap menuBoxBitmap(args.clipRect.size.wargs.clipRect.size.hargs.graphics);
1027                             Graphics menuBoxGraphics = Graphics.FromImage(menuBoxBitmap);
1028                             Rect menuBoxClipRect(Point(00)Size(args.clipRect.size.wargs.clipRect.size.h));
1029                             menuBoxGraphics.SetClipChecked(menuBoxClipRect);
1030                             menuBoxGraphics.TranslateTransformChecked(-loc.x-loc.y);
1031                             PaintEventArgs paintMenuBoxArgs(menuBoxGraphicsmenuBoxClipRect);
1032                             bool prevPaintMenu = paintMenu;
1033                             paintMenu = true;
1034                             bool skipMenuBar = this is ContextMenu*;
1035                             parentControl->PaintAll(paintMenuBoxArgsskipMenuBar);
1036                             paintMenu = prevPaintMenu;
1037                             args.graphics.DrawImageChecked(menuBoxBitmapPointF(00));
1038                         }
1039                     }
1040                 }
1041                 else
1042                 {
1043                     if (menuBar != null)
1044                     {
1045                         menuBar->DrawMenuItems(argstrueloc);
1046                     }
1047                     else if (rootItem != null)
1048                     {
1049                         rootItem->Draw(args.graphicsDefaultPadding()TextBrush()DisabledTextBrush()BackgroundBrush()MouseOverBrush()MenuOpenBrush()ShadowBrush()BlackBrush()BlackPen()
1050                             DarkPen()GetFont()Format()MenuOpenColor()thistruePoint());
1051                     }
1052                 }
1053             }
1054             catch (const Exception& ex)
1055             {
1056             }
1057         }
1058         private nothrow Control* ParentControl() const
1059         {
1060             Container* container = GetContainer();
1061             if (container != null)
1062             {
1063                 Component* parent = container->Parent();
1064                 if (parent != null && (parent is Control*))
1065                 {
1066                     return cast<Control*>(parent);
1067                 }
1068             }
1069             return null;
1070         }
1071         protected override void OnMouseEnter()
1072         {
1073             base->OnMouseEnter();
1074             if (menuBar != null)
1075             {
1076                 menuBar->MouseEnterInternal();
1077             }
1078         }
1079         protected override void OnMouseMove(MouseEventArgs& args)
1080         {
1081             base->OnMouseMove(args);
1082             if (menuBar != null)
1083             {
1084                 Point loc = Location();
1085                 args.location.x = args.location.x + loc.x;
1086                 args.location.y = args.location.y + loc.y;
1087                 menuBar->MouseMoveInternal(args);
1088             }
1089             else if (rootItem != null)
1090             {
1091                 bool handled = false;
1092                 rootItem->DispatchMouseMove(argshandledthis);
1093             }
1094         }
1095         protected override void OnMouseLeave()
1096         {
1097             base->OnMouseLeave();
1098             if (menuBar != null)
1099             {
1100                 menuBar->MouseLeaveInternal();
1101             }
1102             else if (rootItem != null)
1103             {
1104                 rootItem->LeaveChildren(this);
1105             }
1106         }
1107         protected override void OnMouseDown(MouseEventArgs& args)
1108         {
1109             base->OnMouseDown(args);
1110             if (menuBar != null)
1111             {
1112                 Point loc = Location();
1113                 args.location.x = args.location.x + loc.x;
1114                 args.location.y = args.location.y + loc.y;
1115                 menuBar->MouseDownInternal(args);
1116             }
1117             else if (rootItem != null)
1118             {
1119                 SetLatestMouseDownMenuItem(null);
1120                 bool handled = false;
1121                 rootItem->DoMouseDown(argshandledthis);
1122                 if (handled)
1123                 {
1124                     Invalidate();
1125                 }
1126             }
1127         }
1128         protected override void OnMouseUp(MouseEventArgs& args)
1129         {
1130             base->OnMouseUp(args);
1131             if (menuBar != null)
1132             {
1133                 Point loc = Location();
1134                 args.location.x = args.location.x + loc.x;
1135                 args.location.y = args.location.y + loc.y;
1136                 menuBar->MouseUpInternal(args);
1137             }
1138             else if (rootItem != null)
1139             {
1140                 bool handled = false;
1141                 rootItem->DoMouseUp(argshandledthis);
1142                 if (handled)
1143                 {
1144                     Invalidate();
1145                 }
1146             }
1147         }
1148         protected inline nothrow MenuItem* GetRootItem() const
1149         {
1150             return rootItem;
1151         }
1152         private MenuBar* menuBar;
1153         private MenuItem* rootItem;
1154         private bool paintThisMenuBox;
1155         private bool paintMenu;
1156     }
1157 
1158     public abstract class ClickAction
1159     {
1160         public nothrow ClickAction()
1161         {
1162             clickEventHandler = Click;
1163         }
1164         public virtual default ~ClickAction();
1165         public nothrow void AddHandlerTo(MenuItem& menuItem)
1166         {
1167             menuItem.ClickEvent().AddHandler(clickEventHandler);
1168         }
1169         private void Click()
1170         {
1171             Execute();
1172         }
1173         protected abstract void Execute();
1174         private ClickEventHandler clickEventHandler;
1175     }
1176 
1177     public class ClickActions
1178     {
1179         public nothrow void Add(ClickAction* action)
1180         {
1181             clickActions.Add(UniquePtr<ClickAction>(action));
1182         }
1183         private List<UniquePtr<ClickAction>> clickActions;
1184     }
1185 
1186     public nothrow ControlCreateParams& ContextMenuControlCreateParams(ControlCreateParams& controlCreateParams)
1187     {
1188         return controlCreateParams.SetWindowStyle(HiddenChildWindowStyle()).
1189             SetWindowClassBackgroundColor(SystemColor.COLOR_MENU).SetBackgroundColor(DefaultMenuBackgroundColor()).
1190             SetWindowClassName("System.Windows.ContextMenu");
1191     }
1192 
1193     public nothrow MenuBoxCreateParams& ContextMenuMenuBoxCreateParams(MenuBoxCreateParams& menuBoxCreateParams)
1194     {
1195         return menuBoxCreateParams;
1196     }
1197 
1198     public class ContextMenuCreateParams
1199     {
1200         public nothrow ContextMenuCreateParams(MenuBoxCreateParams& menuBoxCreateParams_) : menuBoxCreateParams(menuBoxCreateParams_)
1201         {
1202         }
1203         public nothrow ContextMenuCreateParams& Defaults()
1204         {
1205             return *this;
1206         }
1207         public MenuBoxCreateParams& menuBoxCreateParams;
1208     }
1209 
1210     public class ContextMenu : MenuBox
1211     {
1212         public ContextMenu(const Font& font) : 
1213             base(fontnullnew MenuItem("root"))
1214             rootItemPtr(GetRootItem())latestOpenedMenuItem(null)selectedMenuItem(null)latestMouseDownMenuItem(null)
1215         {
1216         }
1217         public ContextMenu() : this(Font(FontFamily("Segoe UI")9.0f))
1218         {
1219         }
1220         public ContextMenu(ContextMenuCreateParams& createParams) : 
1221             base(createParams.menuBoxCreateParamsnullnew MenuItem("root"))
1222             rootItemPtr(GetRootItem())latestOpenedMenuItem(null)selectedMenuItem(null)latestMouseDownMenuItem(null)
1223         {
1224         }
1225         public void AddMenuItem(MenuItemBase* menuItem)
1226         {
1227             rootItemPtr->AddMenuItem(menuItem);
1228         }
1229         public void AddMenuItemAction(MenuItem* menuItemClickAction* action)
1230         {
1231             rootItemPtr->AddMenuItem(menuItem);
1232             action->AddHandlerTo(*menuItem);
1233             clickActions.Add(action);
1234         }
1235         public void CalculateSize()
1236         {
1237             rootItemPtr->SetState(MenuItem.State.openthis);
1238             Graphics graphics = Graphics.FromWindowHandle(Handle());
1239             rootItemPtr->CalculateChildRect(graphicsGetFont()Format()Point(00));
1240             Rect menuRect;
1241             rootItemPtr->GetOpenRect(menuRect);
1242             SetSize(menuRect.size);
1243         }
1244         public nothrow bool HasMenuItems()
1245         {
1246             return !rootItemPtr->Children().IsEmpty();
1247         }
1248         protected override Point GetBoxLocation() const
1249         {
1250             return Point(00);
1251         }
1252         protected override void OnPaint(PaintEventArgs& args)
1253         {
1254             SetPaintThisMenuBox(true);
1255             base->OnPaint(args);
1256         }
1257         protected override void OnVisibleChanged()
1258         {
1259             base->OnVisibleChanged();
1260             if (!IsVisible())
1261             {
1262                 rootItemPtr->SetState(MenuItem.State.closedthis);
1263                 SetPaintThisMenuBox(false);
1264             }
1265         }
1266         internal override nothrow void SetMenuInvalidated()
1267         {
1268             Invalidate();
1269         }
1270         internal override nothrow bool IsOpen() const
1271         {
1272             return rootItemPtr->GetState() == MenuItem.State.open;
1273         }
1274         internal override nothrow MenuItem* GetSelectedMenuItem() const
1275         {
1276             return selectedMenuItem;
1277         }
1278         internal override nothrow void SetSelectedMenuItem(MenuItem* selectedMenuItem_)
1279         {
1280             selectedMenuItem = selectedMenuItem_;
1281         }
1282         internal override nothrow MenuItem* LatestOpenedMenuItem() const
1283         {
1284             return latestOpenedMenuItem;
1285         }
1286         internal override nothrow void SetLatestOpenedMenuItem(MenuItem* menuItem)
1287         {
1288             latestOpenedMenuItem = menuItem;
1289         }
1290         internal override nothrow MenuItem* GetLatestMouseDownMenuItem() const
1291         {
1292             return latestMouseDownMenuItem;
1293         }
1294         internal override nothrow void SetLatestMouseDownMenuItem(MenuItem* menuItem)
1295         {
1296             latestMouseDownMenuItem = menuItem;
1297         }
1298         internal override nothrow MenuItem* GetOpenedMenuItem() const
1299         {
1300             return rootItemPtr.Get();
1301         }
1302         private UniquePtr<MenuItem> rootItemPtr;
1303         private MenuItem* latestOpenedMenuItem;
1304         private MenuItem* selectedMenuItem;
1305         private MenuItem* latestMouseDownMenuItem;
1306         private ClickActions clickActions;
1307     }
1308 
1309     public abstract class MenuItemBase : Component
1310     {
1311         public nothrow MenuItemBase() : location()size()
1312         {
1313         }
1314         public abstract void Draw(Graphics& graphicsconst Padding& parentPaddingconst Brush& textBrushconst Brush& disabledTextBrushconst Brush& backgroundBrushconst Brush& mouseOverBrush
1315             const Brush& menuOpenBrushconst Brush& shadowBrushconst Brush& blackBrushconst Pen& blackPenconst Pen& darkPenconst Font& font
1316             const StringFormat& formatconst Color& menuOpenColorMenuControl* menuControlbool drawSubItemsconst Point& origin);
1317         internal nothrow MenuItem* GetParentMenuItem() const
1318         {
1319             Container* container = GetContainer();
1320             if (container != null)
1321             {
1322                 Component* parent = container->Parent();
1323                 if (parent != null)
1324                 {
1325                     if (parent is MenuItem*)
1326                     {
1327                         MenuItem* parentMenuItem = cast<MenuItem*>(parent);
1328                         return parentMenuItem;
1329                     }
1330                 }
1331             }
1332             return null;
1333         }
1334         public virtual nothrow Padding DefaultPadding() const
1335         {
1336             return Padding(0000);
1337         }
1338         public nothrow int Level() const
1339         {
1340             MenuItem* parent = GetParentMenuItem();
1341             if (parent == null)
1342             {
1343                 return 0;
1344             }
1345             else
1346             {
1347                 return parent->Level() + 1;
1348             }
1349         }
1350         public nothrow const Point& Location() const
1351         {
1352             return location;
1353         }
1354         public nothrow void SetLocation(const Point& location_)
1355         {
1356             location = location_;
1357         }
1358         public nothrow const Size& GetSize() const
1359         {
1360             return size;
1361         }
1362         public nothrow void SetSize(const Size& size_)
1363         {
1364             size = size_;
1365         }
1366         public abstract Size MeasureItem(Graphics& graphicsconst Font& fontconst StringFormat& formatint& maxShortcutWidthint& childIndicatorWidth);
1367         private Point location;
1368         private Size size;
1369     }
1370 
1371     public class MenuItem : MenuItemBase
1372     {
1373         public enum State : sbyte
1374         {
1375             closed = 0open = 1
1376         }
1377         private enum Flags : sbyte
1378         {
1379             none = 0disabled = 1 << 0selected = 1 << 1mouseInClient = 1 << 2lbuttonPressed = 1 << 3
1380         }
1381         public MenuItem(const string& text_) : 
1382             base()text(text_)children(this)state(State.closed)childRect()unionRect()flags(Flags.none)accessKey('\0')shortcut(Keys.none)shortcutFieldWidth(0)
1383         {
1384             SetAccessKey();
1385         }
1386         public void AddMenuItem(MenuItemBase* menuItem)
1387         {
1388             children.AddChild(menuItem);
1389         }
1390         public nothrow MenuItem* GetFirstMenuItem() const
1391         {
1392             Component* child = children.FirstChild();
1393             while (child != null)
1394             {
1395                 if (child is MenuItem*)
1396                 {
1397                     MenuItem* childMenuItem = cast<MenuItem*>(child);
1398                     return childMenuItem;
1399                 }
1400                 child = child->NextSibling();
1401             }
1402             return null;
1403         }
1404         public nothrow MenuItem* GetLastMenuItem() const
1405         {
1406             Component* child = children.LastChild();
1407             while (child != null)
1408             {
1409                 if (child is MenuItem*)
1410                 {
1411                     MenuItem* childMenuItem = cast<MenuItem*>(child);
1412                     return childMenuItem;
1413                 }
1414                 child = child->PrevSibling();
1415             }
1416             return null;
1417         }
1418         public nothrow MenuItem* GetNextMenuItem() const
1419         {
1420             Component* next = NextSibling();
1421             while (next != null)
1422             {
1423                 if (next is MenuItem*)
1424                 {
1425                     MenuItem* nextMenuItem = cast<MenuItem*>(next);
1426                     return nextMenuItem;
1427                 }
1428                 next = next->NextSibling();
1429             }
1430             return null;
1431         }
1432         public nothrow MenuItem* GetPrevMenuItem() const
1433         {
1434             Component* prev = PrevSibling();
1435             while (prev != null)
1436             {
1437                 if (prev is MenuItem*)
1438                 {
1439                     MenuItem* prevMenuItem = cast<MenuItem*>(prev);
1440                     return prevMenuItem;
1441                 }
1442                 prev = prev->PrevSibling();
1443             }
1444             return null;
1445         }
1446         public nothrow MenuItem* GetParentMenuItem() const
1447         {
1448             Container* container = GetContainer();
1449             if (container != null)
1450             {
1451                 Component* parent = container->Parent();
1452                 if (parent != null)
1453                 {
1454                     if (parent is MenuItem*)
1455                     {
1456                         MenuItem* parentItem = cast<MenuItem*>(parent);
1457                         return parentItem;
1458                     }
1459                 }
1460             }
1461             return null;
1462         }
1463         private nothrow MenuControl* GetMenuControl() const
1464         {
1465             Container* container = GetContainer();
1466             if (container != null)
1467             {
1468                 Component* parent = container->Parent();
1469                 if (parent != null)
1470                 {
1471                     if (parent is MenuItem*)
1472                     {
1473                         MenuItem* parentItem = cast<MenuItem*>(parent);
1474                         return parentItem->GetMenuControl();
1475                     }
1476                     else if (parent is MenuControl*)
1477                     {
1478                         MenuControl* menuControl = cast<MenuControl*>(parent);
1479                         return menuControl;
1480                     }
1481                 }
1482             }
1483             return null;
1484         }
1485         internal bool HandleKey(Keys keybool& wantsKeysMenuItem* parentMenuItemMenuControl* menuControl)
1486         {
1487             if (key >= Keys.a && key <= Keys.z || key >= Keys.d0 && key <= Keys.d9)
1488             {
1489                 wchar accessKey = cast<wchar>(cast<int>(key));
1490                 MenuItem* childItem = null;
1491                 if (parentMenuItem != null)
1492                 {
1493                     childItem = parentMenuItem->GetChildItemByAccessKey(accessKey);
1494                 }
1495                 else
1496                 {
1497                     childItem = menuControl->GetMenuItemByAccessKey(accessKey);
1498                 }
1499                 if (childItem != null && childItem->IsEnabled())
1500                 {
1501                     childItem->Execute(parentMenuItemwantsKeysmenuControl);
1502                     return true;
1503                 }
1504                 else
1505                 {
1506                     wantsKeys = true;
1507                     return false;
1508                 }
1509             }
1510             else
1511             {
1512                 switch (key)
1513                 {
1514                     case Keys.enter:
1515                     {
1516                         if (IsEnabled())
1517                         {
1518                             Execute(parentMenuItemwantsKeysmenuControl);
1519                             return true;
1520                         }
1521                         else
1522                         {
1523                             wantsKeys = true;
1524                             return false;
1525                         }
1526                     }
1527                     case Keys.escape:
1528                     {
1529                         MenuItem* openedMenuItem = menuControl->GetOpenedMenuItem();
1530                         if (openedMenuItem != null)
1531                         {
1532                             openedMenuItem->SetState(State.closedmenuControl);
1533                         }
1534                         wantsKeys = false;
1535                         menuControl->SetSelectedMenuItem(null);
1536                         menuControl->SetClosed();
1537                         menuControl->SetMenuInvalidated();
1538                         return true;
1539                     }
1540                     case Keys.home:
1541                     {
1542                         if (Level() == 0)
1543                         {
1544                             MenuItem* firstMenuItem = menuControl->GetFirstMenuItem();
1545                             if (firstMenuItem != null)
1546                             {
1547                                 menuControl->SetSelectedMenuItem(firstMenuItem);
1548                                 wantsKeys = true;
1549                                 menuControl->SetMenuInvalidated();
1550                                 return true;
1551                             }
1552                         }
1553                         else
1554                         {
1555                             MenuItem* parentMenuItem = GetParentMenuItem();
1556                             if (parentMenuItem != null)
1557                             {
1558                                 MenuItem* firstMenuItem = parentMenuItem->GetFirstMenuItem();
1559                                 if (firstMenuItem != null)
1560                                 {
1561                                     menuControl->SetSelectedMenuItem(firstMenuItem);
1562                                     wantsKeys = true;
1563                                     menuControl->SetMenuInvalidated();
1564                                     return true;
1565                                 }
1566                             }
1567                         }
1568                         break;
1569                     }
1570                     case Keys.end:
1571                     {
1572                         if (Level() == 0)
1573                         {
1574                             MenuItem* lastMenuItem = menuControl->GetLastMenuItem();
1575                             if (lastMenuItem != null)
1576                             {
1577                                 menuControl->SetSelectedMenuItem(lastMenuItem);
1578                                 wantsKeys = true;
1579                                 menuControl->SetMenuInvalidated();
1580                                 return true;
1581                             }
1582                         }
1583                         else
1584                         {
1585                             MenuItem* parentMenuItem = GetParentMenuItem();
1586                             if (parentMenuItem != null)
1587                             {
1588                                 MenuItem* lastMenuItem = parentMenuItem->GetLastMenuItem();
1589                                 if (lastMenuItem != null)
1590                                 {
1591                                     menuControl->SetSelectedMenuItem(lastMenuItem);
1592                                     wantsKeys = true;
1593                                     menuControl->SetMenuInvalidated();
1594                                     return true;
1595                                 }
1596                             }
1597                         }
1598                         break;
1599                     }
1600                     case Keys.down:
1601                     {
1602                         if (Level() == 0)
1603                         {
1604                             SetState(state.openmenuControl);
1605                             MenuItem* firstChild = GetFirstMenuItem();
1606                             if (firstChild != null)
1607                             {
1608                                 menuControl->SetSelectedMenuItem(firstChild);
1609                                 wantsKeys = true;
1610                                 menuControl->SetMenuInvalidated();
1611                                 return true;
1612                             }
1613                         }
1614                         else
1615                         {
1616                             MenuItem* nextMenuItem = GetNextMenuItem();
1617                             if (nextMenuItem != null)
1618                             {
1619                                 menuControl->SetSelectedMenuItem(nextMenuItem);
1620                                 wantsKeys = true;
1621                                 menuControl->SetMenuInvalidated();
1622                                 return true;
1623                             }
1624                             else
1625                             {
1626                                 if (parentMenuItem != null)
1627                                 {
1628                                     MenuItem* firstMenuItem = parentMenuItem->GetFirstMenuItem();
1629                                     if (firstMenuItem != null)
1630                                     {
1631                                         menuControl->SetSelectedMenuItem(firstMenuItem);
1632                                         wantsKeys = true;
1633                                         menuControl->SetMenuInvalidated();
1634                                         return true;
1635                                     }
1636                                 }
1637                             }
1638                         }
1639                         break;
1640                     }
1641                     case Keys.up:
1642                     {
1643                         if (Level() == 0)
1644                         {
1645                             SetState(state.openmenuControl);
1646                             MenuItem* lastChild = GetLastMenuItem();
1647                             if (lastChild != null)
1648                             {
1649                                 menuControl->SetSelectedMenuItem(lastChild);
1650                                 wantsKeys = true;
1651                                 menuControl->SetMenuInvalidated();
1652                                 return true;
1653                             }
1654                         }
1655                         else
1656                         {
1657                             MenuItem* prevMenuItem = GetPrevMenuItem();
1658                             if (prevMenuItem != null)
1659                             {
1660                                 menuControl->SetSelectedMenuItem(prevMenuItem);
1661                                 wantsKeys = true;
1662                                 menuControl->SetMenuInvalidated();
1663                                 return true;
1664                             }
1665                             else
1666                             {
1667                                 if (parentMenuItem != null)
1668                                 {
1669                                     MenuItem* lastMenuItem = parentMenuItem->GetLastMenuItem();
1670                                     if (lastMenuItem != null)
1671                                     {
1672                                         menuControl->SetSelectedMenuItem(lastMenuItem);
1673                                         wantsKeys = true;
1674                                         menuControl->SetMenuInvalidated();
1675                                         return true;
1676                                     }
1677                                 }
1678                             }
1679                         }
1680                         break;
1681                     }
1682                     case Keys.right:
1683                     {
1684                         if (Level() == 0)
1685                         {
1686                             MenuItem* nextMenuItem = GetNextMenuItem();
1687                             if (nextMenuItem != null)
1688                             {
1689                                 menuControl->SetSelectedMenuItem(nextMenuItem);
1690                                 wantsKeys = true;
1691                                 menuControl->SetMenuInvalidated();
1692                                 return true;
1693                             }
1694                             else
1695                             {
1696                                 MenuItem* firstMenuItem = menuControl->GetFirstMenuItem();
1697                                 if (firstMenuItem != null)
1698                                 {
1699                                     menuControl->SetSelectedMenuItem(firstMenuItem);
1700                                     wantsKeys = true;
1701                                     menuControl->SetMenuInvalidated();
1702                                     return true;
1703                                 }
1704                             }
1705                         }
1706                         else
1707                         {
1708                             MenuItem* firstChild = GetFirstMenuItem();
1709                             if (firstChild != null)
1710                             {
1711                                 SetState(State.openmenuControl);
1712                                 menuControl->SetSelectedMenuItem(firstChild);
1713                                 wantsKeys = true;
1714                                 menuControl->SetMenuInvalidated();
1715                                 return true;
1716                             }
1717                             else
1718                             {
1719                                 while (parentMenuItem != null)
1720                                 {
1721                                     if (parentMenuItem->Level() == 0)
1722                                     {
1723                                         MenuItem* nextMenuItem = parentMenuItem->GetNextMenuItem();
1724                                         if (nextMenuItem != null)
1725                                         {
1726                                             parentMenuItem->SetState(State.closedmenuControl);
1727                                             nextMenuItem->SetState(State.openmenuControl);
1728                                             MenuItem* firstChild = nextMenuItem->GetFirstMenuItem();
1729                                             if (firstChild != null)
1730                                             {
1731                                                 menuControl->SetSelectedMenuItem(firstChild);
1732                                                 wantsKeys = true;
1733                                                 menuControl->SetMenuInvalidated();
1734                                                 return true;
1735                                             }
1736                                         }
1737                                         else
1738                                         {
1739                                             MenuItem* firstMenuItem = menuControl->GetFirstMenuItem();
1740                                             if (firstMenuItem != null)
1741                                             {
1742                                                 parentMenuItem->SetState(State.closedmenuControl);
1743                                                 firstMenuItem->SetState(State.openmenuControl);
1744                                                 MenuItem* firstChild = firstMenuItem->GetFirstMenuItem();
1745                                                 if (firstChild != null)
1746                                                 {
1747                                                     menuControl->SetSelectedMenuItem(firstChild);
1748                                                     wantsKeys = true;
1749                                                     menuControl->SetMenuInvalidated();
1750                                                     return true;
1751                                                 }
1752                                             }
1753                                         }
1754                                     }
1755                                     else
1756                                     {
1757                                         MenuItem* grandParentMenuItem = parentMenuItem->GetParentMenuItem();
1758                                         MenuItem* nextMenuItem = grandParentMenuItem->GetNextMenuItem();
1759                                         if (nextMenuItem != null)
1760                                         {
1761                                             parentMenuItem->SetState(State.closedmenuControl);
1762                                             grandParentMenuItem->SetState(State.closedmenuControl);
1763                                             nextMenuItem->SetState(State.openmenuControl);
1764                                             MenuItem* firstChild = nextMenuItem->GetFirstMenuItem();
1765                                             if (firstChild != null)
1766                                             {
1767                                                 menuControl->SetSelectedMenuItem(firstChild);
1768                                                 wantsKeys = true;
1769                                                 menuControl->SetMenuInvalidated();
1770                                                 return true;
1771                                             }
1772                                         }
1773                                         else
1774                                         {
1775                                             parentMenuItem = grandParentMenuItem;
1776                                         }
1777                                     }
1778                                 }
1779                             }
1780                         }
1781                         break;
1782                     }
1783                     case Keys.left:
1784                     {
1785                         if (Level() == 0)
1786                         {
1787                             MenuItem* prevMenuItem = GetPrevMenuItem();
1788                             if (prevMenuItem != null)
1789                             {
1790                                 menuControl->SetSelectedMenuItem(prevMenuItem);
1791                                 wantsKeys = true;
1792                                 menuControl->SetMenuInvalidated();
1793                                 return true;
1794                             }
1795                             else
1796                             {
1797                                 MenuItem* lastMenuItem = menuControl->GetLastMenuItem();
1798                                 if (lastMenuItem != null)
1799                                 {
1800                                     menuControl->SetSelectedMenuItem(lastMenuItem);
1801                                     wantsKeys = true;
1802                                     menuControl->SetMenuInvalidated();
1803                                     return true;
1804                                 }
1805                             }
1806                         }
1807                         else
1808                         {
1809                             if (parentMenuItem != null)
1810                             {
1811                                 MenuItem* prevMenuItem = parentMenuItem->GetPrevMenuItem();
1812                                 if (prevMenuItem != null)
1813                                 {
1814                                     parentMenuItem->SetState(State.closedmenuControl);
1815                                     prevMenuItem->SetState(State.openmenuControl);
1816                                     MenuItem* firstChild = prevMenuItem->GetFirstMenuItem();
1817                                     if (firstChild != null)
1818                                     {
1819                                         menuControl->SetSelectedMenuItem(firstChild);
1820                                         wantsKeys = true;
1821                                         menuControl->SetMenuInvalidated();
1822                                         return true;
1823                                     }
1824                                 }
1825                                 else
1826                                 {
1827                                     MenuItem* grandParentMenuItem = parentMenuItem->GetParentMenuItem();
1828                                     if (grandParentMenuItem != null)
1829                                     {
1830                                         grandParentMenuItem->SetState(State.openmenuControl);
1831                                         MenuItem* firstMenuItem = grandParentMenuItem->GetFirstMenuItem();
1832                                         if (firstMenuItem != null)
1833                                         {
1834                                             firstMenuItem->SetState(State.closedmenuControl);
1835                                             menuControl->SetSelectedMenuItem(firstMenuItem);
1836                                         }
1837                                     }
1838                                     else
1839                                     {
1840                                         MenuItem* lastMenuItem = menuControl->GetLastMenuItem();
1841                                         if (lastMenuItem != null)
1842                                         {
1843                                             parentMenuItem->SetState(State.closedmenuControl);
1844                                             lastMenuItem->SetState(State.openmenuControl);
1845                                             MenuItem* firstChild = lastMenuItem->GetFirstMenuItem();
1846                                             if (firstChild != null)
1847                                             {
1848                                                 menuControl->SetSelectedMenuItem(firstChild);
1849                                                 wantsKeys = true;
1850                                                 menuControl->SetMenuInvalidated();
1851                                                 return true;
1852                                             }
1853                                         }
1854                                     }
1855                                 }
1856                             }
1857                         }
1858                         break;
1859                     }
1860                 }
1861             }
1862             wantsKeys = true;
1863             return false;
1864         }
1865         private void Close(MenuControl* menuControl)
1866         {
1867             SetState(State.closedmenuControl);
1868             MenuItem* parentItem = GetParentMenuItem();
1869             while (parentItem != null)
1870             {
1871                 parentItem->SetState(State.closedmenuControl);
1872                 parentItem = parentItem->GetParentMenuItem();
1873             }
1874             menuControl->SetSelectedMenuItem(null);
1875             menuControl->SetClosed();
1876             menuControl->SetMenuInvalidated();
1877         }
1878         private void Execute(MenuItem* parentMenuItembool& wantsKeysMenuControl* menuControl)
1879         {
1880             if (children.IsEmpty())
1881             {
1882                 if (IsEnabled())
1883                 {
1884                     Close(menuControl);
1885                     wantsKeys = false;
1886                     DoClick();
1887                 }
1888             }
1889             else
1890             {
1891                 if (IsEnabled())
1892                 {
1893                     SetState(State.openmenuControl);
1894                     MenuItem* firstMenuItem = GetFirstMenuItem();
1895                     if (firstMenuItem != null)
1896                     {
1897                         menuControl->SetSelectedMenuItem(firstMenuItem);
1898                         wantsKeys = true;
1899                         menuControl->SetMenuInvalidated();
1900                     }
1901                 }
1902             }
1903         }
1904         internal void DoMouseDown(MouseEventArgs& argsbool& handledMenuControl* menuControl)
1905         {
1906             if (Level() == 0)
1907             {
1908                 if (Contains(args.location))
1909                 {
1910                     SetMouseInClient();
1911                     if (menuControl->IsOpen())
1912                     {
1913                         menuControl->SetClosed();
1914                         menuControl->SetLatestOpenedMenuItem(null);
1915                         SetState(State.closedmenuControl);
1916                         DoMouseDown(argsmenuControl);
1917                         handled = true;
1918                     }
1919                     else
1920                     {
1921                         menuControl->SetOpen();
1922                         SetState(State.openmenuControl);
1923                         menuControl->SetLatestOpenedMenuItem(this);
1924                         DoMouseDown(argsmenuControl);
1925                         handled = true;
1926                     }
1927                 }
1928                 else
1929                 {
1930                     Component* child = children.FirstChild();
1931                     while (child != null)
1932                     {
1933                         if (child is MenuItem*)
1934                         {
1935                             MenuItem* childItem = cast<MenuItem*>(child);
1936                             childItem->DoMouseDown(argshandledmenuControl);
1937                             if (handled) return;
1938                         }
1939                         child = child->NextSibling();
1940                     }
1941                 }
1942             }
1943             else
1944             {
1945                 if (menuControl->IsOpen())
1946                 {
1947                     MenuItem* parentMenuItem = GetParentMenuItem();
1948                     if (parentMenuItem != null)
1949                     {
1950                         if (parentMenuItem->state == State.open)
1951                         {
1952                             if (Contains(args.location))
1953                             {
1954                                 if (!children.IsEmpty())
1955                                 {
1956                                     if (state == State.closed)
1957                                     {
1958                                         SetState(State.openmenuControl);
1959                                         menuControl->SetLatestOpenedMenuItem(this);
1960                                         DoMouseDown(argsmenuControl);
1961                                         handled = true;
1962                                     }
1963                                     else if (state == State.open)
1964                                     {
1965                                         SetState(State.closedmenuControl);
1966                                         menuControl->SetLatestOpenedMenuItem(null);
1967                                         DoMouseDown(argsmenuControl);
1968                                         handled = true;
1969                                     }
1970                                 }
1971                                 else
1972                                 {
1973                                     DoMouseDown(argsmenuControl);
1974                                     if ((args.buttons & MouseButtons.lbutton) != 0)
1975                                     {
1976                                         SetLButtonPressed();
1977                                     }
1978                                     handled = true;
1979                                 }
1980                             }
1981                         }
1982                     }
1983                     Component* child = children.FirstChild();
1984                     while (child != null)
1985                     {
1986                         if (child is MenuItem*)
1987                         {
1988                             MenuItem* childItem = cast<MenuItem*>(child);
1989                             childItem->DoMouseDown(argshandledmenuControl);
1990                             if (handled) return;
1991                         }
1992                         child = child->NextSibling();
1993                     }
1994                 }
1995             }
1996         }
1997         internal void DoMouseUp(MouseEventArgs& argsbool& handledMenuControl* menuControl)
1998         {
1999             if (Level() == 0)
2000             {
2001                 if (Contains(args.location))
2002                 {
2003                     DoMouseUp(argsmenuControl);
2004                     handled = true;
2005                 }
2006                 else
2007                 {
2008                     Component* child = children.FirstChild();
2009                     while (child != null)
2010                     {
2011                         if (child is MenuItem*)
2012                         {
2013                             MenuItem* childItem = cast<MenuItem*>(child);
2014                             if (childItem->IsEnabled())
2015                             {
2016                                 childItem->DoMouseUp(argshandledmenuControl);
2017                                 if (handled) return;
2018                             }
2019                         }
2020                         child = child->NextSibling();
2021                     }
2022                 }
2023             }
2024             else
2025             {
2026                 if (menuControl->IsOpen())
2027                 {
2028                     MenuItem* parentMenuItem = GetParentMenuItem();
2029                     if (parentMenuItem != null)
2030                     {
2031                         if (parentMenuItem->state == State.open)
2032                         {
2033                             if (Contains(args.location))
2034                             {
2035                                 DoMouseUp(argsmenuControl);
2036                                 handled = true;
2037                                 return;
2038                             }
2039                         }
2040                     }
2041                     Component* child = children.FirstChild();
2042                     while (child != null)
2043                     {
2044                         if (child is MenuItem*)
2045                         {
2046                             MenuItem* childItem = cast<MenuItem*>(child);
2047                             if (childItem->IsEnabled())
2048                             {
2049                                 childItem->DoMouseUp(argshandledmenuControl);
2050                                 if (handled) return;
2051                             }
2052                         }
2053                         child = child->NextSibling();
2054                     }
2055                 }
2056             }
2057         }
2058         private void DoMouseDown(MouseEventArgs& argsMenuControl* menuControl)
2059         {
2060             menuControl->SetLatestMouseDownMenuItem(this);
2061             ResetLButtonPressed();
2062             OnMouseDown(args);
2063         }
2064         protected virtual void OnMouseDown(MouseEventArgs& args)
2065         {
2066             mouseDownEvent.Fire(args);
2067         }
2068         private void DoMouseUp(MouseEventArgs& argsMenuControl* menuControl)
2069         {
2070             if (!IsEnabled()) return;
2071             OnMouseUp(args);
2072             bool isMenuBar = menuControl is MenuBar*;
2073             MenuItem* latestMouseDownMenuItem = menuControl->GetLatestMouseDownMenuItem();
2074             if ((args.buttons & MouseButtons.lbutton) != 0)
2075             {
2076                 if (LButtonPressed())
2077                 {
2078                     ResetLButtonPressed();
2079                     if (latestMouseDownMenuItem == this && children.IsEmpty())
2080                     {
2081                         ResetSelected(menuControl);
2082                         ResetMouseInClient();
2083                         this->DoMouseLeave(menuControl);
2084                         LeaveChildren(menuControl);
2085                         Close(menuControl);
2086                         DoClick();
2087                     }
2088                     if (isMenuBar)
2089                     {
2090                         MenuItem* openedMenuItem = menuControl->GetOpenedMenuItem();
2091                         if (openedMenuItem != null)
2092                         {
2093                             openedMenuItem->SetState(State.closedmenuControl);
2094                         }
2095                         menuControl->SetClosed();
2096                         menuControl->SetMenuInvalidated();
2097                     }
2098                 }
2099             }
2100         }
2101         protected virtual void OnMouseUp(MouseEventArgs& args)
2102         {
2103             mouseUpEvent.Fire(args);
2104         }
2105         internal void DoMouseEnter(bool parentIsOpenMenuControl* menuControl)
2106         {
2107             if (parentIsOpen)
2108             {
2109                 Component* prev = PrevSibling();
2110                 while (prev != null)
2111                 {
2112                     if (prev is MenuItem*)
2113                     {
2114                         MenuItem* prevItem = cast<MenuItem*>(prev);
2115                         prevItem->DoMouseLeave(menuControl);
2116                     }
2117                     prev = prev->PrevSibling();
2118                 }
2119                 Component* next = NextSibling();
2120                 while (next != null)
2121                 {
2122                     if (next is MenuItem*)
2123                     {
2124                         MenuItem* nextItem = cast<MenuItem*>(next);
2125                         nextItem->DoMouseLeave(menuControl);
2126                     }
2127                     next = next->NextSibling();
2128                 }
2129                 Component* child = children.FirstChild();
2130                 while (child != null)
2131                 {
2132                     if (child is MenuItem*)
2133                     {
2134                         MenuItem* childMenuItem = cast<MenuItem*>(child);
2135                         childMenuItem->ResetSelected(menuControl);
2136                         if (childMenuItem->MouseInClient())
2137                         {
2138                             childMenuItem->ResetMouseInClient();
2139                             childMenuItem->DoMouseLeave(menuControl);
2140                         }
2141                     }
2142                     child = child->NextSibling();
2143                 }
2144             }
2145             if (parentIsOpen)
2146             {
2147                 SetState(State.openmenuControl);
2148                 menuControl->SetLatestOpenedMenuItem(this);
2149             }
2150             OnMouseEnter();
2151             menuControl->SetMenuInvalidated();
2152         }
2153         internal void DoMouseMove(MouseEventArgs& args)
2154         {
2155             OnMouseMove(args);
2156         }
2157         protected virtual void OnMouseEnter()
2158         {
2159             mouseEnterEvent.Fire();
2160         }
2161         internal void LeaveChildren(MenuControl* menuControl)
2162         {
2163             Component* child = children.FirstChild();
2164             while (child != null)
2165             {
2166                 if (child is MenuItem*)
2167                 {
2168                     MenuItem* childMenuItem = cast<MenuItem*>(child);
2169                     childMenuItem->ResetSelected(menuControl);
2170                     childMenuItem->ResetMouseInClient();
2171                     childMenuItem->DoMouseLeave(menuControl);
2172                     childMenuItem->LeaveChildren(menuControl);
2173                 }
2174                 child = child->NextSibling();
2175             }
2176         }
2177         internal void DoMouseLeave(MenuControl* menuControl)
2178         {
2179             ResetLButtonPressed();
2180             if (state == State.open)
2181             {
2182                 SetState(State.closedmenuControl);
2183                 LeaveChildren(menuControl);
2184                 OnMouseLeave();
2185             }
2186             else if (Level() == 0)
2187             {
2188                 OnMouseLeave();
2189             }
2190         }
2191         protected virtual void OnMouseLeave()
2192         {
2193             mouseLeaveEvent.Fire();
2194         }
2195         internal void DispatchMouseMove(MouseEventArgs& argsbool& handledMenuControl* menuControl)
2196         {
2197             if (unionRect.Contains(args.location))
2198             {
2199                 if (Contains(args.location))
2200                 {
2201                     SetSelected(menuControl);
2202                 }
2203                 else
2204                 {
2205                     ResetSelected(menuControl);
2206                     ResetMouseInClient();
2207                 }
2208                 Component* child = children.FirstChild();
2209                 while (child != null)
2210                 {
2211                     if (child is MenuItem*)
2212                     {
2213                         MenuItem* childMenuItem = cast<MenuItem*>(child);
2214                         if (childMenuItem->Contains(args.location))
2215                         {
2216                             childMenuItem->SetSelected(menuControl);
2217                             if (!childMenuItem->MouseInClient())
2218                             {
2219                                 childMenuItem->SetMouseInClient();
2220                                 childMenuItem->DoMouseEnter(truemenuControl);
2221                                 handled = true;
2222                             }
2223                             else
2224                             {
2225                                 childMenuItem->DoMouseMove(args);
2226                             }
2227                         }
2228                         else
2229                         {
2230                             childMenuItem->ResetSelected(menuControl);
2231                             if (childMenuItem->MouseInClient())
2232                             {
2233                                 childMenuItem->ResetMouseInClient();
2234                                 if (!childMenuItem->IsSameOrParentOf(menuControl->LatestOpenedMenuItem()))
2235                                 {
2236                                     childMenuItem->DoMouseLeave(menuControl);
2237                                 }
2238                             }
2239                         }
2240                     }
2241                     child = child->NextSibling();
2242                 }
2243             }
2244             else
2245             {
2246                 Component* child = children.FirstChild();
2247                 while (child != null)
2248                 {
2249                     if (child is MenuItem*)
2250                     {
2251                         MenuItem* childMenuItem = cast<MenuItem*>(child);
2252                         if (childMenuItem->IsSameOrParentOf(menuControl->LatestOpenedMenuItem()))
2253                         {
2254                             childMenuItem->DispatchMouseMove(argshandledmenuControl);
2255                             if (handled) return;
2256                         }
2257                     }
2258                     child = child->NextSibling();
2259                 }
2260             }
2261         }
2262         protected virtual void OnMouseMove(MouseEventArgs& args)
2263         {
2264             mouseMoveEvent.Fire(args);
2265         }
2266         internal void DoClick()
2267         {
2268             LogView* logView = Application.GetLogView();
2269             if (logView != null)
2270             {
2271                 logView->WriteLine("MENUITEM: " + text + " CLICK!");
2272             }
2273             OnClick();
2274         }
2275         protected virtual void OnClick()
2276         {
2277             clickEvent.Fire();
2278         }
2279         public void CalculateChildRect(Graphics& graphicsconst Font& fontconst StringFormat& formatconst Point& location)
2280         {
2281             childRect = Rect();
2282             childRect.location = location;
2283             Component* child = children.FirstChild();
2284             shortcutFieldWidth = 0;
2285             childIndicatorFieldWidth = 0;
2286             while (child != null)
2287             {
2288                 if (child is MenuItemBase*)
2289                 {
2290                     MenuItemBase* item = cast<MenuItemBase*>(child);
2291                     Size size = item->MeasureItem(graphicsfontformatshortcutFieldWidthchildIndicatorFieldWidth);
2292                     childRect.size.w = Max(childRect.size.wsize.w);
2293                     childRect.size.h = childRect.size.h + size.h;
2294                 }
2295                 child = child->NextSibling();
2296             }
2297             childRect.size.w = childRect.size.w + shortcutFieldWidth + childIndicatorFieldWidth;
2298             Rect itemRect(childRect.locationSize(childRect.size.w0));
2299             child = children.FirstChild();
2300             while (child != null)
2301             {
2302                 if (child is MenuItemBase*)
2303                 {
2304                     MenuItemBase* item = cast<MenuItemBase*>(child);
2305                     item->SetLocation(itemRect.location);
2306                     itemRect.size.h = item->GetSize().h;
2307                     item->SetSize(itemRect.size);
2308                     itemRect.location.y = itemRect.location.y + itemRect.size.h;
2309                 }
2310                 child = child->NextSibling();
2311             }
2312             int shadowWidth = ShadowWidth();
2313             childRect.size.h = childRect.size.h + shadowWidth;
2314             childRect.size.w = childRect.size.w + shadowWidth;
2315             child = children.FirstChild();
2316             while (child != null)
2317             {
2318                 if (child is MenuItem*)
2319                 {
2320                     MenuItem* item = cast<MenuItem*>(child);
2321                     if (!item->Children().IsEmpty())
2322                     {
2323                         Point itemLocation = item->Location();
2324                         Size itemSize = item->GetSize();
2325                         item->CalculateChildRect(graphicsfontformatPoint(itemLocation.x + itemSize.w - shadowWidthitemLocation.y));
2326                     }
2327                 }
2328                 child = child->NextSibling();
2329             }
2330             Rect r(Location()GetSize());
2331             unionRect = Rect.Union(rchildRect);
2332         }
2333         public override void Draw(Graphics& graphicsconst Padding& parentPaddingconst Brush& textBrushconst Brush& disabledTextBrushconst Brush& backgroundBrushconst Brush& mouseOverBrush
2334             const Brush& menuOpenBrushconst Brush& shadowBrushconst Brush& blackBrushconst Pen& blackPenconst Pen& darkPenconst Font& fontconst StringFormat& format
2335             const Color& menuOpenColorMenuControl* menuControlbool drawSubItemsconst Point& origin)
2336         {
2337             switch (state)
2338             {
2339                 case State.closed:
2340                 {
2341                     DrawClosed(graphicsparentPaddingtextBrushdisabledTextBrushmouseOverBrushbackgroundBrushmenuOpenBrushblackBrushblackPenfontformatmenuOpenColormenuControl
2342                         drawSubItemsorigin);
2343                     break;
2344                 }
2345                 case State.open:
2346                 {
2347                     DrawOpen(graphicsparentPaddingtextBrushdisabledTextBrushbackgroundBrushmouseOverBrushmenuOpenBrushshadowBrushblackBrushblackPendarkPenfontformat
2348                         menuOpenColormenuControldrawSubItemsorigin);
2349                     break;
2350                 }
2351             }
2352         }
2353         public nothrow const string& Text() const
2354         {
2355             return text;
2356         }
2357         public nothrow void SetText(const string& text_MenuControl* menuControl)
2358         {
2359             text = text_;
2360             SetAccessKey();
2361             menuControl->InvalidateMenu();
2362         }
2363         public inline nothrow wchar AccessKey() const
2364         {
2365             return accessKey;
2366         }
2367         private nothrow void SetAccessKey()
2368         {
2369             wstring s = ToUtf16(text);
2370             long ampPos = s.Find('&');
2371             if (ampPos != -1 && ampPos < s.Length() - 1)
2372             {
2373                 accessKey = cast<wchar>(ToUpper(cast<uchar>(s[ampPos + 1])));
2374             }
2375             else
2376             {
2377                 accessKey = '\0';
2378             }
2379         }
2380         public nothrow void SetShortcut(Keys shortcut_)
2381         {
2382             shortcut = shortcut_;
2383             MenuControl* menuControl = GetMenuControl();
2384             if (menuControl != null)
2385             {
2386                 menuControl->SetMenuChanged();
2387             }
2388         }
2389         private nothrow MenuItem* GetChildItemByAccessKey(wchar accessKey)
2390         {
2391             Component* child = children.FirstChild();
2392             while (child != null)
2393             {
2394                 if (child is MenuItem*)
2395                 {
2396                     MenuItem* menuItem = cast<MenuItem*>(child);
2397                     if (menuItem->AccessKey() == accessKey)
2398                     {
2399                         return menuItem;
2400                     }
2401                 }
2402                 child = child->NextSibling();
2403             }
2404             return null;
2405         }
2406         internal nothrow void CollectShortcuts(HashMap<KeysMenuItem*>& shortcuts)
2407         {
2408             if (shortcut != Keys.none)
2409             {
2410                 shortcuts[shortcut] = this;
2411             }
2412             Component* child = children.FirstChild();
2413             while (child != null)
2414             {
2415                 if (child is MenuItem*)
2416                 {
2417                     MenuItem* menuItem = cast<MenuItem*>(child);
2418                     menuItem->CollectShortcuts(shortcuts);
2419                 }
2420                 child = child->NextSibling();
2421             }
2422         }
2423         public nothrow const Container& Children() const
2424         {
2425             return children;
2426         }
2427         public override nothrow Padding DefaultPadding() const
2428         {
2429             if (Level() == 0)
2430             {
2431                 return Padding(4040);
2432             }
2433             else
2434             {
2435                 return Padding(324324);
2436             }
2437         }
2438         public nothrow Padding ShortcutPadding() const
2439         {
2440             if (Level() == 0)
2441             {
2442                 return Padding(0000);
2443             }
2444             else
2445             {
2446                 return Padding(4040);
2447             }
2448         }
2449         public virtual nothrow int ShadowWidth() const
2450         {
2451             return 3;
2452         }
2453         public virtual nothrow int ChildIndicatorIndent() const
2454         {
2455             return 9;
2456         }
2457         public virtual nothrow int ChildIndicatorWidth() const
2458         {
2459             return 6;
2460         }
2461         public nothrow bool Contains(const Point& p)
2462         {
2463             Rect r(Location()GetSize());
2464             if (r.Contains(p))
2465             {
2466                 return true;
2467             }
2468             return false;
2469         }
2470         public nothrow bool UnionRectContains(const Point& p)
2471         {
2472             return unionRect.Contains(p);
2473         }
2474         public inline nothrow const Rect& UnionRect() const
2475         {
2476             return unionRect;
2477         }
2478         public nothrow void GetOpenRect(Rect& parentRect)
2479         {
2480             if (!childRect.IsEmpty())
2481             {
2482                 if (parentRect.IsEmpty())
2483                 {
2484                     parentRect = childRect;
2485                 }
2486                 else
2487                 {
2488                     parentRect = Rect.Union(parentRectchildRect);
2489                 }
2490             }
2491             Component* child = children.FirstChild();
2492             while (child != null)
2493             {
2494                 if (child is MenuItem*)
2495                 {
2496                     MenuItem* menuItem = cast<MenuItem*>(child);
2497                     if (menuItem->GetState() == MenuItem.State.open)
2498                     {
2499                         menuItem->GetOpenRect(parentRect);
2500                     }
2501                 }
2502                 child = child->NextSibling();
2503             }
2504         }
2505         public inline nothrow State GetState() const
2506         {
2507             return state;
2508         }
2509         internal void SetState(State state_MenuControl* menuControl)
2510         {
2511             if (state != state_)
2512             {
2513                 state = state_;
2514                 menuControl->SetMenuInvalidated();
2515             }
2516         }
2517         public override Size MeasureItem(Graphics& graphicsconst Font& fontconst StringFormat& formatint& shortcutFieldWidthint& childIndicatorFieldWidth)
2518         {
2519             Padding padding = DefaultPadding();
2520             RectF rect = graphics.MeasureStringChecked(textfontPointF(00)format);
2521             int w = cast<int>(rect.size.w);
2522             w = w + padding.Horizontal();
2523             if (shortcut != Keys.none)
2524             {
2525                 string shortcutText = ToString(shortcut);
2526                 RectF shortcutRect = graphics.MeasureStringChecked(shortcutTextfontPointF(00)format);
2527                 Padding shortcutPadding = ShortcutPadding();
2528                 int shortcutWidth = cast<int>(shortcutRect.size.w + shortcutPadding.Horizontal());
2529                 shortcutFieldWidth = Max(shortcutFieldWidthshortcutWidth);
2530             }
2531             if (Level() > 0 && !children.IsEmpty())
2532             {
2533                 childIndicatorFieldWidth = Max(childIndicatorFieldWidthChildIndicatorIndent());
2534             }
2535             int h = cast<int>(rect.size.h);
2536             h = h + padding.Vertical();
2537             Size size(wh);
2538             SetSize(size);
2539             return size;
2540         }
2541         private void DrawClosed(Graphics& graphicsconst Padding& parentPaddingconst Brush& textBrushconst Brush& disabledTextBrushconst Brush& mouseOverBrushconst Brush& backgroundBrush
2542             const Brush& menuOpenBrushconst Brush& blackBrushconst Pen& blackPenconst Font& fontconst StringFormat& formatconst Color& menuOpenColor
2543             MenuControl* menuControlbool drawSubItemsconst Point& origin)
2544         {
2545             Point loc = Location();
2546             loc.x = loc.x - origin.x;
2547             loc.y = loc.y - origin.y;
2548             Size size = GetSize();
2549             Rect r(locsize);
2550             r.size.w = r.size.w - 1;
2551             r.size.h = r.size.h - 1;
2552             MenuItem* selectedMenuItem = menuControl->GetSelectedMenuItem();
2553             if (Selected() || this == selectedMenuItem)
2554             {
2555                 graphics.FillRectangleChecked(mouseOverBrushr);
2556                 graphics.DrawRectangleChecked(blackPenr);
2557             }
2558             if (Level() == 0)
2559             {
2560                 if (!drawSubItems)
2561                 {
2562                     if (!Selected() && this != selectedMenuItem)
2563                     {
2564                         graphics.FillRectangleChecked(backgroundBrushr);
2565                     }
2566                     StringFormat textFormat(format);
2567                     textFormat.SetAlignment(StringAlignment.center);
2568                     RectF rect(PointF(loc.xloc.y)SizeF(size.wsize.h));
2569                     if (IsEnabled())
2570                     {
2571                         graphics.DrawStringChecked(textfontrecttextFormattextBrush);
2572                     }
2573                     else
2574                     {
2575                         graphics.DrawStringChecked(textfontrecttextFormatdisabledTextBrush);
2576                     }
2577                 }
2578             }
2579             else
2580             {
2581                 if (drawSubItems)
2582                 {
2583                     Padding padding = DefaultPadding();
2584                     if (IsEnabled())
2585                     {
2586                         graphics.DrawStringChecked(textfontPointF(loc.x + padding.leftloc.y + padding.top)formattextBrush);
2587                         DrawShortcut(graphicstextBrushfontformatorigin);
2588                     }
2589                     else
2590                     {
2591                         graphics.DrawStringChecked(textfontPointF(loc.x + padding.leftloc.y + padding.top)formatdisabledTextBrush);
2592                         DrawShortcut(graphicsdisabledTextBrushfontformatorigin);
2593                     }
2594                     DrawChildIndicator(graphicsblackBrushorigin);
2595                 }
2596             }
2597         }
2598         private void DrawOpen(Graphics& graphicsconst Padding& parentPaddingconst Brush& textBrushconst Brush& disabledTextBrushconst Brush& backgroundBrushconst Brush& mouseOverBrush
2599             const Brush& menuOpenBrushconst Brush& shadowBrushconst Brush& blackBrushconst Pen& blackPenconst Pen& darkPenconst Font& fontconst StringFormat& format
2600             const Color& menuOpenColorMenuControl* menuControlbool drawSubItemsconst Point& origin)
2601         {
2602             Point loc = Location();
2603             loc.x = loc.x - origin.x;
2604             loc.y = loc.y - origin.y;
2605             Size size = GetSize();
2606             Rect r(locsize);
2607             r.size.w = r.size.w - 1;
2608             r.size.h = r.size.h - 1;
2609             int shadowWidth = ShadowWidth();
2610             if (Level() == 0)
2611             {
2612                 if (!drawSubItems)
2613                 {
2614                     graphics.FillRectangleChecked(menuOpenBrushr);
2615                     graphics.DrawLineChecked(blackPenr.locationPoint(r.location.x + r.size.wr.location.y));
2616                     //graphics.DrawLineChecked(blackPen, r.location, Point(r.location.x, r.size.h));
2617                     graphics.DrawLineChecked(blackPenr.locationPoint(r.location.xr.location.y + r.size.h));
2618                     graphics.DrawLineChecked(blackPenPoint(r.location.x + r.size.wr.location.y)Point(r.location.x + r.size.wr.location.y + r.size.h));
2619                     if (children.IsEmpty())
2620                     {
2621                         graphics.DrawLineChecked(blackPenPoint(r.location.xr.location.y + r.size.h)Point(r.location.x + r.size.wr.location.y + r.size.h));
2622                     }
2623                     StringFormat textFormat(format);
2624                     textFormat.SetAlignment(StringAlignment.center);
2625                     RectF rect(PointF(loc.xloc.y)SizeF(size.wsize.h));
2626                     if (IsEnabled())
2627                     {
2628                         graphics.DrawStringChecked(textfontrecttextFormattextBrush);
2629                     }
2630                     else
2631                     {
2632                         graphics.DrawStringChecked(textfontrecttextFormatdisabledTextBrush);
2633                     }
2634                 }
2635             }
2636             else
2637             {
2638                 if (drawSubItems)
2639                 {
2640                     MenuItem* selectedMenuItem = menuControl->GetSelectedMenuItem();
2641                     if (Selected() || this == selectedMenuItem)
2642                     {
2643                         graphics.FillRectangleChecked(mouseOverBrushr);
2644                         graphics.DrawRectangleChecked(blackPenr);
2645                     }
2646                     else
2647                     {
2648                         Rect inside = r;
2649                         inside.Inflate(-1-1);
2650                         graphics.FillRectangleChecked(menuOpenBrushinside);
2651                     }
2652                     Padding padding = DefaultPadding();
2653                     if (IsEnabled())
2654                     {
2655                         graphics.DrawStringChecked(textfontPointF(loc.x + padding.leftloc.y + padding.top)formattextBrush);
2656                         DrawShortcut(graphicstextBrushfontformatorigin);
2657                     }
2658                     else
2659                     {
2660                         graphics.DrawStringChecked(textfontPointF(loc.x + padding.leftloc.y + padding.top)formatdisabledTextBrush);
2661                         DrawShortcut(graphicsdisabledTextBrushfontformatorigin);
2662                     }
2663                     DrawChildIndicator(graphicsblackBrushorigin);
2664                 }
2665             }
2666             if (!childRect.IsEmpty())
2667             {
2668                 if (drawSubItems)
2669                 {
2670                     Region prevClipRegion = graphics.GetClipChecked();
2671                     Rect menuBox = childRect;
2672                     menuBox.location.x = menuBox.location.x - origin.x;
2673                     menuBox.location.y = menuBox.location.y - origin.y;
2674                     menuBox.size.h = menuBox.size.h - shadowWidth;
2675                     menuBox.size.w = menuBox.size.w - shadowWidth;
2676                     graphics.SetClipChecked(menuBox);
2677                     graphics.Clear(menuOpenColor);
2678                     Rect cr(childRect);
2679                     cr.location.x = cr.location.x - origin.x;
2680                     cr.location.y = cr.location.y - origin.y;
2681                     graphics.SetClipChecked(cr);
2682                     Rect bottomShadowRect(
2683                         Point(cr.location.x + shadowWidthcr.location.y + cr.size.h - shadowWidth)
2684                         Size(cr.size.w - shadowWidthshadowWidth));
2685                     graphics.FillRectangleChecked(shadowBrushbottomShadowRect);
2686                     Rect rightShadowRect(
2687                         Point(cr.location.x + cr.size.w - shadowWidthcr.location.y + shadowWidth)
2688                         Size(shadowWidthcr.size.h - shadowWidth));
2689                     graphics.FillRectangleChecked(shadowBrushrightShadowRect);
2690                     Rect rect = childRect;
2691                     rect.location.x = rect.location.x - origin.x;
2692                     rect.location.y = rect.location.y - origin.y;
2693                     rect.size.w = rect.size.w - 1;
2694                     rect.size.h = rect.size.h - 1;
2695                     if (Level() == 0)
2696                     {
2697                         graphics.DrawLineChecked(blackPenrect.locationPoint(rect.location.xrect.location.y + rect.size.h - shadowWidth));
2698                         graphics.DrawLineChecked(blackPenPoint(rect.location.xrect.location.y + rect.size.h - shadowWidth)
2699                             Point(rect.location.x + rect.size.w - shadowWidthrect.location.y + rect.size.h - shadowWidth));
2700                         graphics.DrawLineChecked(blackPenPoint(rect.location.x + rect.size.w - shadowWidthrect.location.y + rect.size.h - shadowWidth)
2701                             Point(rect.location.x + rect.size.w - shadowWidthrect.location.y));
2702                         graphics.DrawLineChecked(blackPen
2703                             Point(rect.location.x + rect.size.w - shadowWidthrect.location.y)Point(r.location.x + r.size.wrect.location.y));
2704                     }
2705                     else
2706                     {
2707                         graphics.DrawLineChecked(blackPenrect.locationPoint(rect.location.xrect.location.y + rect.size.h - shadowWidth));
2708                         graphics.DrawLineChecked(blackPenPoint(rect.location.xr.location.y + rect.size.h - shadowWidth)
2709                             Point(rect.location.x + rect.size.w - shadowWidthrect.location.y + rect.size.h - shadowWidth));
2710                         graphics.DrawLineChecked(blackPenPoint(rect.location.x + rect.size.w - shadowWidthrect.location.y + rect.size.h - shadowWidth)
2711                             Point(rect.location.x + rect.size.w - shadowWidthrect.location.y));
2712                         graphics.DrawLineChecked(blackPenPoint(rect.location.x + rect.size.w - shadowWidthrect.location.y)
2713                             Point(rect.location.xrect.location.y));
2714                     }
2715                     Component* child = children.FirstChild();
2716                     while (child != null)
2717                     {
2718                         if (child is MenuItemBase*)
2719                         {
2720                             MenuItemBase* menuItem = cast<MenuItem*>(child);
2721                             menuItem->Draw(graphicsparentPaddingtextBrushdisabledTextBrushbackgroundBrushmouseOverBrushmenuOpenBrushshadowBrushblackBrushblackPendarkPen
2722                                 fontformatmenuOpenColormenuControldrawSubItemsorigin);
2723                         }
2724                         child = child->NextSibling();
2725                     }
2726                     graphics.SetClipChecked(prevClipRegion);
2727                 }
2728             }
2729         }
2730         private void DrawShortcut(Graphics& graphicsconst Brush& textBrushconst Font& fontconst StringFormat& formatconst Point& origin)
2731         {
2732             if (shortcut != Keys.none)
2733             {
2734                 string shortcutText = ToString(shortcut);
2735                 Padding shortcutPadding = ShortcutPadding();
2736                 int shortcutFieldWidth = 0;
2737                 int childIndicatorFieldWidth = 0;
2738                 MenuItem* parent = GetParentMenuItem();
2739                 if (parent != null)
2740                 {
2741                     shortcutFieldWidth = parent->shortcutFieldWidth;
2742                     childIndicatorFieldWidth = parent->childIndicatorFieldWidth;
2743                 }
2744                 Padding padding = DefaultPadding();
2745                 int shadowWidth = ShadowWidth();
2746                 Point loc = Location();
2747                 loc.x = loc.x - origin.x;
2748                 loc.y = loc.y - origin.y;
2749                 Size size = GetSize();
2750                 graphics.DrawStringChecked(shortcutTextfont
2751                     PointF(loc.x + size.w - shadowWidth - shortcutFieldWidth - childIndicatorFieldWidth + shortcutPadding.leftloc.y + padding.top)formattextBrush);
2752             }
2753         }
2754         private void DrawChildIndicator(Graphics& graphicsconst Brush& blackBrushconst Point& origin)
2755         {
2756             if (children.IsEmpty()) return;
2757             Point loc = Location();
2758             loc.x = loc.x - origin.x;
2759             loc.y = loc.y - origin.y;
2760             Size size = GetSize();
2761             int childIndicatorIndent = ChildIndicatorIndent();
2762             int childIndicatorWidth = ChildIndicatorWidth();
2763             int shadowWidth = ShadowWidth();
2764             Point up(loc.x + size.w - childIndicatorIndent - shadowWidthloc.y + size.h / 2 - childIndicatorWidth / 2);
2765             Point down(loc.x + size.w - childIndicatorIndent - shadowWidthloc.y + size.h / 2 + childIndicatorWidth / 2);
2766             Point right(loc.x + size.w - childIndicatorIndent + cast<int>((Sqrt(3) / 2.0) * childIndicatorWidth) - shadowWidthloc.y + size.h / 2);
2767             List<Point> triangle;
2768             triangle.Add(up);
2769             triangle.Add(down);
2770             triangle.Add(right);
2771             graphics.FillPolygonChecked(blackBrush3triangle.Begin().Ptr());
2772         }
2773         internal nothrow bool IsSameOrParentOf(MenuItem* menuItem) const
2774         {
2775             if (this == menuItem) return true;
2776             MenuItem* parent = menuItem->GetParentMenuItem();
2777             if (parent != null)
2778             {
2779                 return IsSameOrParentOf(parent);
2780             }
2781             return false;
2782         }
2783         internal inline nothrow bool Selected() const
2784         {
2785             return (flags & Flags.selected) != 0;
2786         }
2787         internal nothrow void SetSelected(MenuControl* menuControl)
2788         {
2789             if ((flags & Flags.selected) == 0)
2790             {
2791                 flags = cast<Flags>(flags | Flags.selected);
2792                 menuControl->SetMenuInvalidated();
2793             }
2794         }
2795         internal nothrow void ResetSelected(MenuControl* menuControl)
2796         {
2797             if ((flags & Flags.selected) != 0)
2798             {
2799                 flags = cast<Flags>(flags & ~Flags.selected);
2800                 menuControl->SetMenuInvalidated();
2801             }
2802         }
2803         public inline nothrow bool IsEnabled() const
2804         {
2805             return cast<Flags>(flags & Flags.disabled) == Flags.none;
2806         }
2807         public inline nothrow bool IsDisabled() const
2808         {
2809             return cast<Flags>(flags & Flags.disabled) != Flags.none;
2810         }
2811         public nothrow void Enable()
2812         {
2813             if (!IsEnabled())
2814             {
2815                 flags = cast<Flags>(flags & ~Flags.disabled);
2816                 MenuControl* menuControl = GetMenuControl();
2817                 if (menuControl != null)
2818                 {
2819                     menuControl->SetMenuInvalidated();
2820                     menuControl->SetMenuChanged();
2821                 }
2822             }
2823         }
2824         public nothrow void Disable()
2825         {
2826             if (IsEnabled())
2827             {
2828                 flags = cast<Flags>(flags | Flags.disabled);
2829                 MenuControl* menuControl = GetMenuControl();
2830                 if (menuControl != null)
2831                 {
2832                     menuControl->SetMenuInvalidated();
2833                     menuControl->SetMenuChanged();
2834                 }
2835             }
2836         }
2837         internal inline nothrow bool MouseInClient() const
2838         {
2839             return (flags & Flags.mouseInClient) != 0;
2840         }
2841         internal void SetMouseInClient()
2842         {
2843             flags = cast<Flags>(flags | Flags.mouseInClient);
2844         }
2845         internal void ResetMouseInClient()
2846         {
2847             flags = cast<Flags>(flags & ~Flags.mouseInClient);
2848         }
2849         private inline nothrow bool LButtonPressed() const
2850         {
2851             return (flags & Flags.lbuttonPressed) != 0;
2852         }
2853         private nothrow void SetLButtonPressed()
2854         {
2855             flags = cast<Flags>(flags | Flags.lbuttonPressed);
2856         }
2857         private nothrow void ResetLButtonPressed()
2858         {
2859             flags = cast<Flags>(flags & ~Flags.lbuttonPressed);
2860         }
2861         public nothrow Event<MouseEventHandlerMouseEventArgs>& MouseDownEvent()
2862         {
2863             return mouseDownEvent;
2864         }
2865         public nothrow Event<MouseEventHandlerMouseEventArgs>& MouseUpEvent()
2866         {
2867             return mouseUpEvent;
2868         }
2869         public nothrow Event<MouseEnterEventHandler>& MouseEnterEvent()
2870         {
2871             return mouseEnterEvent;
2872         }
2873         public nothrow Event<MouseEventHandlerMouseEventArgs>& MouseMoveEvent()
2874         {
2875             return mouseMoveEvent;
2876         }
2877         public nothrow Event<MouseLeaveEventHandler>& MouseLeaveEvent()
2878         {
2879             return mouseLeaveEvent;
2880         }
2881         public nothrow Event<ClickEventHandler>& ClickEvent()
2882         {
2883             return clickEvent;
2884         }
2885         private string text;
2886         private Container children;
2887         private Rect childRect;
2888         private Rect unionRect;
2889         private Event<MouseEventHandlerMouseEventArgs> mouseDownEvent;
2890         private Event<MouseEventHandlerMouseEventArgs> mouseUpEvent;
2891         private Event<MouseEnterEventHandler> mouseEnterEvent;
2892         private Event<MouseEventHandlerMouseEventArgs> mouseMoveEvent;
2893         private Event<MouseLeaveEventHandler> mouseLeaveEvent;
2894         private Event<ClickEventHandler> clickEvent;
2895         private State state;
2896         private Flags flags;
2897         private wchar accessKey;
2898         private Keys shortcut;
2899         private int shortcutFieldWidth;
2900         private int childIndicatorFieldWidth;
2901     }
2902 
2903     public class MenuItemSeparator : MenuItemBase
2904     {
2905         public override void Draw(Graphics& graphicsconst Padding& parentPaddingconst Brush& textBrushconst Brush& disabledTextBrushconst Brush& backgroundBrushconst Brush& mouseOverBrush
2906             const Brush& menuOpenBrushconst Brush& shadowBrushconst Brush& blackBrushconst Pen& blackPenconst Pen& darkPenconst Font& fontconst StringFormat& format
2907             const Color& menuOpenColorMenuControl* menuControlbool drawSubItemsconst Point& origin)
2908         {
2909             Point loc = Location();
2910             loc.x = loc.x - origin.x;
2911             loc.y = loc.y - origin.y;
2912             Rect rect(locGetSize());
2913             Padding padding = DefaultPadding();
2914             graphics.DrawLineChecked(darkPen
2915                 Point(rect.location.x + padding.leftrect.location.y + rect.size.h / 2)
2916                 Point(rect.location.x + rect.size.w - padding.rightrect.location.y + rect.size.h / 2));
2917         }
2918         public override nothrow Padding DefaultPadding() const
2919         {
2920             return Padding(32484);
2921         }
2922         public override Size MeasureItem(Graphics& graphicsconst Font& fontconst StringFormat& formatint& shortcutFieldWidthint& childIndicatorFieldWidth)
2923         {
2924             Padding padding = DefaultPadding();
2925             RectF rect;
2926             int w = cast<int>(rect.size.w);
2927             w = w + padding.Horizontal();
2928             int h = cast<int>(rect.size.h);
2929             h = h + padding.Vertical();
2930             Size size(wh);
2931             SetSize(size);
2932             return size;
2933         }
2934     }
2935 }