📄 popupmenu.cs
字号:
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 + -