📄 popupmenu.cs
字号:
[Category("AnimateStyle")]
public Animation AnimateStyle
{
get { return _animateStyle; }
set { _animateStyle = value; }
}
public MenuCommand TrackPopup(Point screenPos)
{
return TrackPopup(screenPos, false);
}
public MenuCommand TrackPopup(Point screenPos, bool selectFirst)
{
// No point in showing PopupMenu if there are no entries
if (_menuCommands.VisibleItems())
{
// Default the drawing direction
_direction = Direction.Horizontal;
// Remember screen positions
_screenPos = screenPos;
_aboveScreenPos = screenPos;
_leftScreenPos = screenPos;
return InternalTrackPopup(selectFirst);
}
return null;
}
internal MenuCommand TrackPopup(Point screenPos,
Point aboveScreenPos,
Direction direction,
MenuCommandCollection menuCollection,
int borderGap,
bool selectFirst,
MenuControl parentControl,
bool animateIn,
ref int returnDir)
{
// Remember which direction the MenuControl is drawing in
_direction = direction;
// Remember the MenuControl that initiated us
_parentControl = parentControl;
// Remember the gap in drawing the top border
_borderGap = borderGap;
// Is this the first time a menu at this level has been animated
_animateIn = animateIn;
// Remember any currect menu item collection
MenuCommandCollection oldCollection = _menuCommands;
// Use the passed in collection of menu commands
_menuCommands = menuCollection;
// Remember screen positions
_screenPos = screenPos;
_aboveScreenPos = aboveScreenPos;
_leftScreenPos = screenPos;
MenuCommand ret = InternalTrackPopup(selectFirst);
// Restore to original collection
_menuCommands = oldCollection;
// Remove reference no longer required
_parentControl = null;
// Return the direction key that caused dismissal
returnDir = _returnDir;
return ret;
}
protected MenuCommand InternalTrackPopup(Point screenPosTR,
Point screenPosTL,
MenuCommandCollection menuCollection,
PopupMenu parentMenu,
bool selectFirst,
MenuControl parentControl,
bool popupRight,
bool popupDown,
bool animateIn,
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;
// Is this the first time a menu at this level has been animated
_animateIn = animateIn;
// 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;
}
protected MenuCommand InternalTrackPopup(bool selectFirst)
{
// MenuCommand to return as method result
_returnCommand = null;
// No item is being tracked
_trackItem = -1;
// Flag to indicate when to exit the message loop
_exitLoop = false;
// Assume the mouse does not start over our window
_mouseOver = false;
// Direction of key press if this caused dismissal
_returnDir = 0;
// Flag to indicate if the message should be dispatched
bool leaveMsg = false;
// First time a submenu is shown we pass in our value
_animateFirst = true;
// Create and show the popup window (without taking the focus)
CreateAndShowWindow();
// Create an object for storing windows message information
Win32.MSG msg = new Win32.MSG();
// Pretend user pressed key down to get the first valid item selected
if (selectFirst)
ProcessKeyDown();
// Always use the arrow cursor
User32.SetCursor(User32.LoadCursor(IntPtr.Zero, (uint)Win32.Cursors.IDC_ARROW));
// Must hide caret so user thinks focus has changed
bool hideCaret = User32.HideCaret(IntPtr.Zero);
// Process messages until exit condition recognised
while(!_exitLoop)
{
// Suspend thread until a windows message has arrived
if (User32.WaitMessage())
{
// Take a peek at the message details without removing from queue
while(!_exitLoop && User32.PeekMessage(ref msg, 0, 0, 0, (int)Win32.PeekMessageFlags.PM_NOREMOVE))
{
// Console.WriteLine("Track {0} {1}", this.Handle, ((Win32.Msgs)msg.message).ToString());
bool eatMessage = false;
int localWidth = _currentSize.Width - _position[(int)_style, (int)PI.ShadowWidth];
int localHeight = _currentSize.Height - _position[(int)_style, (int)PI.ShadowHeight];
// Mouse was pressed in a window of this application
if ((msg.message == (int)Win32.Msgs.WM_LBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_MBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_RBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_XBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_NCLBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_NCMBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_NCRBUTTONUP) ||
(msg.message == (int)Win32.Msgs.WM_NCXBUTTONUP))
{
Win32.POINT screenPos = MousePositionToScreen(msg);
// Is the POINT inside the Popup window rectangle
if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) &&
(screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight)))
{
OnWM_YBUTTONUP(screenPos.x, screenPos.y);
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
else
{
PopupMenu target = ParentPopupMenuWantsMouseMessage(screenPos, ref msg);
// Let the parent chain of PopupMenu's decide if they want it
if (target != null)
{
target.OnWM_YBUTTONUP(screenPos.x, screenPos.y);
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
}
}
// Mouse was pressed in a window of this application
if ((msg.message == (int)Win32.Msgs.WM_LBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_MBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_RBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_XBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_NCLBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_NCMBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_NCRBUTTONDOWN) ||
(msg.message == (int)Win32.Msgs.WM_NCXBUTTONDOWN))
{
Win32.POINT screenPos = MousePositionToScreen(msg);
// Is the POINT inside the Popup window rectangle
if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) &&
(screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight)))
{
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
else
{
// Let the parent chain of PopupMenu's decide if they want it
if (ParentPopupMenuWantsMouseMessage(screenPos, ref msg) == null)
{
if (ParentControlWantsMouseMessage(screenPos, ref msg))
{
// Let the MenuControl do its business
_parentControl.OnWM_MOUSEDOWN(screenPos);
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
else
{
// No, then we need to exit the popup menu tracking
_exitLoop = true;
// DO NOT process the message, leave it on the queue
// and let the real destination window handle it.
leaveMsg = true;
// Is a parent control specified?
if (_parentControl != null)
{
// Is the mouse event destination the parent control?
if (msg.hwnd == _parentControl.Handle)
{
// Then we want to consume the message so it does not get processed
// by the parent control. Otherwise, pressing down will cause this
// popup to disappear but the message will then get processed by
// the parent and cause a popup to reappear again. When we actually
// want the popup to disappear and nothing more.
leaveMsg = false;
}
}
}
}
else
{
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
}
}
// Mouse move occured
if (msg.message == (int)Win32.Msgs.WM_MOUSEMOVE)
{
Win32.POINT screenPos = MousePositionToScreen(msg);
// Is the POINT inside the Popup window rectangle
if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) &&
(screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight)))
{
OnWM_MOUSEMOVE(screenPos.x, screenPos.y);
}
else
{
// Do we still think the mouse is over our window?
if (_mouseOver)
{
// Process mouse leaving situation
OnWM_MOUSELEAVE();
}
// Let the parent chain of PopupMenu's decide if they want it
PopupMenu target = ParentPopupMenuWantsMouseMessage(screenPos, ref msg);
if (target != null)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -