524 lines
16 KiB
C#
Raw Normal View History

#if NETFRAMEWORK || WINDOWS
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace PopupTool
{
[ToolboxItem(false)]
public class Popup : ToolStripDropDown
{
public Control Content
{
get
{
return this.content;
}
}
public bool UseFadeEffect
{
get
{
return this.fade;
}
set
{
if (this.fade != value)
{
this.fade = value;
}
}
}
public bool FocusOnOpen
{
get
{
return this.focusOnOpen;
}
set
{
this.focusOnOpen = value;
}
}
public bool AcceptAlt
{
get
{
return this.acceptAlt;
}
set
{
this.acceptAlt = value;
}
}
public bool Resizable
{
get
{
return this.resizable && this._resizable;
}
set
{
this.resizable = value;
}
}
public new Size MinimumSize
{
get
{
return this.minSize;
}
set
{
this.minSize = value;
}
}
public new Size MaximumSize
{
get
{
return this.maxSize;
}
set
{
this.maxSize = value;
}
}
public bool IsOpen
{
get
{
return this._isOpen;
}
}
protected override CreateParams CreateParams
{
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 134217728;
return createParams;
}
}
public Popup(Control content)
{
EventHandler handler = null;
EventHandler handler2 = null;
PaintEventHandler handler3 = null;
this.focusOnOpen = true;
this.acceptAlt = true;
if (ReferenceEquals(content, null))
{
throw new ArgumentNullException("content");
}
this.content = content;
this.fade = SystemInformation.IsMenuAnimationEnabled && SystemInformation.IsMenuFadeEnabled;
this._resizable = true;
this.AutoSize = false;
this.DoubleBuffered = true;
base.ResizeRedraw = true;
this.host = new ToolStripControlHost(content);
Padding padding1 = this.host.Margin = Padding.Empty;
Padding padding2 = this.host.Padding = padding1;
base.Padding = base.Margin = padding2;
this.MinimumSize = content.MinimumSize;
content.MinimumSize = content.Size;
this.MaximumSize = content.MaximumSize;
content.MaximumSize = content.Size;
base.Size = content.Size;
content.Location = Point.Empty;
this.Items.Add(this.host);
if (handler == null)
{
handler = delegate (object sender, EventArgs e) {
content = null;
this.Dispose(true);
};
}
content.Disposed += handler;
if (handler2 == null)
{
handler2 = (sender, e) => this.UpdateRegion();
}
content.RegionChanged += handler2;
if (handler3 == null)
{
handler3 = (sender, e) => this.PaintSizeGrip(e);
}
content.Paint += handler3;
this.UpdateRegion();
}
protected override bool ProcessDialogKey(Keys keyData)
{
if (this.acceptAlt && (keyData & Keys.Alt) == Keys.Alt)
{
if ((keyData & Keys.F4) != Keys.F4)
{
return false;
}
base.Close();
}
return base.ProcessDialogKey(keyData);
}
protected void UpdateRegion()
{
if (base.Region != null)
{
base.Region.Dispose();
base.Region = null;
}
if (this.content.Region != null)
{
base.Region = this.content.Region.Clone();
}
}
public void Show(Control control)
{
this.Show(control, control.ClientRectangle);
}
public void Show(Control control, bool center)
{
this.Show(control, control.ClientRectangle, center);
}
public void Show(Control control, Rectangle area)
{
this.Show(control, area, false);
}
public void Show(Control control, Rectangle area, bool center)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
this.SetOwnerItem(control);
this.resizableTop = (this.resizableLeft = false);
Point point = control.PointToScreen(new Point(area.Left, area.Top + area.Height));
Rectangle workingArea = Screen.FromControl(control).WorkingArea;
if (center)
{
if (point.X + (area.Width + base.Size.Width) / 2 > workingArea.Right)
{
this.resizableLeft = true;
point.X = workingArea.Right - base.Size.Width;
}
else
{
this.resizableLeft = true;
point.X -= (base.Size.Width - area.Width) / 2;
}
}
else if (point.X + base.Size.Width > workingArea.Left + workingArea.Width)
{
this.resizableLeft = true;
point.X = workingArea.Left + workingArea.Width - base.Size.Width;
}
if (point.Y + base.Size.Height > workingArea.Top + workingArea.Height)
{
this.resizableTop = true;
point.Y -= base.Size.Height + area.Height;
}
point = control.PointToClient(point);
base.Show(control, point, ToolStripDropDownDirection.BelowRight);
}
protected override void SetVisibleCore(bool visible)
{
double opacity = base.Opacity;
if (visible && this.fade && this.focusOnOpen)
{
base.Opacity = 0.0;
}
base.SetVisibleCore(visible);
if (visible && this.fade && this.focusOnOpen)
{
for (int i = 1; i <= 5; i++)
{
if (i > 1)
{
Thread.Sleep(20);
}
base.Opacity = opacity * (double)i / 5.0;
}
base.Opacity = opacity;
}
}
private void SetOwnerItem(Control control)
{
if (control != null)
{
if (control is Popup)
{
Popup popup = control as Popup;
this.ownerPopup = popup;
this.ownerPopup.childPopup = this;
base.OwnerItem = popup.Items[0];
}
else if (control.Parent != null)
{
this.SetOwnerItem(control.Parent);
}
}
}
protected override void OnSizeChanged(EventArgs e)
{
this.content.MinimumSize = base.Size;
this.content.MaximumSize = base.Size;
this.content.Size = base.Size;
this.content.Location = Point.Empty;
base.OnSizeChanged(e);
}
protected override void OnOpening(CancelEventArgs e)
{
if (this.content.IsDisposed || this.content.Disposing)
{
e.Cancel = true;
}
else
{
this.UpdateRegion();
base.OnOpening(e);
}
}
protected override void OnOpened(EventArgs e)
{
if (this.ownerPopup != null)
{
this.ownerPopup._resizable = false;
}
if (this.focusOnOpen)
{
this.content.Focus();
}
this._isOpen = true;
base.OnOpened(e);
}
protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
{
if (this.ownerPopup != null)
{
this.ownerPopup._resizable = true;
}
this._isOpen = false;
base.OnClosed(e);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
if (!this.InternalProcessResizing(ref m, false))
{
base.WndProc(ref m);
}
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public bool ProcessResizing(ref Message m)
{
return this.InternalProcessResizing(ref m, true);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private bool InternalProcessResizing(ref Message m, bool contentControl)
{
if (m.Msg == 134 && m.WParam != IntPtr.Zero && this.childPopup != null && this.childPopup.Visible)
{
this.childPopup.Hide();
}
bool result;
if (!this.Resizable)
{
result = false;
}
else if (m.Msg == 132)
{
result = this.OnNcHitTest(ref m, contentControl);
}
else
{
result = (m.Msg == 36 && this.OnGetMinMaxInfo(ref m));
}
return result;
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private bool OnGetMinMaxInfo(ref Message m)
{
UnsafeMethods.MINMAXINFO minmaxinfo = (UnsafeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(UnsafeMethods.MINMAXINFO));
minmaxinfo.maxTrackSize = this.MaximumSize;
minmaxinfo.minTrackSize = this.MinimumSize;
Marshal.StructureToPtr(minmaxinfo, m.LParam, false);
return true;
}
private bool OnNcHitTest(ref Message m, bool contentControl)
{
int x = UnsafeMethods.LOWORD(m.LParam);
int y = UnsafeMethods.HIWORD(m.LParam);
Point pt = base.PointToClient(new Point(x, y));
GripBounds gripBounds = new GripBounds(contentControl ? this.content.ClientRectangle : base.ClientRectangle);
IntPtr intPtr = new IntPtr(-1);
if (this.resizableTop)
{
if (this.resizableLeft && gripBounds.TopLeft.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)13));
return true;
}
if (!this.resizableLeft && gripBounds.TopRight.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)14));
return true;
}
if (gripBounds.Top.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)12));
return true;
}
}
else
{
if (this.resizableLeft && gripBounds.BottomLeft.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)16));
return true;
}
if (!this.resizableLeft && gripBounds.BottomRight.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)17));
return true;
}
if (gripBounds.Bottom.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)15));
return true;
}
}
bool result;
if (this.resizableLeft && gripBounds.Left.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)10));
result = true;
}
else if (!this.resizableLeft && gripBounds.Right.Contains(pt))
{
m.Result = (contentControl ? intPtr : ((IntPtr)11));
result = true;
}
else
{
result = false;
}
return result;
}
public void PaintSizeGrip(PaintEventArgs e)
{
if (e != null && e.Graphics != null && this.resizable)
{
Size clientSize = this.content.ClientSize;
using (Bitmap bitmap = new Bitmap(16, 16))
{
using (Graphics graphics = Graphics.FromImage(bitmap))
{
if (Application.RenderWithVisualStyles)
{
if (this.sizeGripRenderer == null)
{
this.sizeGripRenderer = new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal);
}
this.sizeGripRenderer.DrawBackground(graphics, new Rectangle(0, 0, 16, 16));
}
else
{
ControlPaint.DrawSizeGrip(graphics, this.content.BackColor, 0, 0, 16, 16);
}
}
GraphicsState gstate = e.Graphics.Save();
e.Graphics.ResetTransform();
if (this.resizableTop)
{
if (this.resizableLeft)
{
e.Graphics.RotateTransform(180f);
e.Graphics.TranslateTransform((float)(-(float)clientSize.Width), (float)(-(float)clientSize.Height));
}
else
{
e.Graphics.ScaleTransform(1f, -1f);
e.Graphics.TranslateTransform(0f, (float)(-(float)clientSize.Height));
}
}
else if (this.resizableLeft)
{
e.Graphics.ScaleTransform(-1f, 1f);
e.Graphics.TranslateTransform((float)(-(float)clientSize.Width), 0f);
}
e.Graphics.DrawImage(bitmap, clientSize.Width - 16, clientSize.Height - 16 + 1, 16, 16);
e.Graphics.Restore(gstate);
}
}
}
private const int frames = 5;
private const int totalduration = 100;
private const int frameduration = 20;
private Control content;
private bool fade;
private bool focusOnOpen = true;
private bool acceptAlt = true;
private Popup ownerPopup;
private Popup childPopup;
private bool _resizable;
private bool resizable;
private ToolStripControlHost host;
private Size minSize;
private Size maxSize;
private bool _isOpen;
private bool resizableTop;
private bool resizableLeft;
private VisualStyleRenderer sizeGripRenderer;
}
}
#endif