Esempio n. 1
0
		internal void DrawSingleCommand(Graphics g, DrawCommand dc, bool tracked)
		{
			Rectangle drawRect = dc.DrawRect;
			MenuCommand mc = dc.MenuCommand;

			// Copy the rectangle used for drawing cell
			Rectangle shadowRect = drawRect;

			// Expand to right and bottom to cover the area used to draw shadows
			shadowRect.Width += _shadowGap;
			shadowRect.Height += _shadowGap;

			// Draw background color over cell and shadow area to the right
			using (SolidBrush back = new SolidBrush(SystemColors.Control))
				g.FillRectangle(back, shadowRect);

			if (!dc.Separator)
			{
				Rectangle textRect;

				// Text rectangle size depends on type of draw command we are drawing
				if (dc.Chevron)
				{
					// Create chevron drawing rectangle
					textRect = new Rectangle(drawRect.Left + _lengthGap, drawRect.Top + _boxExpandUpper,
											 drawRect.Width - _lengthGap * 2, drawRect.Height - (_boxExpandUpper * 2));
				}
				else
				{
					// Create text drawing rectangle
					textRect = new Rectangle(drawRect.Left + _lengthGap, drawRect.Top + _lengthGap,
											 drawRect.Width - _lengthGap * 2, drawRect.Height - _lengthGap * 2);
				}

				if (dc.Enabled)
				{
					// Draw selection
					if (tracked)
					{
						Rectangle boxRect;

						// Create the rectangle for box around the text
						if (_direction == Direction.Horizontal)
						{
							boxRect = new Rectangle(textRect.Left - _boxExpandSides,
													textRect.Top - _boxExpandUpper,
													textRect.Width + _boxExpandSides * 2,
													textRect.Height + _boxExpandUpper);
						}
						else
						{
							if (!dc.Chevron)
							{
								boxRect = new Rectangle(textRect.Left,
														textRect.Top - _boxExpandSides,
														textRect.Width - _boxExpandSides,
														textRect.Height + _boxExpandSides * 2);
							}
							else
								boxRect = textRect;
						}

						switch (_style)
						{
							case VisualStyle.IDE:
								if (_selected)
								{
									// Fill the entire inside
									g.FillRectangle(SystemBrushes.ControlLight, boxRect);

								int rightLeft = boxRect.Right + 1;
									int rightBottom = boxRect.Bottom;

								if (_drawUpwards && (_direction == Direction.Horizontal))
									{
										// Draw the box around the selection area
										using (Pen dark = new Pen(SystemColors.ControlDark))
											g.DrawRectangle(dark, boxRect.Left, boxRect.Top - _shadowGap,
															  boxRect.Width, boxRect.Height + _shadowGap);

										// Remove the top line of the selection area
										using (Pen dark = new Pen(SystemColors.ControlLight))
											g.DrawLine(dark, boxRect.Left + 1, boxRect.Top, boxRect.Right - 2, boxRect.Top);

										int rightTop = boxRect.Top;
										//int leftLeft = boxRect.Left + _shadowGap;

										SolidBrush shadowBrush = null;
										try
										{
											// Decide if we need to use an alpha brush
											if (_supportsLayered && (_style == VisualStyle.IDE))
												shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
											else
												shadowBrush = new SolidBrush(SystemColors.ControlDark);

											g.FillRectangle(shadowBrush, new Rectangle(rightLeft, rightTop + _shadowGap - 1, _shadowGap, rightBottom - rightTop - _shadowGap * 2));
										}
										finally
										{
											shadowBrush.Dispose();
										}
								}
								else
								{
									// Draw the box around the selection area
									using(Pen dark = new Pen(SystemColors.ControlDark))
										g.DrawRectangle(dark, boxRect);

									if (_direction == Direction.Horizontal)
									{
										// Remove the bottom line of the selection area
										using(Pen dark = new Pen(SystemColors.ControlLight))
											g.DrawLine(dark, boxRect.Left, boxRect.Bottom, boxRect.Right, boxRect.Bottom);

										int rightTop = boxRect.Top + _shadowYOffset;

										SolidBrush shadowBrush = null;
										try
										{
											// Decide if we need to use an alpha brush
											if (_supportsLayered && (_style == VisualStyle.IDE))
												shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
											else
												shadowBrush = new SolidBrush(SystemColors.ControlDark);

											g.FillRectangle(shadowBrush, new Rectangle(rightLeft, rightTop, _shadowGap, rightBottom - rightTop));
										}
										finally
										{
											shadowBrush.Dispose();
										}
									}
									else
									{
										// Remove the right line of the selection area
										using(Pen dark = new Pen(SystemColors.ControlLight))
											g.DrawLine(dark, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);

										int leftLeft = boxRect.Left + _shadowYOffset;

										SolidBrush shadowBrush = null;
										try
										{
											// Decide if we need to use an alpha brush
											if (_supportsLayered && (_style == VisualStyle.IDE))
												shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
											else
												shadowBrush = new SolidBrush(SystemColors.ControlDark);

											g.FillRectangle(shadowBrush, new Rectangle(leftLeft, rightBottom + 1, rightBottom - leftLeft - _shadowGap, _shadowGap));
										}
										finally
										{
											shadowBrush.Dispose();
										}
									}
								}
							}
							else
							{
								using (Pen selectPen = new Pen(ColorUtil.VSNetBorderColor))
								{
									// Draw the selection area in white so can alpha draw over the top
									using (SolidBrush whiteBrush = new SolidBrush(Color.White))
										g.FillRectangle(whiteBrush, boxRect);

									using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70, ColorUtil.VSNetBorderColor)))
									{
										// Draw the selection area
										g.FillRectangle(selectBrush, boxRect);

										// Draw a border around the selection area
										g.DrawRectangle(selectPen, boxRect);
									}
								}
							}
							break;
						case VisualStyle.Plain:
							if (_plainAsBlock)
							{
								using (SolidBrush selectBrush = new SolidBrush(ColorUtil.VSNetBorderColor))
									g.FillRectangle(selectBrush, drawRect);
							}
							else
							{
								using(Pen lighlight = new Pen(SystemColors.ControlLightLight),
										  dark = new Pen(SystemColors.ControlDark))
								{
									if (_selected)
									{
										g.DrawLine(dark, boxRect.Left, boxRect.Bottom, boxRect.Left, boxRect.Top);
										g.DrawLine(dark, boxRect.Left, boxRect.Top, boxRect.Right, boxRect.Top);
										g.DrawLine(lighlight, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);
										g.DrawLine(lighlight, boxRect.Right, boxRect.Bottom, boxRect.Left, boxRect.Bottom);
									}
									else
									{
										g.DrawLine(lighlight, boxRect.Left, boxRect.Bottom, boxRect.Left, boxRect.Top);
										g.DrawLine(lighlight, boxRect.Left, boxRect.Top, boxRect.Right, boxRect.Top);
										g.DrawLine(dark, boxRect.Right, boxRect.Top, boxRect.Right, boxRect.Bottom);
										g.DrawLine(dark, boxRect.Right, boxRect.Bottom, boxRect.Left, boxRect.Bottom);
									}
								}
							}
							break;
						}
					}
				}

				if (dc.Chevron)
				{
					// Draw the chevron image in the centre of the text area
					int yPos = drawRect.Top;
					int xPos = drawRect.X + ((drawRect.Width - _chevronLength) / 2);

					// When selected...
					if (_selected)
					{
						// ...offset down and to the right
						xPos += 1;
						yPos += 1;
					}

					g.DrawImage(_menuImages.Images[_chevronIndex], xPos, yPos);
				}
				else
				{
					// Left align the text drawing on a single line centered vertically
					// and process the & character to be shown as an underscore on next character
					using (StringFormat format = new StringFormat())
					{
						format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
						format.Alignment = StringAlignment.Center;
						format.LineAlignment = StringAlignment.Center;
						format.HotkeyPrefix = HotkeyPrefix.Show;

						if (_direction == Direction.Vertical)
							format.FormatFlags |= StringFormatFlags.DirectionVertical;


						if (dc.Enabled)
						{
							if (tracked && (_style == VisualStyle.Plain) && _plainAsBlock)
							{
								// Is the item selected as well as tracked?
								if (_selected)
								{
									// Offset to show it is selected
									textRect.X += 2;
									textRect.Y += 2;
								}

								using (SolidBrush textBrush = new SolidBrush(SystemColors.HighlightText))
									g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
							}
							else
								using (SolidBrush textBrush = new SolidBrush(SystemColors.MenuText))
									g.DrawString(mc.Text, this.Font, textBrush, textRect, format);
						}
						else
						{
							// Helper values used when drawing grayed text in plain style
							Rectangle rectDownRight = textRect;
							rectDownRight.Offset(1,1);

							// Draw then text offset down and right
							using (SolidBrush whiteBrush = new SolidBrush(SystemColors.HighlightText))
								g.DrawString(mc.Text, this.Font, whiteBrush, rectDownRight, format);

							// Draw then text offset up and left
							using (SolidBrush grayBrush = new SolidBrush(SystemColors.GrayText))
								g.DrawString(mc.Text, this.Font, grayBrush, textRect, format);
						}
					}
				}
			}
		}
Esempio n. 2
0
		internal void DrawSingleCommand(Graphics g, DrawCommand dc, bool hotCommand)
		{
			Rectangle drawRect = dc.DrawRect;
			MenuCommand mc = dc.MenuCommand;

			// Remember some often used values
			int textGapLeft = _position[(int)_style, (int)PI.TextGapLeft];
			int imageGapLeft = _position[(int)_style, (int)PI.ImageGapLeft];
			int imageGapRight = _position[(int)_style, (int)PI.ImageGapRight];
			int imageLeft = drawRect.Left + imageGapLeft;

			// Calculate some common values
			int imageColWidth = imageGapLeft + _imageWidth + imageGapRight;

//			int subMenuWidth = _position[(int)_style, (int)PI.SubMenuGapLeft] +
//							   _position[(int)_style, (int)PI.SubMenuWidth] +
//							   _position[(int)_style, (int)PI.SubMenuGapRight];

			int subMenuX = drawRect.Right -
						   _position[(int)_style, (int)PI.SubMenuGapRight] -
						   _position[(int)_style, (int)PI.SubMenuWidth];

			// Text drawing rectangle needs to know the right most position for drawing
			// to stop. This is the width of the window minus the relevant values
			int shortCutX = subMenuX -
							_position[(int)_style, (int)PI.SubMenuGapLeft] -
							_position[(int)_style, (int)PI.TextGapRight];

			// Is this item an expansion command?
			if (dc.Expansion)
			{
				Rectangle box = drawRect;

				// In IDE style the box is next to the image column
				if (_style == VisualStyle.IDE)
				{
					// Reduce the box to take into account the column
					box.X += imageColWidth;
					box.Width -= imageColWidth;
				}

				// Find centre for drawing the image
				int xPos = box.Left + ((box.Width - _imageHeight) / 2);
				;
				int yPos = box.Top + ((box.Height - _imageHeight) / 2);

				switch(_style)
				{
				case VisualStyle.IDE:
					g.FillRectangle(SystemBrushes.ControlLightLight, box);
					break;
				case VisualStyle.Plain:
					g.FillRectangle(SystemBrushes.Control, box);
					break;
				}

				// Should the item look selected
				if (hotCommand)
				{
					switch(_style)
					{
					case VisualStyle.IDE:
						Rectangle selectArea = new Rectangle(drawRect.Left + 1, drawRect.Top,
															 drawRect.Width - 3, drawRect.Height - 1);

						using (Pen selectPen = new Pen(ColorUtil.VSNetBorderColor))
						{
							// Draw the selection area white, because we are going to use an alpha brush
							using (SolidBrush whiteBrush = new SolidBrush(Color.White))
								g.FillRectangle(whiteBrush, selectArea);

							using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70,ColorUtil.VSNetBorderColor)))
							{
								// Draw the selection area
								g.FillRectangle(selectBrush, selectArea);

								// Draw a border around the selection area
								g.DrawRectangle(selectPen, selectArea);
							}
						}
						break;
					case VisualStyle.Plain:
						// Shrink the box to provide a small border
						box.Inflate(-2, -2);

						// Grab common values
						//Color baseColor = SystemColors.Control;

						using (Pen lightPen = new Pen(SystemColors.ControlLightLight),
								   darkPen = new Pen(SystemColors.ControlDarkDark))
						{
							g.DrawLine(lightPen, box.Right, box.Top, box.Left, box.Top);
							g.DrawLine(lightPen, box.Left, box.Top, box.Left, box.Bottom);
							g.DrawLine(darkPen, box.Left, box.Bottom, box.Right, box.Bottom);
							g.DrawLine(darkPen, box.Right, box.Bottom, box.Right, box.Top);
						}
						break;
					}
				}
				else
				{
					switch(_style)
					{
					case VisualStyle.IDE:
						// Fill the entire drawing area with white
						using (SolidBrush whiteBrush = new SolidBrush(SystemColors.ControlLightLight))
							g.FillRectangle(whiteBrush, new Rectangle(drawRect.Left + 1, drawRect.Top,
																	  drawRect.Width - 1, drawRect.Height));

						Rectangle imageCol = new Rectangle(drawRect.Left, drawRect.Top,
														   imageColWidth, drawRect.Height);

						// Draw the image column background
						g.FillRectangle(SystemBrushes.Control, imageCol);
						break;
					case VisualStyle.Plain:
							g.FillRectangle(SystemBrushes.Control, new Rectangle(drawRect.Left, drawRect.Top,
																				 drawRect.Width, drawRect.Height));
						break;
					}

				}

				// Always draw the expansion bitmap
				g.DrawImage(_menuImages.Images[(int)ImageIndex.Expansion], xPos, yPos);
			}
			else
			{
				// Is this item a separator?
				if (dc.Separator)
				{
					if (dc.VerticalSeparator)
					{
						switch(_style)
						{
						case VisualStyle.IDE:
							// Draw the separator as a single line
							using (Pen separatorPen = new Pen(SystemColors.ControlDark))
								g.DrawLine(separatorPen, drawRect.Left, drawRect.Top, drawRect.Left, drawRect.Bottom);
							break;
						case VisualStyle.Plain:
							Color baseColor = SystemColors.Control;
							ButtonBorderStyle bsInset = ButtonBorderStyle.Inset;
							ButtonBorderStyle bsNone = ButtonBorderStyle.Inset;

							Rectangle sepRect = new Rectangle(drawRect.Left + 1, drawRect.Top, 2, drawRect.Height);

							// Draw the separator as two lines using Inset style
							ControlPaint.DrawBorder(g, sepRect,
													baseColor, 1, bsInset, baseColor, 0, bsNone,
													baseColor, 1,
								bsInset, baseColor, 0, bsNone);
							break;
						}
					}
					else
					{
						switch(_style)
						{
						case VisualStyle.IDE:
							// Draw the image column background
							Rectangle imageCol = new Rectangle(drawRect.Left, drawRect.Top,
															   imageColWidth,
															   drawRect.Height);

							g.FillRectangle(new SolidBrush(ColorUtil.VSNetBackgroundColor), drawRect);
							g.FillRectangle(new SolidBrush(ColorUtil.VSNetControlColor), imageCol);

							// Draw a separator
							using (Pen separatorPen = new Pen(Color.FromArgb(75, SystemColors.MenuText)))
							{
								// Draw the separator as a single line
								g.DrawLine(separatorPen, drawRect.Left + imageColWidth + textGapLeft, drawRect.Top + 1,
										   drawRect.Right-4, drawRect.Top + 1);

							}
							break;
						case VisualStyle.Plain:
							Color baseColor = SystemColors.Control;
							ButtonBorderStyle bsInset = ButtonBorderStyle.Inset;
							ButtonBorderStyle bsNone = ButtonBorderStyle.Inset;

							Rectangle sepRect = new Rectangle(drawRect.Left + 2, drawRect.Top + 1,
															  drawRect.Width - 4, 2);

							// Draw the separator as two lines using Inset style
							ControlPaint.DrawBorder(g, sepRect,
													baseColor, 0, bsNone, baseColor, 1, bsInset,
													baseColor, 0,
								bsNone, baseColor, 1, bsInset);
							break;
						}
					}
				}
				else
				{
					// Should the command be drawn selected?
					if (hotCommand && mc.ComboBox == null )
					{
						switch(_style)
						{
						case VisualStyle.IDE:
							Rectangle selectArea = new Rectangle(drawRect.Left + 1, drawRect.Top,
																 drawRect.Width - 3, drawRect.Height - 1);

							using (Pen selectPen = new Pen(ColorUtil.VSNetBorderColor))
							{
								// Draw the selection area white, because we are going to use an alpha brush
								using (SolidBrush whiteBrush = new SolidBrush(Color.White))
									g.FillRectangle(whiteBrush, selectArea);

								using (SolidBrush selectBrush = new SolidBrush(Color.FromArgb(70, ColorUtil.VSNetBorderColor)))
								{
									// Draw the selection area
									g.FillRectangle(selectBrush, selectArea);

									// Draw a border around the selection area
									g.DrawRectangle(selectPen, selectArea);
								}
							}
							break;
						case VisualStyle.Plain:
							using (SolidBrush selectBrush = new SolidBrush(ColorUtil.VSNetBorderColor))
								g.FillRectangle(selectBrush, drawRect);
							break;
						}
					}
					else
					{
						switch(_style)
						{
						case VisualStyle.IDE:
							// Fill the entire drawing area with white
							using (SolidBrush whiteBrush = new SolidBrush(ColorUtil.VSNetBackgroundColor))
								g.FillRectangle(whiteBrush, new Rectangle(drawRect.Left + 1, drawRect.Top,
																		  drawRect.Width - 1, drawRect.Height));

							Rectangle imageCol = new Rectangle(drawRect.Left, drawRect.Top,
															   imageColWidth, drawRect.Height);

							// Draw the image column background
							g.FillRectangle(new SolidBrush(ColorUtil.VSNetControlColor), imageCol);

							// If this is a combobox item, make sure to position the combobox a couple
							// of pixel after the icon area
							if ( mc.ComboBox != null )
							{
								// Combobox will paint itself
								mc.ComboBox.Left = drawRect.Left+imageColWidth + 2;
								mc.ComboBox.Top = drawRect.Top + (drawRect.Height - mc.ComboBox.Height)/2;

							}

							break;
						case VisualStyle.Plain:
							g.FillRectangle(SystemBrushes.Control, new Rectangle(drawRect.Left, drawRect.Top,
																				 drawRect.Width, drawRect.Height));
							break;
						}
					}

					int leftPos = drawRect.Left + imageColWidth + textGapLeft;

					// Calculate text drawing rectangle
					Rectangle strRect = new Rectangle(leftPos, drawRect.Top, shortCutX - leftPos, drawRect.Height);

					// Left align the text drawing on a single line centered vertically
					// and process the & character to be shown as an underscore on next character
					using (StringFormat format = new StringFormat())
					{
					format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
					format.Alignment = StringAlignment.Near;
					format.LineAlignment = StringAlignment.Center;
					format.HotkeyPrefix = HotkeyPrefix.Show;

						SolidBrush textBrush = null;
						try
						{
					// Create brush depending on enabled state
					if (mc.Enabled)
					{
						if (!hotCommand || (_style == VisualStyle.IDE))
							textBrush = new SolidBrush(SystemColors.MenuText);
						else
							textBrush = new SolidBrush(SystemColors.HighlightText);
					}
					else
						textBrush = new SolidBrush(SystemColors.GrayText);

					// Helper values used when drawing grayed text in plain style
					Rectangle rectDownRight = strRect;
					rectDownRight.Offset(1,1);

					if (mc.Enabled || (_style == VisualStyle.IDE))
						g.DrawString(mc.Text, _textFont, textBrush, strRect, format);
					else
					{
						// Draw grayed text by drawing white string offset down and right
						using (SolidBrush whiteBrush = new SolidBrush(SystemColors.HighlightText))
							g.DrawString(mc.Text, _textFont, whiteBrush, rectDownRight, format);

						// And then draw in corret color offset up and left
						g.DrawString(mc.Text, _textFont, textBrush, strRect, format);
					}

					if (mc.Shortcut != Shortcut.None)
					{
						// Right align the shortcut drawing
						format.Alignment = StringAlignment.Far;

						if (mc.Enabled || (_style == VisualStyle.IDE))
						{
							// Draw the shortcut text
							g.DrawString(GetShortcutText(mc.Shortcut), _textFont, textBrush, strRect, format);
						}
						else
						{
							// Draw grayed text by drawing white string offset down and right
							using (SolidBrush whiteBrush = new SolidBrush(SystemColors.HighlightText))
								g.DrawString(GetShortcutText(mc.Shortcut), _textFont, whiteBrush, rectDownRight, format);

							// And then draw in corret color offset up and left
							g.DrawString(GetShortcutText(mc.Shortcut), _textFont, textBrush, strRect, format);
						}
					}
						}
						finally
						{
							textBrush.Dispose();
						}
					}

					// The image offset from top of cell is half the space left after
					// subtracting the height of the image from the cell height
					int imageTop = drawRect.Top + (drawRect.Height - _imageHeight) / 2;

					Image image = null;

					// Should a check mark be drawn?
					if (mc.Checked)
					{
						switch(_style)
						{
						case VisualStyle.IDE:
								using (Pen boxPen = mc.Enabled ?
									new Pen(ColorUtil.VSNetBorderColor) :
									new Pen(SystemColors.GrayText))
								{
							// Draw the box around the checkmark area
							g.DrawRectangle(boxPen, new Rectangle(imageLeft - 1, imageTop - 1,
																  _imageHeight + 2, _imageWidth + 2));
								}
							break;
						case VisualStyle.Plain:
							break;
						}

						// Grab either tick or radio button image
						if (mc.RadioCheck)
						{
							if (hotCommand && (_style == VisualStyle.Plain))
								image = _menuImages.Images[(int)ImageIndex.RadioSelected];
							else
								image = _menuImages.Images[(int)ImageIndex.Radio];
						}
						else
						{
							if (hotCommand && (_style == VisualStyle.Plain))
								image = _menuImages.Images[(int)ImageIndex.CheckSelected];
							else
								image = _menuImages.Images[(int)ImageIndex.Check];
						}
					}
					else
					{
						try
						{
							// Is there an image available to be drawn?
							if ((mc.ImageList != null) && (mc.ImageIndex >= 0))
								image = mc.ImageList.Images[mc.ImageIndex];
							else if ( mc.Image != null)
								image = mc.Image;
						}
						catch(Exception)
						{
							// User supplied ImageList/ImageIndex are invalid, use an error image instead
							image = _menuImages.Images[(int)ImageIndex.ImageError];
						}
					}

					// Is there an image to be drawn?
					if (image != null)
					{
						if (mc.Enabled)
						{
							if ((hotCommand) && (!mc.Checked) && (_style == VisualStyle.IDE))
							{
								// Draw a disabled icon offset down and right
								ControlPaint.DrawImageDisabled(g, image, imageLeft + 1, imageTop + 1,
															   SystemColors.HighlightText);

								// Draw an enabled icon offset up and left
								g.DrawImage(image, imageLeft - 1, imageTop - 1);
							}
							else
							{
								// Draw an enabled icon
								g.DrawImage(image, imageLeft, imageTop);
							}
						}
						else
						{
							// Draw a image disabled
							ControlPaint.DrawImageDisabled(g, image, imageLeft, imageTop,
														   SystemColors.HighlightText);
						}
					}

					// Does the menu have a submenu defined?
					if (dc.SubMenu)
					{
						// Is the item enabled?
						if (mc.Enabled)
						{
							int subMenuIndex = (int)ImageIndex.SubMenu;

							if (hotCommand && (_style == VisualStyle.Plain))
								subMenuIndex = (int)ImageIndex.SubMenuSelected;

							// Draw the submenu arrow
							g.DrawImage(_menuImages.Images[subMenuIndex], subMenuX, imageTop);
						}
						else
						{
							// Draw a image disabled
							ControlPaint.DrawImageDisabled(g, _menuImages.Images[(int)ImageIndex.SubMenu],
														   subMenuX, imageTop, SystemColors.HighlightText);
						}
					}
				}
			}
		}
Esempio n. 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;
				}
			}
		}
Esempio n. 4
0
		protected Size GenerateDrawPositions()
		{
			// Create a collection of drawing objects
			_drawCommands = new ArrayList();

			// Calculate the minimum cell width and height
			int cellMinHeight = _position[(int)_style, (int)PI.ImageGapTop] +
								_imageHeight +
								_position[(int)_style, (int)PI.ImageGapBottom];

			int cellMinWidth = _position[(int)_style, (int)PI.ImageGapLeft] +
							   _imageWidth +
							   _position[(int)_style, (int)PI.ImageGapRight] +
							   _position[(int)_style, (int)PI.TextGapLeft] +
							   _position[(int)_style, (int)PI.TextGapRight] +
							   _position[(int)_style, (int)PI.SubMenuGapLeft] +
							   _position[(int)_style, (int)PI.SubMenuWidth] +
							   _position[(int)_style, (int)PI.SubMenuGapRight];

			// Find cell height needed to draw text
			int textHeight = _textFont.Height;

			// If height needs to be more to handle image then use image height
			if (textHeight < cellMinHeight)
				textHeight = cellMinHeight;

			// Make sure no column in the menu is taller than the screen
			int screenHeight = SystemInformation.WorkingArea.Height;

			// Define the starting positions for calculating cells
			int xStart = _position[(int)_style, (int)PI.BorderLeft];
			int yStart =_position[(int)_style, (int)PI.BorderTop];
			int yPosition = yStart;

			// Largest cell for column defaults to minimum cell width
			int xColumnMaxWidth = cellMinWidth;

			int xPreviousColumnWidths = 0;
			int xMaximumColumnHeight = 0;

			// Track the row/col of each cell
			int row = 0;
			int col = 0;

			// Are there any infrequent items
			bool infrequent = false;

			// Get hold of the DC for the desktop
			IntPtr hDC = WindowsAPI.GetDC(IntPtr.Zero);

			// Contains the collection of items in the current column
			ArrayList columnItems = new ArrayList();

			using(Graphics g = Graphics.FromHdc(hDC))
			{
				// Handle any extra text drawing
				if (_menuCommands.ExtraText.Length > 0)
				{
					// Calculate the column width needed to show this text
					SizeF dimension = g.MeasureString(_menuCommands.ExtraText, _menuCommands.ExtraFont);

					// Always add 1 to ensure that rounding is up and not down
					int extraHeight = (int)dimension.Height + 1;

					// Find the total required as the text requirement plus style specific spacers
					_extraSize = extraHeight +
								 _position[(int)_style, (int)PI.ExtraRightGap] +
								 _position[(int)_style, (int)PI.ExtraWidthGap] * 2;

					// Push first column of items across from the extra text
					xStart += _extraSize;

					// Add this extra width to the total width of the window
					xPreviousColumnWidths = _extraSize;
				}

				foreach(MenuCommand command in _menuCommands)
				{
					// Give the command a chance to update its state
					command.OnUpdate(EventArgs.Empty);

					// Ignore items that are marked as hidden
					if (!command.Visible)
						continue;

					// If this command has menu items (and so it a submenu item) then check
					// if any of the submenu items are visible. If none are visible then there
					// is no point in showing this submenu item
					if ((command.MenuCommands.Count > 0) && (!command.MenuCommands.VisibleItems()))
						continue;

					// Ignore infrequent items unless flag set to show them
					if (command.Infrequent && !_showInfrequent)
					{
						infrequent = true;
						continue;
					}

					int cellWidth = 0;
					int cellHeight = 0;

					// Shift across to the next column?
					if (command.Break)
					{
						// Move row/col tracking to the next column
						row = 0;
						col++;

						// Apply cell width to the current column entries
						ApplySizeToColumnList(columnItems, xColumnMaxWidth);

						// Move cell position across to start of separator position
						xStart += xColumnMaxWidth;

						// Get width of the separator area
						int xSeparator = _position[(int)_style, (int)PI.SeparatorWidth];

						DrawCommand dcSep = new DrawCommand(new Rectangle(xStart, 0, xSeparator, 0), false);

						// Add to list of items for drawing
						_drawCommands.Add(dcSep);

						// Move over the separator
						xStart += xSeparator;

						// Reset cell position to top of column
						yPosition = yStart;

						// Accumulate total width of previous columns
						xPreviousColumnWidths += xColumnMaxWidth + xSeparator;

						// Largest cell for column defaults to minimum cell width
						xColumnMaxWidth  = cellMinWidth;
					}

					// Is this a horizontal separator?
					if (command.Text == "-")
					{
						cellWidth = cellMinWidth;
						cellHeight = _position[(int)_style, (int)PI.SeparatorHeight];
					}
					else
					{
						// Use precalculated height
						cellHeight = textHeight;

						// Calculate the text width portion of the cell
						SizeF dimension = g.MeasureString(command.Text, _textFont);

						// Always add 1 to ensure that rounding is up and not down
						cellWidth = cellMinWidth + (int)dimension.Width + 1;

						// Does the menu command have a shortcut defined?
						if (command.Shortcut != Shortcut.None)
						{
							// Find the width of the shortcut text
							dimension = g.MeasureString(GetShortcutText(command.Shortcut), _textFont);

							// Add to the width of the cell
							cellWidth += _position[(int)_style, (int)PI.ShortcutGap] + (int)dimension.Width + 1;
						}

						// If this is a combobox, then add the combobox dimension
						if ( command.ComboBox != null )
						{
							cellWidth += command.ComboBox.Width;
						}
					}

					// If the new cell expands past the end of the screen...
					if ((yPosition + cellHeight) >= screenHeight)
					{
						// .. then need to insert a column break

						// Move row/col tracking to the next column
						row = 0;
						col++;

						// Apply cell width to the current column entries
						ApplySizeToColumnList(columnItems, xColumnMaxWidth);

						// Move cell position across to start of separator position
						xStart += xColumnMaxWidth;

						// Get width of the separator area
						int xSeparator = _position[(int)_style, (int)PI.SeparatorWidth];

						DrawCommand dcSep = new DrawCommand(new Rectangle(xStart, yStart, xSeparator, 0), false);

						// Add to list of items for drawing
						_drawCommands.Add(dcSep);

						// Move over the separator
						xStart += xSeparator;

						// Reset cell position to top of column
						yPosition = yStart;

						// Accumulate total width of previous columns
						xPreviousColumnWidths += xColumnMaxWidth + xSeparator;

						// Largest cell for column defaults to minimum cell width
						xColumnMaxWidth  = cellMinWidth;
					}

					// Create a new position rectangle (the width will be reset later once the
					// width of the column has been determined but the other values are correct)
					Rectangle cellRect = new Rectangle(xStart, yPosition, cellWidth, cellHeight);

					// Create a drawing object
					DrawCommand dc = new DrawCommand(command, cellRect, row, col);

					// Add to list of items for drawing
					_drawCommands.Add(dc);

					// Add to list of items in this column
					columnItems.Add(dc);

					// Remember the biggest cell width in this column
					if (cellWidth > xColumnMaxWidth)
						xColumnMaxWidth = cellWidth;

					// Move down to start of next cell in column
					yPosition += cellHeight;

					// Remember the tallest column in the menu
					if (yPosition > xMaximumColumnHeight)
						xMaximumColumnHeight = yPosition;

					row++;
				}

				// Check if we need to add an infrequent expansion item
				if (infrequent)
				{
					// Create a minimum size cell
					Rectangle cellRect = new Rectangle(xStart, yPosition, cellMinWidth, cellMinHeight);

					// Create a draw command to represent the drawing of the expansion item
					DrawCommand dc = new DrawCommand(cellRect, true);

					// Must be last item
					_drawCommands.Add(dc);

					// Add to list of items in this column
					columnItems.Add(dc);

					yPosition += cellMinHeight;

					// Remember the tallest column in the menu
					if (yPosition > xMaximumColumnHeight)
						xMaximumColumnHeight = yPosition;
				}

				// Apply cell width to the current column entries
				ApplySizeToColumnList(columnItems, xColumnMaxWidth);
			}

			// Must remember to release the HDC resource!
			WindowsAPI.ReleaseDC(IntPtr.Zero, hDC);

			// Find width/height of window
			int windowWidth = _position[(int)_style, (int)PI.BorderLeft] +
							  xPreviousColumnWidths +
							  xColumnMaxWidth +
							  _position[(int)_style, (int)PI.BorderRight];

			int windowHeight = _position[(int)_style, (int)PI.BorderTop] +
							  xMaximumColumnHeight +
							  _position[(int)_style, (int)PI.BorderBottom];

			// Define the height of the vertical separators
			ApplyVerticalSeparators(xMaximumColumnHeight);

			// Style specific modification of window size
			int xAdd = _position[(int)_style, (int)PI.ShadowHeight];
			int yAdd = _position[(int)_style, (int)PI.ShadowWidth];

			if (_style == VisualStyle.Plain)
			{
				xAdd += SystemInformation.Border3DSize.Width * 2;
				yAdd += SystemInformation.Border3DSize.Height * 2;
			}

			return new Size(windowWidth + xAdd, windowHeight + yAdd);
		}