📄 popupmenu.cs
字号:
UpdateLayeredWindow();
bool animate = false;
switch(_animate)
{
case Animate.No:
animate = false;
break;
case Animate.Yes:
animate = true;
break;
case Animate.System:
int bRetValue = 0;
// Does the system want animation to occur?
User32.SystemParametersInfo((uint)Win32.SPIActions.SPI_GETMENUANIMATION, 0, ref bRetValue, 0);
animate = (bRetValue != 0);
break;
}
// Should the menu be shown with animation?
if (animate && _animateIn)
{
uint animateFlags = (uint)_animateStyle;
if (_animateStyle == Animation.System)
{
int bRetValue = 0;
// Does the system want fading or sliding?
User32.SystemParametersInfo((uint)Win32.SPIActions.SPI_GETMENUFADE, 0, ref bRetValue, 0);
// Use appropriate flags to match request
if (bRetValue != 0)
animateFlags = (uint)Animation.Blend;
else
animateFlags = (uint)Animation.SlideHorVerPositive;
}
// Animate the appearance of the window
if ((animateFlags & (uint)Win32.AnimateFlags.AW_BLEND) != 0)
{
// Cannot use Win32.AnimateWindow to blend a layered window
ManualAnimateBlend(true);
}
else
{
// Animate the appearance of the window
User32.AnimateWindow(this.Handle, (uint)_animateTime, animateFlags);
}
animated = true;
}
}
// Did any animation take place?
if (!animated)
{
// Show the window without activating it (i.e. do not take focus)
User32.ShowWindow(this.Handle, (short)Win32.ShowWindowStyles.SW_SHOWNOACTIVATE);
}
}
protected void UpdateLayeredWindow()
{
UpdateLayeredWindow(_currentPoint, _currentSize, 255);
}
protected void UpdateLayeredWindow(byte alpha)
{
UpdateLayeredWindow(_currentPoint, _currentSize, alpha);
}
protected void UpdateLayeredWindow(Point point, Size size, byte alpha)
{
// Create bitmap for drawing onto
Bitmap memoryBitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb);
using(Graphics g = Graphics.FromImage(memoryBitmap))
{
Rectangle area = new Rectangle(0, 0, size.Width, size.Height);
// Draw the background area
DrawBackground(g, area);
// Draw the actual menu items
DrawAllCommands(g);
// Get hold of the screen DC
IntPtr hDC = User32.GetDC(IntPtr.Zero);
// Create a memory based DC compatible with the screen DC
IntPtr memoryDC = Gdi32.CreateCompatibleDC(hDC);
// Get access to the bitmap handle contained in the Bitmap object
IntPtr hBitmap = memoryBitmap.GetHbitmap(Color.FromArgb(0));
// Select this bitmap for updating the window presentation
IntPtr oldBitmap = Gdi32.SelectObject(memoryDC, hBitmap);
// New window size
Win32.SIZE ulwsize;
ulwsize.cx = size.Width;
ulwsize.cy = size.Height;
// New window position
Win32.POINT topPos;
topPos.x = point.X;
topPos.y = point.Y;
// Offset into memory bitmap is always zero
Win32.POINT pointSource;
pointSource.x = 0;
pointSource.y = 0;
// We want to make the entire bitmap opaque
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = (byte)Win32.AlphaFlags.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = alpha;
blend.AlphaFormat = (byte)Win32.AlphaFlags.AC_SRC_ALPHA;
// Tell operating system to use our bitmap for painting
User32.UpdateLayeredWindow(Handle, hDC, ref topPos, ref ulwsize,
memoryDC, ref pointSource, 0, ref blend,
(int)Win32.UpdateLayeredWindowsFlags.ULW_ALPHA);
// Put back the old bitmap handle
Gdi32.SelectObject(memoryDC, oldBitmap);
// Cleanup resources
User32.ReleaseDC(IntPtr.Zero, hDC);
Gdi32.DeleteObject(hBitmap);
Gdi32.DeleteDC(memoryDC);
}
}
protected void SetWindowRegion(Size winSize)
{
// Style specific handling
if (_style == VisualStyle.IDE)
{
int shadowHeight = _position[(int)_style, (int)PI.ShadowHeight];
int shadowWidth = _position[(int)_style, (int)PI.ShadowWidth];
// Create a new region object
Region drawRegion = new Region();
// Can draw anywhere
drawRegion.MakeInfinite();
// Remove the area above the right hand shadow
drawRegion.Xor(new Rectangle(winSize.Width - shadowWidth, 0, shadowWidth, shadowHeight));
// When drawing upwards from a vertical menu we need to allow a connection between the
// MenuControl selection box and the PopupMenu shadow
if (!((_direction == Direction.Vertical) && !_excludeTop))
{
// Remove the area left of the bottom shadow
drawRegion.Xor(new Rectangle(0, winSize.Height - shadowHeight, shadowWidth, shadowHeight));
}
// Define a region to prevent drawing over exposed corners of shadows
using(Graphics g = Graphics.FromHwnd(this.Handle))
User32.SetWindowRgn(this.Handle, drawRegion.GetHrgn(g), false);
}
}
protected Point CorrectPositionForScreen(Size winSize)
{
Rectangle screenRect = Screen.GetWorkingArea (_screenPos);
Point screenPos = _screenPos;
int screenWidth = screenRect.Width;
int screenLeft = screenRect.Left;
int screenRight = screenRect.Right;
int screenHeight = screenRect.Height;
int screenBottom = screenRect.Bottom;
int screenTop = screenRect.Top;
// Default to excluding menu border from top
_excludeTop = true;
_excludeOffset = 0;
// Shadow area does not count as part of width
winSize.Width -= _position[(int)_style, (int)PI.ShadowWidth];
// Calculate the downward position first
if (_popupDown)
{
// Ensure the end of the menu is not off the bottom of the screen
if ((screenPos.Y + winSize.Height) > screenBottom)
{
// If the parent control exists then try and position upwards instead
if ((_parentControl != null) && (_parentMenu == null))
{
// Is there space above the required position?
if ((_aboveScreenPos.Y - winSize.Height) > screenTop)
{
// Great...do that instead
screenPos.Y = _aboveScreenPos.Y - winSize.Height;
// Reverse direction of drawing this and submenus
_popupDown = false;
// Remember to exclude border from bottom of menu and not the top
_excludeTop = false;
// Inform parent it needs to redraw the selection upwards
_parentControl.DrawSelectionUpwards();
}
}
// Did the above logic still fail?
if ((screenPos.Y + winSize.Height) > screenBottom)
{
// If not a top level PopupMenu then..
if (_parentMenu != null)
{
// Reverse direction of drawing this and submenus
_popupDown = false;
// Is there space above the required position?
if ((_aboveScreenPos.Y - winSize.Height) > screenTop)
screenPos.Y = _aboveScreenPos.Y - winSize.Height;
else
screenPos.Y = screenTop;
}
else
screenPos.Y = screenBottom - winSize.Height - 1;
}
}
}
else
{
// Ensure the end of the menu is not off the top of the screen
if ((screenPos.Y - winSize.Height) < screenTop)
{
// Reverse direction
_popupDown = true;
// Is there space below the required position?
if ((screenPos.Y + winSize.Height) > screenBottom)
screenPos.Y = screenBottom - winSize.Height - 1;
}
else
screenPos.Y -= winSize.Height;
}
// Calculate the across position next
if (_popupRight)
{
// Ensure that right edge of menu is not off right edge of screen
if ((screenPos.X + winSize.Width) > screenRight)
{
// If not a top level PopupMenu then...
if (_parentMenu != null)
{
// Reverse direction
_popupRight = false;
// Adjust across position
screenPos.X = _leftScreenPos.X - winSize.Width;
if (screenPos.X < screenLeft)
screenPos.X = screenLeft;
}
else
{
// Find new position of X coordinate
int newX = screenRight - winSize.Width - 1;
// Modify the adjust needed when drawing top/bottom border
_excludeOffset = screenPos.X - newX;
// Use new position for popping up menu
screenPos.X = newX;
}
}
}
else
{
// Start by using the left screen pos instead
screenPos.X = _leftScreenPos.X;
// Ensure the left edge of the menu is not off the left of the screen
if ((screenPos.X - winSize.Width) < screenLeft)
{
// Reverse direction
_popupRight = true;
// Is there space below the required position?
if ((_screenPos.X + winSize.Width) > screenRight)
screenPos.X = screenRight - winSize.Width - 1;
else
screenPos.X = _screenPos.X;
}
else
screenPos.X -= winSize.Width;
}
return screenPos;
}
protected void RegenerateExpansion()
{
// Remove all existing draw commands
_drawCommands.Clear();
// Move into the expanded mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -