Inheritance: System.Windows.Forms.NativeWindow, IDisposable
Example #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 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);
		}
Example #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);
		}
Example #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;
				}
			}
		}
Example #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;
		}
Example #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;
			}
		}
Example #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);
		}