MenuAPI.cs :  » 2.6.4-mono-.net-core » System.Windows.Forms » System » Windows » Forms » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows.Forms 
System.Windows.Forms » System » Windows » Forms » MenuAPI.cs
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2004-2005 Novell, Inc.
//
// Authors:
//  Jordi Mas i Hernandez, jordi@ximian.com
//  Mike Kestner  <mkestner@novell.com>
//  Everaldo Canuto  <ecanuto@novell.com>
//

using System.Collections;
using System.Drawing;
using System.Threading;

namespace System.Windows.Forms{

  /*
    When writing this code the Wine project was of great help to
    understand the logic behind some Win32 issues. Thanks to them. Jordi,
  */
  // UIA Framework Note: This class used by UIA for its mouse action methods.
  internal class MenuTracker {

    internal bool active;
    internal bool popup_active;
    internal bool popdown_menu;
    internal bool hotkey_active;
    private bool mouse_down = false;
    public Menu CurrentMenu;
    public Menu TopMenu;
    public Control GrabControl;
    Point last_motion = Point.Empty;
    
      public MenuTracker (Menu top_menu)
    {
      TopMenu = CurrentMenu = top_menu;
      foreach (MenuItem item in TopMenu.MenuItems)
        AddShortcuts (item);
    }

    enum KeyNavState {
      Idle,
      Startup,
      NoPopups,
      Navigating
    }

    KeyNavState keynav_state = KeyNavState.Idle;

    public bool Navigating {
      get { return keynav_state != KeyNavState.Idle || active; }
    }

    internal static Point ScreenToMenu (Menu menu, Point pnt)    
    {
      int x = pnt.X;
      int y = pnt.Y;
      XplatUI.ScreenToMenu (menu.Wnd.window.Handle, ref x, ref y);
      return new Point (x, y);
    }  

    private void UpdateCursor ()
    {
      Control child_control = GrabControl.GetRealChildAtPoint (Cursor.Position);
      if (child_control != null) {
        if (active)
          XplatUI.SetCursor (child_control.Handle, Cursors.Default.handle);
        else
          XplatUI.SetCursor (child_control.Handle, child_control.Cursor.handle);
      }
    }

    internal void Deactivate ()
    {
      bool redrawbar = (keynav_state != KeyNavState.Idle) && (TopMenu is MainMenu); 

      active = false;
      popup_active = false;
      hotkey_active = false;
      if (GrabControl != null)
        GrabControl.ActiveTracker = null;
      keynav_state = KeyNavState.Idle;
      if (TopMenu is ContextMenu) {
        PopUpWindow puw = TopMenu.Wnd as PopUpWindow;
        DeselectItem (TopMenu.SelectedItem);
        if (puw != null)
          puw.HideWindow ();
      } else {
        DeselectItem (TopMenu.SelectedItem);
      }
      CurrentMenu = TopMenu;

      if (redrawbar)
        (TopMenu as MainMenu).Draw ();      
    }

    MenuItem FindItemByCoords (Menu menu, Point pt)
    {
      if (menu is MainMenu)
        pt = ScreenToMenu (menu, pt);
      else
        pt = menu.Wnd.PointToClient (pt);
      foreach (MenuItem item in menu.MenuItems) {
        Rectangle rect = item.bounds;
        if (rect.Contains (pt))
          return item;
      }

      return null;
    }

    MenuItem GetItemAtXY (int x, int y)
    {
      Point pnt = new Point (x, y);
      MenuItem item = null;
      if (TopMenu.SelectedItem != null)
        item = FindSubItemByCoord (TopMenu.SelectedItem, Control.MousePosition);
      if (item == null)
        item = FindItemByCoords (TopMenu, pnt);
      return item;
    }

    // UIA Framework Note: Used to expand/collapse MenuItems
    public bool OnMouseDown (MouseEventArgs args)
    {
      MenuItem item = GetItemAtXY (args.X, args.Y);

      mouse_down = true;

      if (item == null) {
        Deactivate ();
        return false;
      }

      if ((args.Button & MouseButtons.Left) == 0)
        return true;

      if (!item.Enabled)
        return true;
      
      popdown_menu = active && item.VisibleItems;
      
      if (item.IsPopup || (item.Parent is MainMenu)) {
        active = true;
        item.Parent.InvalidateItem (item);
      }
      
      if ((CurrentMenu == TopMenu) && !popdown_menu)
        SelectItem (item.Parent, item, item.IsPopup);
      
      GrabControl.ActiveTracker = this;
      return true;
    }

    // UIA Framework Note: Used to select MenuItems
    public void OnMotion (MouseEventArgs args)
    {
      // Windows helpfully sends us MOUSEMOVE messages when any key is pressed.
      // So if the mouse hasn't actually moved since the last MOUSEMOVE, ignore it.
      if (args.Location == last_motion)
        return;
        
      last_motion = args.Location;
      
      MenuItem item = GetItemAtXY (args.X, args.Y);

      UpdateCursor ();

      if (CurrentMenu.SelectedItem == item)
        return;

      GrabControl.ActiveTracker = (active || item != null) ? this : null;

      if (item == null) {
        MenuItem old_item = CurrentMenu.SelectedItem;
        
        // Return when is a popup with visible subitems for MainMenu 
        if  ((active && old_item.VisibleItems && old_item.IsPopup && (CurrentMenu is MainMenu)))
          return;

        // Also returns when keyboard navigating
        if (keynav_state == KeyNavState.Navigating)
          return;
        
        // Select parent menu when move outside of menu item
        if (old_item.Parent is MenuItem) {
          MenuItem new_item = (old_item.Parent as MenuItem);
          if (new_item.IsPopup) {
            SelectItem (new_item.Parent, new_item, false);
            return;
          }
        }
        if (CurrentMenu != TopMenu)
          CurrentMenu = CurrentMenu.parent_menu;
                
        DeselectItem (old_item);
      } else {
        keynav_state = KeyNavState.Idle;
        SelectItem (item.Parent, item, active && item.IsPopup && popup_active && (CurrentMenu.SelectedItem != item));
      }
    }

    // UIA Framework Note: Used to expand/collapse MenuItems
    public void OnMouseUp (MouseEventArgs args)
    {
      /* mouse down dont comes from menu */
      if (!mouse_down)
        return;

      mouse_down = false;

      /* is not left button */
      if ((args.Button & MouseButtons.Left) == 0)
        return;
      
      MenuItem item = GetItemAtXY (args.X, args.Y);

      /* the user released the mouse button outside the menu */
      if (item == null) {
        Deactivate ();
        return;
      }
      
      if (!item.Enabled)
        return;
      
      /* Deactivate the menu when is topmenu and popdown and */
      if (((CurrentMenu == TopMenu) && !(CurrentMenu is ContextMenu) && popdown_menu) || !item.IsPopup) {
        Deactivate ();
        UpdateCursor ();
      }
      
      /* Perform click when is not a popup */
      if (!item.IsPopup) {
        DeselectItem (item);
        
        // Raise the form's MenuComplete event
        if (TopMenu != null && TopMenu.Wnd != null) {
          Form f = TopMenu.Wnd.FindForm ();
          
          if (f != null)
            f.OnMenuComplete (EventArgs.Empty);  
        }
        
        item.PerformClick ();
      }
    }

    static public bool TrackPopupMenu (Menu menu, Point pnt)
    {
      if (menu.MenuItems.Count <= 0)  // No submenus to track
        return true;        

      MenuTracker tracker = menu.tracker;
      tracker.active = true;
      tracker.popup_active = true;
      
      // Set GrabControl
      Control src_ctrl = (tracker.TopMenu as ContextMenu).SourceControl;
      tracker.GrabControl = src_ctrl.FindForm ();
      if (tracker.GrabControl == null)
        tracker.GrabControl = src_ctrl.FindRootParent ();
      tracker.GrabControl.ActiveTracker = tracker;
      
      menu.Wnd = new PopUpWindow (tracker.GrabControl, menu);
      menu.Wnd.Location =  menu.Wnd.PointToClient (pnt);
      ((PopUpWindow)menu.Wnd).ShowWindow ();

      bool no_quit = true;

      Object queue_id = XplatUI.StartLoop(Thread.CurrentThread);

      while ((menu.Wnd != null) && menu.Wnd.Visible && no_quit) {
        MSG msg = new MSG ();
        no_quit = XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0);

        switch((Msg)msg.message) {
        case Msg.WM_KEYDOWN:
        case Msg.WM_SYSKEYDOWN:
        case Msg.WM_CHAR:
        case Msg.WM_SYSCHAR:
        case Msg.WM_KEYUP:
        case Msg.WM_SYSKEYUP:
          Control c = Control.FromHandle(msg.hwnd);
          if (c != null) {
            Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
            c.PreProcessControlMessageInternal (ref m);
          }
          break;
        default:
          XplatUI.TranslateMessage (ref msg);
          XplatUI.DispatchMessage (ref msg);
          break;
        }
      }

      if (tracker.GrabControl.IsDisposed)
        return true;

      if (!no_quit)
        XplatUI.PostQuitMessage(0);

      if (menu.Wnd != null) {
        menu.Wnd.Dispose ();
        menu.Wnd = null;
      }

      return true;
    }
  
    void DeselectItem (MenuItem item)
    {
      if (item == null)
        return;        
      
      item.Selected = false;

      /* When popup item then close all sub popups and unselect all sub items */
      if (item.IsPopup) {
        HideSubPopups (item, TopMenu);
        
        /* Unselect all selected sub itens */
        foreach (MenuItem subitem in item.MenuItems)
          if (subitem.Selected)
            DeselectItem (subitem);
      }

      Menu menu = item.Parent;
      menu.InvalidateItem (item);
    }

    void SelectItem (Menu menu, MenuItem item, bool execute)
    {
      MenuItem prev_item = CurrentMenu.SelectedItem;
      
      if (prev_item != item.Parent) {
        DeselectItem (prev_item);
        if ((CurrentMenu != menu) && (prev_item.Parent != item) && (prev_item.Parent is MenuItem)) {
          DeselectItem (prev_item.Parent as MenuItem);
        }
      }

      if (CurrentMenu != menu)
        CurrentMenu = menu;
      
      item.Selected = true;
      menu.InvalidateItem (item);
      
      if (((CurrentMenu == TopMenu) && execute) || ((CurrentMenu != TopMenu) && popup_active))
        item.PerformSelect ();

      if ((execute) && ((prev_item == null) || (item != prev_item.Parent)))
        ExecFocusedItem (menu, item);
    }

    //  Used when the user executes the action of an item (press enter, shortcut)
    //  or a sub-popup menu has to be shown
    void ExecFocusedItem (Menu menu, MenuItem item)
    {
      if (item == null)
        return;

      if (!item.Enabled)
         return;
         
      if (item.IsPopup) {
        ShowSubPopup (menu, item);
      } else {
        Deactivate ();
        item.PerformClick ();
      }
    }

    // Create a popup window and show it or only show it if it is already created
    void ShowSubPopup (Menu menu, MenuItem item)
    {
      if (item.Enabled == false)
        return;

      if (!popdown_menu || !item.VisibleItems) 
        item.PerformPopup ();
      
      if (item.VisibleItems == false)
        return;

      if (item.Wnd != null) {
        item.Wnd.Dispose ();
      }

      popup_active = true;
      PopUpWindow puw = new PopUpWindow (GrabControl, item);
      
      Point pnt;
      if (menu is MainMenu)
        pnt = new Point (item.X, item.Y + item.Height - 2 - menu.Height);
      else
        pnt = new Point (item.X + item.Width - 3, item.Y - 3);
      pnt = menu.Wnd.PointToScreen (pnt);
      puw.Location = pnt;
      item.Wnd = puw;

      puw.ShowWindow ();
    }

    static public void HideSubPopups (Menu menu, Menu topmenu)
    {
      foreach (MenuItem item in menu.MenuItems)
        if (item.IsPopup)
          HideSubPopups (item, null);

      if (menu.Wnd == null)
        return;

      PopUpWindow puw = menu.Wnd as PopUpWindow;
      if (puw != null) {
        puw.Hide ();
        puw.Dispose ();
      }
      menu.Wnd = null;

#if NET_2_0
      if ((topmenu != null) && (topmenu is MainMenu))
        ((MainMenu) topmenu).OnCollapse (EventArgs.Empty);
#endif
    }

    MenuItem FindSubItemByCoord (Menu menu, Point pnt)
    {    
      foreach (MenuItem item in menu.MenuItems) {

        if (item.IsPopup && item.Wnd != null && item.Wnd.Visible && item == menu.SelectedItem) {
          MenuItem result = FindSubItemByCoord (item, pnt);
          if (result != null)
            return result;
        }
          
        if (menu.Wnd == null || !menu.Wnd.Visible)
          continue;

        Rectangle rect = item.bounds;
        Point pnt_client = menu.Wnd.PointToScreen (new Point (item.X, item.Y));
        rect.X = pnt_client.X;
        rect.Y = pnt_client.Y;
        
        if (rect.Contains (pnt) == true)
          return item;
      }      
      
      return null;
    }

    static MenuItem FindItemByKey (Menu menu, IntPtr key)
    {
      char key_char = Char.ToUpper ((char) (key.ToInt32() & 0xff));
      foreach (MenuItem item in menu.MenuItems) {
        if (item.Mnemonic == key_char)
          return item;
      }

      string key_str = key_char.ToString (); 
      foreach (MenuItem item in menu.MenuItems) {
        //if (item.Mnemonic == key_char)
        if (item.Text.StartsWith (key_str))
          return item;
      }

      return null;
    }

    enum ItemNavigation {
      First,
      Last,
      Next,
      Previous,
    }

    static MenuItem GetNextItem (Menu menu, ItemNavigation navigation)
    {
      int pos = 0;
      bool selectable_items = false;
      MenuItem item;

      // Check if there is at least a selectable item
      for (int i = 0; i < menu.MenuItems.Count; i++) {
        item = menu.MenuItems [i];
        if (item.Separator == false && item.Visible == true) {
          selectable_items = true;
          break;
        }
      }

      if (selectable_items == false)
        return null;

      switch (navigation) {
      case ItemNavigation.First:

        /* First item that is not separator and it is visible*/
        for (pos = 0; pos < menu.MenuItems.Count; pos++) {
          item = menu.MenuItems [pos];
          if (item.Separator == false && item.Visible == true)
            break;
        }

        break;

      case ItemNavigation.Last: // Not used
        break;

      case ItemNavigation.Next:

        pos = menu.SelectedItem == null ? - 1 : menu.SelectedItem.Index;

        /* Next item that is not separator and it is visible*/
        for (pos++; pos < menu.MenuItems.Count; pos++) {
          item = menu.MenuItems [pos];
          if (item.Separator == false && item.Visible == true)
            break;
        }

        if (pos >= menu.MenuItems.Count) { /* Jump at the start of the menu */
          pos = 0;
          /* Next item that is not separator and it is visible*/
          for (; pos < menu.MenuItems.Count; pos++) {
            item = menu.MenuItems [pos];
            if (item.Separator == false && item.Visible == true)
              break;
          }
        }
        break;

      case ItemNavigation.Previous:

        if (menu.SelectedItem != null)
          pos = menu.SelectedItem.Index;

        /* Previous item that is not separator and it is visible*/
        for (pos--; pos >= 0; pos--) {
          item = menu.MenuItems [pos];
          if (item.Separator == false && item.Visible == true)
            break;
        }

        if (pos < 0 ) { /* Jump at the end of the menu*/
          pos = menu.MenuItems.Count - 1;
          /* Previous item that is not separator and it is visible*/
          for (; pos >= 0; pos--) {
            item = menu.MenuItems [pos];
            if (item.Separator == false && item.Visible == true)
              break;
          }
        }

        break;

      default:
        break;
      }

      return menu.MenuItems [pos];
    }

    void ProcessMenuKey (Msg msg_type)
    {
      if (TopMenu.MenuItems.Count == 0)
        return;

      MainMenu main_menu = TopMenu as MainMenu;

      switch (msg_type) {
      case Msg.WM_SYSKEYDOWN:
        switch (keynav_state) {
        case KeyNavState.Idle:
          keynav_state = KeyNavState.Startup;
          hotkey_active = true;
          GrabControl.ActiveTracker = this;
          CurrentMenu = TopMenu;
          main_menu.Draw ();
          break;
        case KeyNavState.Startup:
          break;
        default:
          Deactivate ();
          main_menu.Draw ();
          break;
        }
        break;

      case Msg.WM_SYSKEYUP:
        switch (keynav_state) {
        case KeyNavState.Idle:
        case KeyNavState.Navigating:
          break;
        case KeyNavState.Startup:
          keynav_state = KeyNavState.NoPopups;
          SelectItem (TopMenu, TopMenu.MenuItems [0], false);
          break;
        default:
          Deactivate ();
          main_menu.Draw ();
          break;
        }
        break;
      }
    }

    bool ProcessMnemonic (Message msg, Keys key_data)
    {
      keynav_state = KeyNavState.Navigating;
      MenuItem item = FindItemByKey (CurrentMenu, msg.WParam);
      if ((item == null) || (GrabControl == null))
        return false;

      active = true;
      GrabControl.ActiveTracker = this;
      
      SelectItem (CurrentMenu, item, true);
      if (item.IsPopup) {
        CurrentMenu = item;
        SelectItem (item, item.MenuItems [0], false);
      }
      return true;
    }

    Hashtable shortcuts = new Hashtable ();
    
    public void AddShortcuts (MenuItem item)
    {
      foreach (MenuItem child in item.MenuItems) {
        AddShortcuts (child);
        if (child.Shortcut != Shortcut.None)
          shortcuts [(int)child.Shortcut] = child;
      }

      if (item.Shortcut != Shortcut.None)
        shortcuts [(int)item.Shortcut] = item;
    }

    public void RemoveShortcuts (MenuItem item)
    {
      foreach (MenuItem child in item.MenuItems) {
        RemoveShortcuts (child);
        if (child.Shortcut != Shortcut.None)
          shortcuts.Remove ((int)child.Shortcut);
      }

      if (item.Shortcut != Shortcut.None)
        shortcuts.Remove ((int)item.Shortcut);
    }

    bool ProcessShortcut (Keys keyData)
    {
      MenuItem item = shortcuts [(int)keyData] as MenuItem;
      if (item == null || !item.Enabled)
        return false;

      if (active)
        Deactivate ();
      item.PerformClick ();
      return true;
    }

    public bool ProcessKeys (ref Message msg, Keys keyData)
    {
      // We should process Alt+key only if we don't have an active menu,
      // and hide it otherwise.
      if ((keyData & Keys.Alt) == Keys.Alt && active) {
        Deactivate ();
        return false;
      }

      // If we get Alt-F4, Windows will ignore it because we have a capture,
      // release the capture and the program will exit.  (X11 doesn't care.)
      if ((keyData & Keys.Alt) == Keys.Alt && (keyData & Keys.F4) == Keys.F4) {
        if (GrabControl != null)
          GrabControl.ActiveTracker = null;
          
        return false;
      }
      
      if ((Msg)msg.Msg != Msg.WM_SYSKEYUP && ProcessShortcut (keyData))
        return true;
      else if ((keyData & Keys.KeyCode) == Keys.Menu && TopMenu is MainMenu) {
        ProcessMenuKey ((Msg) msg.Msg);
        return true;
      } else if ((keyData & Keys.Alt) == Keys.Alt)
        return ProcessMnemonic (msg, keyData);
      else if ((Msg)msg.Msg == Msg.WM_SYSKEYUP)
        return false;
      else if (!Navigating)
        return false;

      MenuItem item;
      
      switch (keyData) {
      case Keys.Up:
        if (CurrentMenu is MainMenu)
          return true;
        else if (CurrentMenu.MenuItems.Count == 1 && CurrentMenu.parent_menu == TopMenu) {
          DeselectItem (CurrentMenu.SelectedItem);
          CurrentMenu = TopMenu;
          return true;
        }
        item = GetNextItem (CurrentMenu, ItemNavigation.Previous);
        if (item != null)
          SelectItem (CurrentMenu, item, false);
        break;
      
      case Keys.Down:
        if (CurrentMenu is MainMenu) {
          if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
            keynav_state = KeyNavState.Navigating;
            item = CurrentMenu.SelectedItem;
            ShowSubPopup (CurrentMenu, item);
            SelectItem (item, item.MenuItems [0], false);
            CurrentMenu = item;
            active = true;
            GrabControl.ActiveTracker = this;
          }
          return true;
        }
        item = GetNextItem (CurrentMenu, ItemNavigation.Next);
        if (item != null)
          SelectItem (CurrentMenu, item, false);
        break;
      
      case Keys.Right:
        if (CurrentMenu is MainMenu) {
          item = GetNextItem (CurrentMenu, ItemNavigation.Next);
          bool popup = item.IsPopup && keynav_state != KeyNavState.NoPopups;
          SelectItem (CurrentMenu, item, popup);
          if (popup) {
            SelectItem (item, item.MenuItems [0], false);
            CurrentMenu = item;
          }
        } else if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
          item = CurrentMenu.SelectedItem;
          ShowSubPopup (CurrentMenu, item);
          SelectItem (item, item.MenuItems [0], false);
          CurrentMenu = item;
        } else {
          //Search up for a main menu
          Menu Prnt = CurrentMenu.parent_menu;
          while (Prnt != null && !(Prnt is MainMenu)) {
            Prnt = Prnt.parent_menu;
           }
          if (Prnt is MainMenu)
          {
            item = GetNextItem(Prnt, ItemNavigation.Next);
            SelectItem(Prnt, item, item.IsPopup);
            if (item.IsPopup)
            {
              SelectItem(item, item.MenuItems[0], false);
              CurrentMenu = item;
            }
          }
        }
        break;
      
      case Keys.Left:
        if (CurrentMenu is MainMenu) {
          item = GetNextItem (CurrentMenu, ItemNavigation.Previous);
          bool popup = item.IsPopup && keynav_state != KeyNavState.NoPopups;
          SelectItem (CurrentMenu, item, popup);
          if (popup) {
            SelectItem (item, item.MenuItems [0], false);
            CurrentMenu = item;
          }
        } else if (CurrentMenu.parent_menu is MainMenu) {
          item = GetNextItem (CurrentMenu.parent_menu, ItemNavigation.Previous);
          SelectItem (CurrentMenu.parent_menu, item, item.IsPopup);
          if (item.IsPopup) {
            SelectItem (item, item.MenuItems [0], false);
            CurrentMenu = item;
          }
        } else if (!(CurrentMenu is ContextMenu)) { // ContextMenu root remains active.
          HideSubPopups (CurrentMenu, TopMenu);
          if (CurrentMenu.parent_menu != null)
            CurrentMenu = CurrentMenu.parent_menu;
        }
        break;

      case Keys.Return:
        if (CurrentMenu.SelectedItem != null && CurrentMenu.SelectedItem.IsPopup) {
          keynav_state = KeyNavState.Navigating;
          item = CurrentMenu.SelectedItem;
          ShowSubPopup (CurrentMenu, item);
          SelectItem (item, item.MenuItems [0], false);
          CurrentMenu = item;
          active = true;
          GrabControl.ActiveTracker = this;
        } else {
          ExecFocusedItem (CurrentMenu, CurrentMenu.SelectedItem);
        }
        break;
        
      case Keys.Escape:
        Deactivate ();
        break;

      default:
        ProcessMnemonic (msg, keyData);
        break;
      }

      return active;
    }
  }

  internal class PopUpWindow : Control
  {
    private Menu menu;
    private Control form;

    public PopUpWindow (Control form, Menu menu): base ()
    {
      this.menu = menu;
      this.form = form;
      SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
      SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
      is_visible = false;
    }

    protected override CreateParams CreateParams
    {
      get {
        CreateParams cp = base.CreateParams;
        cp.Caption = "Menu PopUp";
        cp.Style = unchecked ((int)(WindowStyles.WS_POPUP));
        cp.ExStyle |= (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST);
        return cp;
      }
    }

    public void ShowWindow ()
    {
      XplatUI.SetCursor(form.Handle, Cursors.Default.handle);
      RefreshItems ();
      Show ();
    }
    
    internal override void OnPaintInternal (PaintEventArgs args)
    {
      ThemeEngine.Current.DrawPopupMenu (args.Graphics, menu, args.ClipRectangle, ClientRectangle);
    }
    
    public void HideWindow ()
    {
      XplatUI.SetCursor (form.Handle, form.Cursor.handle);
      MenuTracker.HideSubPopups (menu, null);
        Hide ();
    }

    protected override void CreateHandle ()
    {
      base.CreateHandle ();
      RefreshItems ();      
    }    
    
    // Called when the number of items has changed
    internal void RefreshItems ()
    {
      Point pt = new Point (Location.X, Location.Y);
      
      ThemeEngine.Current.CalcPopupMenuSize (DeviceContext, menu);

      if ((pt.X + menu.Rect.Width) > SystemInformation.VirtualScreen.Width) {
        if (((pt.X - menu.Rect.Width) > 0) && !(menu.parent_menu is MainMenu))
          pt.X = pt.X - menu.Rect.Width;
        else
          pt.X = SystemInformation.VirtualScreen.Width - menu.Rect.Width;

        if (pt.X < 0)
          pt.X = 0;
      }
      if ((pt.Y + menu.Rect.Height) > SystemInformation.VirtualScreen.Height) {
        if ((pt.Y - menu.Rect.Height) > 0)
          pt.Y = pt.Y - menu.Rect.Height;
        else
          pt.Y = SystemInformation.VirtualScreen.Height - menu.Rect.Height;

        if (pt.Y < 0)
          pt.Y = 0;
      }

      Location = pt;
      Width = menu.Rect.Width;
      Height = menu.Rect.Height;      
    }
    
    internal override bool ActivateOnShow { get { return false; } }
  }
}


www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.