⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 popupmenu.cs

📁 c#编写的仿OUTLOOK工具条的Winform菜单
💻 CS
📖 第 1 页 / 共 5 页
字号:
					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);
		}

		protected void ApplyVerticalSeparators(int sepHeight)
		{
			// Each vertical separator needs to be the same height, this has already 
			// been calculated and passed in from the tallest column in the menu
			foreach(DrawCommand dc in _drawCommands)
			{
				if (dc.VerticalSeparator)
				{
					// Grab the current drawing rectangle
					Rectangle cellRect = dc.DrawRect;

					// Modify the height to that requested
					dc.DrawRect = new Rectangle(cellRect.Left, cellRect.Top, cellRect.Width, sepHeight);
				}
			}
		}

		protected void ApplySizeToColumnList(ArrayList columnList, int cellWidth)
		{
			// Each cell in the same column needs to be the same width, this has already
			// been calculated and passed in as the widest cell in the column
			foreach(DrawCommand dc in columnList)
			{
				// Grab the current drawing rectangle
				Rectangle cellRect = dc.DrawRect;

				// Modify the width to that requested
				dc.DrawRect = new Rectangle(cellRect.Left, cellRect.Top, cellWidth, cellRect.Height);
			}

			// Clear collection out ready for reuse
			columnList.Clear();
		}

		protected void RefreshAllCommands()
		{
			Win32.RECT rectRaw = new Win32.RECT();

			// Grab the screen rectangle of the window
			WindowsAPI.GetWindowRect(this.Handle, ref rectRaw);

			// Convert from screen to client sizing
			Rectangle rectWin = new Rectangle(0, 0, 
											  rectRaw.right - rectRaw.left, 
											  rectRaw.bottom - rectRaw.top);

			using(Graphics g = Graphics.FromHwnd(this.Handle))
			{
				// Draw the background area
				DrawBackground(g, rectWin);

				// Draw the actual menu items
				DrawAllCommands(g);
			}
		}

		protected void DrawBackground(Graphics g, Rectangle rectWin)
		{ 
			Rectangle main = new Rectangle(0, 0, 
										   rectWin.Width - 1 - _position[(int)_style, (int)PI.ShadowWidth], 
										   rectWin.Height - 1 - _position[(int)_style, (int)PI.ShadowHeight]);

			// Style specific drawing
			switch(_style)
			{
			case VisualStyle.IDE:
				// Calculate some common values
				int imageColWidth = _position[(int)_style, (int)PI.ImageGapLeft] + 
									_imageWidth + 
									_position[(int)_style, (int)PI.ImageGapRight];

				int xStart = _position[(int)_style, (int)PI.BorderLeft];
				int yStart = _position[(int)_style, (int)PI.BorderTop];
				int yHeight = main.Height - yStart - _position[(int)_style, (int)PI.BorderBottom] - 1;

				// Paint the main area background
				using(SolidBrush mainBrush = new SolidBrush(SystemColors.ControlLightLight))
					g.FillRectangle(mainBrush, main);

				// Draw single line border around the main area
				using(Pen mainBorder = new Pen(SystemColors.ControlDark))
				{
					g.DrawRectangle(mainBorder, main);

					// Should the border be drawn with part of the border missing?
					if (_borderGap > 0)
					{
						using(Pen mainControl = new Pen(SystemColors.ControlLight))								
						{
							// Remove the appropriate section of the border
							if (_direction == Direction.Horizontal)
							{
								if (_excludeTop)
									g.DrawLine(mainControl, main.Left + 1 + _excludeOffset, 
															main.Top, main.Left + _borderGap + _excludeOffset - 1, main.Top);
								else
									g.DrawLine(mainControl, main.Left + 1 + _excludeOffset, 
															main.Bottom, main.Left + _borderGap + _excludeOffset - 1, main.Bottom);
							}
							else
							{
								if (_excludeTop)
									g.DrawLine(mainControl, main.Left, main.Top + 1 + _excludeOffset, 
															main.Left, main.Top + _borderGap + _excludeOffset - 1);
								else
									g.DrawLine(mainControl, main.Left, main.Bottom - 1 - _excludeOffset, 
															main.Left, main.Bottom - _borderGap - _excludeOffset - 1);
							}
						}
					}
				}

				// Draw the first image column
				Rectangle imageRect = new Rectangle(xStart, yStart, imageColWidth, yHeight);

				g.FillRectangle(SystemBrushes.ControlLight, imageRect);

				// Draw image column after each vertical separator
				foreach(DrawCommand dc in _drawCommands)
				{
					if (dc.Separator && dc.VerticalSeparator)
					{
						// Recalculate starting position (but height remains the same)
						imageRect.X = dc.DrawRect.Right;

						g.FillRectangle(SystemBrushes.ControlLight, imageRect);
					}
				}

				// Draw shadow around borders
				int rightLeft = main.Right + 1;
				int rightTop = main.Top + _position[(int)_style, (int)PI.ShadowHeight];
				int rightBottom = main.Bottom + 1;
				int leftLeft = main.Left + _position[(int)_style, (int)PI.ShadowWidth];
				int xExcludeStart = main.Left + _excludeOffset;
				int xExcludeEnd = main.Left + _excludeOffset + _borderGap;

				SolidBrush shadowBrush;

				if (_layered)
					shadowBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
				else
					shadowBrush = new SolidBrush(SystemColors.ControlDark);

				if ((_borderGap > 0) && (!_excludeTop) && (_direction == Direction.Horizontal))
				{
					int rightright = rectWin.Width;

					if (xExcludeStart >= leftLeft)
						g.FillRectangle(shadowBrush, leftLeft, rightBottom, xExcludeStart - leftLeft, _position[(int)_style, (int)PI.ShadowHeight]);

					if (xExcludeEnd <= rightright)
						g.FillRectangle(shadowBrush, xExcludeEnd, rightBottom, rightright - xExcludeEnd, _position[(int)_style, (int)PI.ShadowHeight]);
				}
				else
				{
					if ((_direction == Direction.Vertical) && (!_excludeTop))
						leftLeft = 0;
								
					g.FillRectangle(shadowBrush, leftLeft, rightBottom, rightLeft, _position[(int)_style, (int)PI.ShadowHeight]);
				}

				g.FillRectangle(shadowBrush, rightLeft, rightTop, _position[(int)_style, (int)PI.ShadowWidth], rightBottom - rightTop);
		
				shadowBrush.Dispose();

				if ((_borderGap > 0) && (!_excludeTop) && (_direction == Direction.Horizontal))
				{
					using(SolidBrush tabBrush = new SolidBrush(SystemColors.ControlLight))
						g.FillRectangle(tabBrush, new Rectangle(xExcludeStart, rightBottom - 1, 
															    xExcludeEnd - xExcludeStart, 
																_position[(int)_style, (int)PI.ShadowHeight] + 1));

					// Draw lines connecting the selected MenuControl item to the submenu
					using(Pen connectPen = new Pen(SystemColors.ControlDark))
					{
						g.DrawLine(connectPen, xExcludeStart, rightBottom - 1, xExcludeStart, rectWin.Height);
						g.DrawLine(connectPen, xExcludeEnd, rightBottom - 1, xExcludeEnd, rectWin.Height);
					}
			    }
				break;
			case VisualStyle.Plain:
				// Paint the main area background
				using(SolidBrush mainBrush = new SolidBrush(SystemColors.Control))
					g.FillRectangle(mainBrush, rectWin);
				break;
			}

			// Is there an extra title text to be drawn?
			if (_menuCommands.ExtraText.Length > 0)
				DrawColumn(g, main);
		}

		protected void DrawColumn(Graphics g, Rectangle main)
		{
			// Create the rectangle that encloses the drawing
			Rectangle rectText = new Rectangle(main.Left, main.Top, 
											   _extraSize - _position[(int)_style, (int)PI.ExtraRightGap], 
											   main.Height);

			Brush backBrush = null;
			bool disposeBack = true;

			if (_menuCommands.ExtraBackBrush != null)
			{
				backBrush = _menuCommands.ExtraBackBrush;
				disposeBack = false;
				rectText.Width++;
			}
			else
				backBrush = new SolidBrush(_menuCommands.ExtraBackColor);

			// Fill background using brush
			g.FillRectangle(backBrush, rectText);

			// Do we need to dispose of the brush?
			if (disposeBack)
				backBrush.Dispose();

			// Adjust rectangle for drawing the text into
			rectText.X += _position[(int)_style, (int)PI.ExtraWidthGap];
			rectText.Y += _position[(int)_style, (int)PI.ExtraHeightGap];
			rectText.Width -= _position[(int)_style, (int)PI.ExtraWidthGap] * 2;
			rectText.Height -= _position[(int)_style, (int)PI.ExtraHeightGap] * 2;

			// For Plain style we need to take into account the border sizes
			if (_style == VisualStyle.Plain)
				rectText.Height -= SystemInformation.Border3DSize.Height * 2;

			// Draw the text into this rectangle
			StringFormat format = new StringFormat();
			format.FormatFlags = StringFormatFlags.DirectionVertical | 
								 StringFormatFlags.NoClip | 
								 StringFormatFlags.NoWrap;
			format.Alignment = StringAlignment.Near;
			format.LineAlignment = StringAlignment.Center;

			Brush textBrush = null;
			bool disposeText = true;

			if (_menuCommands.ExtraTextBrush != null)
			{
				textBrush = _menuCommands.ExtraTextBrush;
				disposeText = false;
			}
			else
				textBrush = new SolidBrush(_menuCommands.ExtraTextColor);

			// Draw string from bottom of area towards the top using the given Font/Brush
			TextUtil.DrawReverseString(g, _menuCommands.ExtraText, _menuCommands.ExtraFont, rectText, textBrush, format);

			// Do we need to dispose of the brush?
			if (disposeText)
				textBrush.Dispose();
		}

		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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -