Beispiel #1
0
    public MenuControl()
    {
      // Set default values
      this.Dock = DockStyle.Top;
      _trackItem = -1;
      _selected = false;
      _multiLine = false;
      _popupMenu = null;
      _mouseOver = false;
      _manualFocus = false;
      _drawUpwards = false;
      _plainAsBlock = false;
      _oldFocus = IntPtr.Zero;
      _ignoreEscapeUp = false;
      _ignoreMouseMove = false;
      _dismissTransfer = false;
      _style = VisualStyle.IDE;
      _chevronStartCommand = null;
      _direction = Direction.Horizontal;
      _menuCommands = new MenuCommandCollection();
      
      // Prevent flicker with double buffering and all painting inside WM_PAINT
      SetStyle(ControlStyles.DoubleBuffer, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);

      // Should not be allowed to select this control
      SetStyle(ControlStyles.Selectable, false);

      // Hookup to collection events
      _menuCommands.Cleared += new CollectionClear( OnCollectionCleared );
      _menuCommands.Inserted+= new CollectionChange( OnCollectionInserted );
      _menuCommands.Removed += new CollectionChange( OnCollectionRemoved );

      // Set the default menu color as background
      this.BackColor = SystemColors.Control;

      // Do not allow tab key to select this control
      this.TabStop = false;

      // Default the Font we use
      this.Font = SystemInformation.MenuFont;

      // Calculate the initial height/width of the control
      _rowWidth = _rowHeight = this.Font.Height + _breadthGap * 2 + 1;

      // Default to one line of items
      this.Height = _rowHeight;

      // Add ourself to the application filtering list
      Application.AddMessageFilter(this);
    }
Beispiel #2
0
    protected override void OnMouseDown(MouseEventArgs e)
    {
      Point pos = new Point(e.X, e.Y);

      for(int i=0; i<_drawCommands.Count; i++)
      {
        DrawCommand dc = _drawCommands[i] as DrawCommand;

        // Find the DrawCommand this is over
        if (dc.DrawRect.Contains(pos))
        {
          // Is an item already selected?
          if (_selected)
          {
            // Is it this item that is already selected?
            if (_trackItem == i)
            {
              // Is a popupMenu showing
              if (_popupMenu != null)
              {
                // Dismiss the submenu
                _popupMenu.Dismiss();

                // No reference needed
                _popupMenu = null;
              }
            }
          }
          else
          {
            // Select the tracked item
            _selected = true;
            _drawUpwards = false;
                
            GrabTheFocus();
        
            // Is there a change in tracking?
            if (_trackItem != i)
            {
              // Modify the display of the two items 
              _trackItem = SwitchTrackingItem(_trackItem, i);
            }
            else
            {
              // Update display to show as selected
              DrawCommand(_trackItem, true);
            }

            // Is there a submenu to show?
            if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
              WindowsAPI.PostMessage(this.Handle, WM_OPERATEMENU, 1, 0);
          }

          break;
        }
      }

      base.OnMouseDown(e);
    }
Beispiel #3
0
    internal void OperateSubMenu(DrawCommand dc, bool selectFirst, bool trackRemove)
    {
      Rectangle drawRect = dc.DrawRect;

      // Find screen positions for popup menu
      Point screenPos;
      
      if (_style == VisualStyle.IDE)
      {
        if (_direction == Direction.Horizontal)
          screenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Bottom - _lengthGap - 1));
        else
          screenPos = PointToScreen(new Point(dc.DrawRect.Right - _breadthGap, drawRect.Top + _boxExpandSides - 1));
      }
      else
      {
        if (_direction == Direction.Horizontal)
          screenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Bottom));
        else
          screenPos = PointToScreen(new Point(dc.DrawRect.Right, drawRect.Top));
      }

      Point aboveScreenPos;
      
      if (_style == VisualStyle.IDE)
      {
        if (_direction == Direction.Horizontal)
          aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Top + _lengthGap + 1));
        else
          aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Right - _breadthGap, drawRect.Bottom + _lengthGap));
      }
      else
      {
        if (_direction == Direction.Horizontal)
          aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Left + 1, drawRect.Top));
        else
          aboveScreenPos = PointToScreen(new Point(dc.DrawRect.Right, drawRect.Bottom));
      }

      int borderGap;

      // Calculate the missing gap in the PopupMenu border
      if (_direction == Direction.Horizontal)
        borderGap = dc.DrawRect.Width - _subMenuBorderAdjust;
      else
        borderGap = dc.DrawRect.Height - _subMenuBorderAdjust;    
  
      _popupMenu = new PopupMenu();

      // Define the correct visual style based on ours
      _popupMenu.Style = this.Style;

      // Key direction when keys cause dismissal
      int returnDir = 0;

      if (dc.Chevron)
      {
        MenuCommandCollection mcc = new MenuCommandCollection();

        bool addCommands = false;

        // Generate a collection of menu commands for those not visible
        foreach(MenuCommand command in _menuCommands)
        {
          if (!addCommands && (command == _chevronStartCommand))
            addCommands = true;

          if (addCommands)
            mcc.Add(command);
        }

        // Track the popup using provided menu item collection
        _popupMenu.TrackPopup(screenPos, 
          aboveScreenPos,
          _direction,
          mcc, 
          borderGap,
          selectFirst,
          this,
          ref returnDir);
      }
      else
      {
        // Generate event so that caller has chance to modify MenuCommand contents
        OnPopupStart(dc.MenuCommand);

        // Track the popup using provided menu item collection
        _popupMenu.TrackPopup(screenPos, 
          aboveScreenPos,
          _direction,
          dc.MenuCommand.MenuCommands, 
          borderGap,
          selectFirst,
          this,
          ref returnDir);

        // Generate event so that caller has chance to modify MenuCommand contents
        OnPopupEnd(dc.MenuCommand);
      }

      // Remove unwanted object
      _popupMenu = null;

      // Was arrow key used to dismiss the submenu?
      if (returnDir != 0)
      {
        // Using keyboard movements means we should have the focus
        if (!_manualFocus)
        {
          _manualFocus = true;

          GrabTheFocus();
        }

        if (returnDir < 0)
        {
          // Shift selection left one
          ProcessMoveLeft(true);
        }
        else
        {
          // Shift selection right one
          ProcessMoveRight(true);
        }

        // A WM_MOUSEMOVE is generated when we open up the new submenu for 
        // display, ignore this as it causes the selection to move
        _ignoreMouseMove = true;
      }
      else
      {
        // Only if the submenu was dismissed at the request of the submenu
        // should the selection mode be cancelled, otherwise keep selection mode
        if (!_dismissTransfer)
        {
          // This item is no longer selected
          _selected = false;
          _drawUpwards = false;

          // Should we stop tracking this item
          if (trackRemove)
          {
            ReturnTheFocus();

            // Unselect the current item
            _trackItem = SwitchTrackingItem(_trackItem, -1);
          }
          else
          {
            // Repaint the item
            DrawCommand(_trackItem, true);
          }
        }
        else
        {
          // Do not change _selected status
          _dismissTransfer = false;
        }
      }
    }
Beispiel #4
0
    protected MenuCommand InternalTrackPopup(Point screenPosTR, Point screenPosTL, 
      MenuCommandCollection menuCollection, 
      PopupMenu parentMenu, bool selectFirst, 
      MenuControl parentControl, bool popupRight,
      bool popupDown, ref int returnDir)
    {
      // Default the drawing direction
      direction = Direction.Horizontal;

      // Remember the MenuControl that initiated us
      parentControl = parentControl;

      // We have a parent popup menu that should be consulted about operation
      parentMenu = parentMenu;

      // Remember any currect menu item collection
      MenuCommandCollection oldCollection =  menuCommands;

      // Use the passed in collection of menu commands
      menuCommands = menuCollection;

      // Remember screen positions
      screenPos = screenPosTR;
      aboveScreenPos = screenPosTR;
      leftScreenPos = screenPosTL;

      // Remember display directions
      popupRight = popupRight;
      popupDown = popupDown;

      MenuCommand ret = InternalTrackPopup(selectFirst);

      // Restore to original collection
      menuCommands = oldCollection;

      // Remove references no longer required
      parentControl = null;
      parentMenu = null;

      // Return the direction key that caused dismissal
      returnDir =  returnDir;

      return ret;
    }
Beispiel #5
0
    protected void OperateSubMenu(int popupItem, bool selectFirst)
    {
      popupItem = popupItem;
      childMenu = new PopupMenu();

      DrawCommand dc =  drawCommands[popupItem] as DrawCommand;

      // Find screen coordinate of Top right of item cell
      Win32.POINT screenPosTR;
      screenPosTR.x = dc.DrawRect.Right;
      screenPosTR.y = dc.DrawRect.Top;
      WindowsAPI.ClientToScreen(this.Handle, ref screenPosTR);
      
      // Find screen coordinate of top left of item cell
      Win32.POINT screenPosTL;
      screenPosTL.x = dc.DrawRect.Left;
      screenPosTL.y = dc.DrawRect.Top;
      WindowsAPI.ClientToScreen(this.Handle, ref screenPosTL);

      // Ensure the child has the same properties as ourself
      childMenu.Style = this.Style;
      childMenu.Font = this.Font;

      // Record keyboard direction
      int returnDir = 0;

      returnCommand =  childMenu.InternalTrackPopup(new Point(screenPosTR.x, screenPosTR.y),
        new Point(screenPosTL.x, screenPosTL.y), 
        dc.MenuCommand.MenuCommands, 
        this, 
        selectFirst,
        parentControl,
        popupRight,
        popupDown,
        ref returnDir);

      popupItem = -1;;
      childMenu = null;

      if (( returnCommand != null) || (returnDir != 0))
      {
        // Finish processing messages
        timer.Stop();
        exitLoop = true;  
        returnDir = returnDir;
      }
    }
Beispiel #6
0
    public PopupMenu()
    {
      // Create collection objects
      drawCommands = new ArrayList();
      menuCommands = new MenuCommandCollection(); 

      // Default the properties
      returnDir = 0;
      extraSize = 0;
      popupItem = -1;
      trackItem = -1;
      childMenu = null;
      exitLoop = false;
      popupDown = true;
      mouseOver = false;
      grabFocus = false;
      excludeTop = true;
      popupRight = true;
      parentMenu = null;
      excludeOffset = 0;
      focusCatcher = null;
      parentControl = null;
      returnCommand = null;
      oldFocus = IntPtr.Zero;
      showInfrequent = false;
      style = VisualStyle.IDE;
      lastMousePos = new Point(-1,-1);
      direction = Direction.Horizontal;
      textFont = SystemInformation.MenuFont;

      // Create and initialise the timer object (but do not start it running!)
      timer = new Timer();
      timer.Interval = selectionDelay;
      timer.Tick += new EventHandler(OnTimerExpire);
    }