📄 popupmenu.cs
字号:
// Let parent target process the message
target.OnWM_MOUSEMOVE(screenPos.x, screenPos.y);
}
else
{
if (ParentControlWantsMouseMessage(screenPos, ref msg))
{
// Let the MenuControl do its business
_parentControl.OnWM_MOUSEMOVE(screenPos);
}
}
}
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
if (msg.message == (int)Win32.Msgs.WM_SETCURSOR)
{
OnWM_SETCURSOR();
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
// Was the alt key pressed?
if (msg.message == (int)Win32.Msgs.WM_SYSKEYDOWN)
{
// Alt key pressed on its own
if((int)msg.wParam == (int)Win32.VirtualKeys.VK_MENU) // ALT key
{
// Then we should dimiss ourself
_exitLoop = true;
}
else
{
// Pretend it is a normal keypress for processing
msg.message = (int)Win32.Msgs.WM_KEYDOWN;
}
}
// Was a non-alt key pressed?
if (msg.message == (int)Win32.Msgs.WM_KEYDOWN)
{
switch((int)msg.wParam)
{
case (int)Win32.VirtualKeys.VK_UP:
ProcessKeyUp();
break;
case (int)Win32.VirtualKeys.VK_DOWN:
ProcessKeyDown();
break;
case (int)Win32.VirtualKeys.VK_LEFT:
ProcessKeyLeft();
break;
case (int)Win32.VirtualKeys.VK_RIGHT:
if(ProcessKeyRight())
{
// Do not attempt to pull a message off the queue as the
// ProcessKeyRight has eaten the message for us
leaveMsg = true;
}
break;
case (int)Win32.VirtualKeys.VK_RETURN:
// Is an item currently selected
if (_trackItem != -1)
{
DrawCommand dc = _drawCommands[_trackItem] as DrawCommand;
// Does this item have a submenu?
if (dc.SubMenu)
{
// Handle the submenu
OperateSubMenu(_trackItem, false);
// Do not attempt to pull a message off the queue as it has already
// been eaten by us in the above code
leaveMsg = true;
}
else
{
// Is this item the expansion command?
if (dc.Expansion)
{
RegenerateExpansion();
}
else
{
// Define the selection to return to caller
_returnCommand = dc.MenuCommand;
// Finish processing messages
_exitLoop = true;
}
}
}
break;
case (int)Win32.VirtualKeys.VK_ESCAPE:
// User wants to exit the menu, so set the flag to exit the message loop but
// let the message get processed. This way the key press is thrown away.
_exitLoop = true;
break;
default:
// Any other key is treated as a possible mnemonic
int selectItem = ProcessMnemonicKey((char)msg.wParam);
if (selectItem != -1)
{
DrawCommand dc = _drawCommands[selectItem] as DrawCommand;
// Define the selection to return to caller
_returnCommand = dc.MenuCommand;
// Finish processing messages
_exitLoop = true;
// Do not attempt to pull a message off the queue as it has already
// been eaten by us in the above code
leaveMsg = true;
}
break;
}
}
// We consume all keyboard input
if ((msg.message == (int)Win32.Msgs.WM_KEYDOWN) ||
(msg.message == (int)Win32.Msgs.WM_KEYUP) ||
(msg.message == (int)Win32.Msgs.WM_SYSKEYDOWN) ||
(msg.message == (int)Win32.Msgs.WM_SYSKEYUP))
{
// Eat the message to prevent the intended destination getting it
eatMessage = true;
}
// Should the message be eaten to prevent intended destination getting it?
if (eatMessage)
{
Win32.MSG eat = new Win32.MSG();
User32.GetMessage(ref eat, 0, 0, 0);
}
else
{
// Should the message we pulled from the queue?
if (!leaveMsg)
{
if (User32.GetMessage(ref msg, 0, 0, 0))
{
User32.TranslateMessage(ref msg);
User32.DispatchMessage(ref msg);
}
}
else
leaveMsg = false;
}
}
}
}
// If caret was hidden then show it again now
if (hideCaret)
User32.ShowCaret(IntPtr.Zero);
// Remove tracking of any item, this ensure 'Deselected' event is generated if required
SwitchSelection(_trackItem, -1, false, false);
// Hide the window from view before killing it, as sometimes there is a
// short delay between killing it and it disappearing because of the time
// it takes for the destroy messages to get processed
HideMenuWindow();
// Commit suicide
DestroyHandle();
// Was a command actually selected in a top level PopupMenu AND we
// are not here at the request of a MenuControl
if ((_parentMenu == null) && (_returnCommand != null) && (_parentControl == null))
{
// Pulse the selected event for the command
_returnCommand.OnClick(EventArgs.Empty);
}
return _returnCommand;
}
public void Dismiss()
{
if (this.Handle != IntPtr.Zero)
{
// Prevent the timer from expiring
_timer.Stop();
// Kill any child menu
if (_childMenu != null)
_childMenu.Dismiss();
// Finish processing messages
_exitLoop = true;
// Hide ourself
HideMenuWindow();
// Cause our own message loop to exit
User32.PostMessage(this.Handle, WM_DISMISS, 0, 0);
}
}
protected void HideMenuWindow()
{
User32.ShowWindow(this.Handle, (short)Win32.ShowWindowStyles.SW_HIDE);
}
protected void ManualAnimateBlend(bool show)
{
// Set the image to be completely transparent so the following command
// to show the window does not actual show anything.
UpdateLayeredWindow(0);
// Show the window without activating it (i.e. do not take focus)
User32.ShowWindow(this.Handle, (short)Win32.ShowWindowStyles.SW_SHOWNOACTIVATE);
int stepDelay = (int)(_animateTime / _blendSteps);
for(int i=0; i<_blendSteps; i++)
{
// Calculate increasing values of opaqueness
byte alpha = (byte)(63 + (192 / _blendSteps * (i + 1)));
DateTime beforeTime = DateTime.Now;
// Update the image for display
UpdateLayeredWindow(alpha);
DateTime afterTime = DateTime.Now;
// Need to subtract elapsed time from required step delay
TimeSpan elapsed = afterTime.Subtract(beforeTime);
// Short delay before showing next frame, but test if delay is actually needed
// because sometimes the time to update layered window is longer than delay
if ((_animateTime > 0) && (elapsed.Milliseconds < stepDelay))
System.Threading.Thread.Sleep(stepDelay - elapsed.Milliseconds);
}
}
protected void CreateAndShowWindow()
{
// Decide if we need layered windows
_layered = (_supportsLayered && (_style == VisualStyle.IDE));
// Process the menu commands to determine where each one needs to be
// drawn and return the size of the window needed to display it.
Size winSize = GenerateDrawPositions();
Point screenPos = CorrectPositionForScreen(winSize);
// Special case, if there are no menu options to show then show nothing by
// making the window 0,0 in size.
if (_menuCommands.Count == 0)
winSize = new Size(0,0);
CreateParams cp = new CreateParams();
// Any old title will do as it will not be shown
cp.Caption = "NativePopupMenu";
// Define the screen position/size
cp.X = screenPos.X;
cp.Y = screenPos.Y;
cp.Height = winSize.Height;
cp.Width = winSize.Width;
// As a top-level window it has no parent
cp.Parent = IntPtr.Zero;
// Appear as a top-level window
cp.Style = unchecked((int)(uint)Win32.WindowStyles.WS_POPUP);
// Set styles so that it does not have a caption bar and is above all other
// windows in the ZOrder, i.e. TOPMOST
cp.ExStyle = (int)Win32.WindowExStyles.WS_EX_TOPMOST +
(int)Win32.WindowExStyles.WS_EX_TOOLWINDOW;
// OS specific style
if (_layered)
{
// If not on NT then we are going to use alpha blending on the shadow border
// and so we need to specify the layered window style so the OS can handle it
cp.ExStyle += (int)Win32.WindowExStyles.WS_EX_LAYERED;
}
// Is this the plain style of appearance?
if (_style == VisualStyle.Plain)
{
// We want the tradiditonal 3D border
cp.Style += unchecked((int)(uint)Win32.WindowStyles.WS_DLGFRAME);
}
// Create the actual window
this.CreateHandle(cp);
// Update the window clipping region
if (!_layered)
SetWindowRegion(winSize);
// Remember the correct screen drawing details
_currentSize = winSize;
_currentPoint = screenPos;
bool animated = false;
if (_layered)
{
// Update the image for display
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -