📄 menucontrol.cs
字号:
// Is there a change in selected item?
if (_trackItem != i)
{
// We are currently selecting an item
if (_selected)
{
if (_popupMenu != null)
{
// Note that we are dismissing the submenu but not removing
// the selection of items, this flag is tested by the routine
// that will return because the submenu has been finished
_dismissTransfer = true;
// Dismiss the submenu
_popupMenu.Dismiss();
// Default to downward drawing
_drawUpwards = false;
}
// Modify the display of the two items
_trackItem = SwitchTrackingItem(_trackItem, i);
// Does the newly selected item have a submenu?
if (dc.Chevron || (dc.MenuCommand.MenuCommands.Count > 0))
User32.PostMessage(this.Handle, WM_OPERATEMENU, 1, 0);
}
else
{
// Modify the display of the two items
_trackItem = SwitchTrackingItem(_trackItem, i);
}
}
break;
}
}
// If not in selected mode
if (!_selected)
{
// None of the commands match?
if (i == _drawCommands.Count)
{
// If we have the focus then do not change the tracked item
if (!_manualFocus)
{
// Modify the display of the two items
_trackItem = SwitchTrackingItem(_trackItem, -1);
}
}
}
}
}
}
protected override void OnMouseLeave(EventArgs e)
{
_mouseOver = false;
// If we manually grabbed focus then do not switch
// selection when the mouse leaves the control area
if (!_manualFocus)
{
if (_trackItem != -1)
{
// If an item is selected then do not change tracking item when the
// mouse leaves the control area, as a popup menu might be showing and
// so keep the tracking and selection indication visible
if (_selected == false)
_trackItem = SwitchTrackingItem(_trackItem, -1);
}
}
base.OnMouseLeave(e);
}
protected override void OnResize(EventArgs e)
{
Recalculate();
// Any resize of control should redraw all of it otherwise when you
// stretch to the right it will not paint correctly as we have a one
// pixel gap between text and min button which is not honoured otherwise
this.Invalidate();
base.OnResize(e);
}
internal void DrawSelectionUpwards()
{
// Double check the state is correct for this method to be called
if ((_trackItem != -1) && (_selected))
{
// This flag is tested in the DrawCommand method
_drawUpwards = true;
// Force immediate redraw of the item
DrawCommand(_trackItem, true);
}
}
protected void Deselect()
{
// The next submenu should be animated
_animateFirst = true;
// Remove selection state
_selected = false;
// Should expansion items be reset on deselection?
if (_deselectReset)
{
// Set everything to expanded
SetAllCommandsExpansion(_menuCommands, false);
}
}
protected void Recalculate()
{
int length;
if (_direction == Direction.Horizontal)
length = this.Width;
else
length = this.Height;
// Is there space for any commands?
if (length > 0)
{
// Count the number of rows needed
int rows = 0;
// Number of items on this row
int columns = 0;
// Create a collection of drawing objects
_drawCommands = new ArrayList();
// Minimum length is a gap on either side of the text
int cellMinLength = _lengthGap * 2;
// Each cell is as broad as the whole control
int cellBreadth = this.Height;
// Accumulate starting position of each cell
int lengthStart = 0;
// Allow enough space to draw a chevron
length -= (cellMinLength + _chevronLength);
bool showPendant = ((rows == 0) && (_activeChild != null));
// If we are showing on a single line but the active child is not
// currently maximized then we can show a menu item in pendant space
if (showPendant && !_multiLine && (_activeChild.WindowState != FormWindowState.Maximized))
showPendant = false;
// Pendant positioning information
int xPos = 0;
int yPos = 0;
int xInc = 0;
int yInc = 0;
// First line needs extra space for pendant
if (showPendant)
{
length -= (_pendantLength + _pendantOffset + _shadowGap);
bool popupStyle = (_style == VisualStyle.IDE);
int borderWidth = (_style == VisualStyle.IDE) ? 1 : 2;
// Define the correct visual style
_minButton.PopupStyle = popupStyle;
_restoreButton.PopupStyle = popupStyle;
_closeButton.PopupStyle = popupStyle;
// Define correct border width
_minButton.BorderWidth = borderWidth;
_restoreButton.BorderWidth = borderWidth;
_closeButton.BorderWidth = borderWidth;
if (_direction == Direction.Horizontal)
{
xPos = this.Width - _pendantOffset - _buttonLength;
yPos = _pendantOffset;
xInc = -_buttonLength;
}
else
{
xPos = _pendantOffset;
yPos = this.Height - _pendantOffset - _buttonLength;
yInc = -_buttonLength;
}
}
// Assume chevron is not needed by default
_chevronStartCommand = null;
using(Graphics g = this.CreateGraphics())
{
// Count the item we are processing
int index = 0;
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;
int cellLength = 0;
// Is this a separator?
if (command.Text == "-")
cellLength = _separatorWidth;
else
{
// Calculate the text width of the cell
SizeF dimension = g.MeasureString(command.Text, this.Font);
// Always add 1 to ensure that rounding is up and not down
cellLength = cellMinLength + (int)dimension.Width + 1;
}
Rectangle cellRect;
// Create a new position rectangle
if (_direction == Direction.Horizontal)
cellRect = new Rectangle(lengthStart, _rowHeight * rows, cellLength, _rowHeight);
else
cellRect = new Rectangle(_rowWidth * rows, lengthStart, _rowWidth, cellLength);
lengthStart += cellLength;
columns++;
// If this item is overlapping the control edge and it is not the first
// item on the line then we should wrap around to the next row.
if ((lengthStart > length) && (columns > 1))
{
if (_multiLine)
{
// Move to next row
rows++;
// Reset number of items on this column
columns = 1;
// Reset starting position of next item
lengthStart = cellLength;
// Reset position of this item
if (_direction == Direction.Horizontal)
{
cellRect.X = 0;
cellRect.Y += _rowHeight;
}
else
{
cellRect.X += _rowWidth;
cellRect.Y = 0;
}
// Only the first line needs extra space for pendant
if (showPendant && (rows == 1))
length += (_pendantLength + _pendantOffset);
}
else
{
// Is a tracked item being make invisible
if (index <= _trackItem)
{
// Need to remove tracking of this item
RemoveItemTracking();
}
// Remember which item is first for the chevron submenu
_chevronStartCommand = command;
if (_direction == Direction.Horizontal)
{
cellRect.Y = 0;
cellRect.Width = cellMinLength + _chevronLength;
cellRect.X = this.Width - cellRect.Width;
cellRect.Height = _rowHeight;
xPos -= cellRect.Width;
}
else
{
cellRect.X = 0;
cellRect.Height = cellMinLength + _chevronLength;
cellRect.Y = this.Height - (cellMinLength + _chevronLength);
cellRect.Width = _rowWidth;
yPos -= cellRect.Height;
}
// Create a draw command for this chevron
_drawCommands.Add(new DrawCommand(cellRect));
// Exit, do not add the current item or any afterwards
break;
}
}
Rectangle selectRect = cellRect;
// Selection rectangle differs from drawing rectangle with IDE, because pressing the
// mouse down causes the menu to appear and because the popup menu appears drawn slightly
// over the drawing area the mouse up might select the first item in the popup.
if (_style == VisualStyle.IDE)
{
// Modify depending on orientation
if (_direction == Direction.Horizontal)
selectRect.Height -= (_lengthGap + 2);
else
selectRect.Width -= _breadthGap;
}
// Create a drawing object
_drawCommands.Add(new DrawCommand(command, cellRect, selectRect));
index++;
}
}
// Position the pendant buttons
if (showPendant)
{
if (_activeChild.WindowState == FormWindowState.Maximized)
{
// Window maximzied, must show the buttons
if (!_minButton.Visible)
{
_minButton.Show();
_restoreButton.Show();
_closeButton.Show();
}
// Only enabled minimize box if child is allowed to be minimized
_minButton.Enabled = _activeChild.MinimizeBox;
_closeButton.Location = new Point(xPos, yPos);
xPos += xInc; yPos += yInc;
_restoreButton.Location = new Point(xPos, yPos);
xPos += xInc; yPos += yInc;
_minButton.Location = new Point(xPos, yPos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -