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 CollectionWithEvents.CollectionClear(OnCollectionCleared); _menuCommands.Inserted += new CollectionWithEvents.CollectionChange(OnCollectionInserted); _menuCommands.Removed += new CollectionWithEvents.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); }
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); }
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; } } }
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; }
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; } }
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); }