/******************************************************************************* * Copyright(c) 2014 DongkeSoft All rights reserved. / Confidential * 类的信息: * 1.程序名称:NativeMethods.cs * 2.功能描述: * 编辑履历: * 作者 日期 版本 修改内容 * 陈晓野 2014/09/04 1.00 新建 *******************************************************************************/ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Security.Permissions; using System.Runtime.InteropServices; using VS = System.Windows.Forms.VisualStyles; /*
  • Base class for custom tooltips.
  • Office-2007-like tooltip class.
  • */ namespace Dongke.IBOSS.PRD.Basics.BaseControls { /// /// CodeProject.com "Simple pop-up control" "http://www.codeproject.com/cs/miscctrl/simplepopup.asp". /// Represents a pop-up window. /// [ToolboxItem(false)] //[CLSCompliant(true)] public partial class Popup : ToolStripDropDown { #region " Fields & Properties " private Control content; /// /// Gets the content of the pop-up. /// public Control Content { get { return content; } } private bool fade; /// /// Gets a value indicating whether the uses the fade effect. /// /// true if pop-up uses the fade effect; otherwise, false. /// To use the fade effect, the FocusOnOpen property also has to be set to true. public bool UseFadeEffect { get { return fade; } set { if (fade == value) return; fade = value; } } private bool focusOnOpen = true; /// /// Gets or sets a value indicating whether to focus the content after the pop-up has been opened. /// /// true if the content should be focused after the pop-up has been opened; otherwise, false. /// If the FocusOnOpen property is set to false, then pop-up cannot use the fade effect. public bool FocusOnOpen { get { return focusOnOpen; } set { focusOnOpen = value; } } private bool acceptAlt = true; /// /// Gets or sets a value indicating whether presing the alt key should close the pop-up. /// /// true if presing the alt key does not close the pop-up; otherwise, false. public bool AcceptAlt { get { return acceptAlt; } set { acceptAlt = value; } } private Popup ownerPopup; private Popup childPopup; private bool _resizable; private bool resizable; /// /// Gets or sets a value indicating whether this is resizable. /// /// true if resizable; otherwise, false. public bool Resizable { get { return resizable && _resizable; } set { resizable = value; } } private ToolStripControlHost host; private Size minSize; /// /// Gets or sets the size that is the lower limit that can specify. /// /// An ordered pair of type representing the width and height of a rectangle. public new Size MinimumSize { get { return minSize; } set { minSize = value; } } private Size maxSize; /// /// Gets or sets the size that is the upper limit that can specify. /// /// An ordered pair of type representing the width and height of a rectangle. public new Size MaximumSize { get { return maxSize; } set { maxSize = value; } } /// /// Gets parameters of a new window. /// /// An object of type used when creating a new window. protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { CreateParams cp = base.CreateParams; cp.ExStyle |= NativeMethods.WS_EX_NOACTIVATE; return cp; } } #endregion #region " Constructors " /// /// Initializes a new instance of the class. /// /// The content of the pop-up. /// /// Pop-up will be disposed immediately after disposion of the content control. /// /// is null. public Popup(Control content) { if (content == null) { throw new ArgumentNullException("content"); } this.content = content; this.fade = SystemInformation.IsMenuAnimationEnabled && SystemInformation.IsMenuFadeEnabled; this._resizable = true; InitializeComponent(); AutoSize = false; DoubleBuffered = true; ResizeRedraw = true; host = new ToolStripControlHost(content); Padding = Margin = host.Padding = host.Margin = Padding.Empty; MinimumSize = content.MinimumSize; content.MinimumSize = content.Size; MaximumSize = content.MaximumSize; content.MaximumSize = content.Size; Size = content.Size; content.Location = Point.Empty; Items.Add(host); content.Disposed += delegate(object sender, EventArgs e) { content = null; Dispose(true); }; content.RegionChanged += delegate(object sender, EventArgs e) { UpdateRegion(); }; content.Paint += delegate(object sender, PaintEventArgs e) { PaintSizeGrip(e); }; UpdateRegion(); } #endregion #region " Methods " /// /// Processes a dialog box key. /// /// One of the values that represents the key to process. /// /// true if the key was processed by the control; otherwise, false. /// protected override bool ProcessDialogKey(Keys keyData) { if (acceptAlt && ((keyData & Keys.Alt) == Keys.Alt)) return false; return base.ProcessDialogKey(keyData); } /// /// Updates the pop-up region. /// protected void UpdateRegion() { if (this.Region != null) { this.Region.Dispose(); this.Region = null; } if (content.Region != null) { this.Region = content.Region.Clone(); } } /// /// Shows pop-up window below the specified control. /// /// The control below which the pop-up will be shown. /// /// When there is no space below the specified control, the pop-up control is shown above it. /// /// is null. public void Show(Control control) { if (control == null) { throw new ArgumentNullException("control"); } SetOwnerItem(control); Show(control, control.ClientRectangle); } /// /// Shows pop-up window below the specified area of specified control. /// /// The control used to compute screen location of specified area. /// The area of control below which the pop-up will be shown. /// /// When there is no space below specified area, the pop-up control is shown above it. /// /// is null. public void Show(Control control, Rectangle area) { if (control == null) { throw new ArgumentNullException("control"); } SetOwnerItem(control); resizableTop = resizableRight = false; Point location = control.PointToScreen(new Point(area.Left, area.Top + area.Height)); Rectangle screen = Screen.FromControl(control).WorkingArea; if (location.X + Size.Width > (screen.Left + screen.Width)) { resizableRight = true; location.X = (screen.Left + screen.Width) - Size.Width; } if (location.Y + Size.Height > (screen.Top + screen.Height)) { resizableTop = true; location.Y -= Size.Height + area.Height; } location = control.PointToClient(location); Show(control, location, ToolStripDropDownDirection.BelowRight); } private const int frames = 1; private const int totalduration = 0; // ML : 2007-11-05 : was 100 but caused a flicker. private const int frameduration = totalduration / frames; /// /// Adjusts the size of the owner to accommodate the if the owner is currently displayed, or clears and resets active child controls of the if the is not currently displayed. /// /// true if the owner is currently displayed; otherwise, false. protected override void SetVisibleCore(bool visible) { double opacity = Opacity; if (visible && fade && focusOnOpen) Opacity = 0; base.SetVisibleCore(visible); if (!visible || !fade || !focusOnOpen) return; for (int i = 1; i <= frames; i++) { if (i > 1) { System.Threading.Thread.Sleep(frameduration); } Opacity = opacity * (double)i / (double)frames; } Opacity = opacity; } private bool resizableTop; private bool resizableRight; private void SetOwnerItem(Control control) { if (control == null) { return; } if (control is Popup) { Popup popupControl = control as Popup; ownerPopup = popupControl; ownerPopup.childPopup = this; OwnerItem = popupControl.Items[0]; return; } if (control.Parent != null) { SetOwnerItem(control.Parent); } } /// /// Raises the event. /// /// An that contains the event data. protected override void OnSizeChanged(EventArgs e) { content.MinimumSize = Size; content.MaximumSize = Size; content.Size = Size; content.Location = Point.Empty; base.OnSizeChanged(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnOpening(CancelEventArgs e) { if (content.IsDisposed || content.Disposing) { e.Cancel = true; return; } UpdateRegion(); base.OnOpening(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnOpened(EventArgs e) { if (ownerPopup != null) { ownerPopup._resizable = false; } if (focusOnOpen) { content.Focus(); } base.OnOpened(e); } protected override void OnClosed(ToolStripDropDownClosedEventArgs e) { if (ownerPopup != null) { ownerPopup._resizable = true; } base.OnClosed(e); } public DateTime LastClosedTimeStamp = DateTime.Now; protected override void OnVisibleChanged(EventArgs e) { if (Visible == false) LastClosedTimeStamp = DateTime.Now; base.OnVisibleChanged(e); } #endregion #region " Resizing Support " /// /// Processes Windows messages. /// /// The Windows to process. [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { if (InternalProcessResizing(ref m, false)) { return; } base.WndProc(ref m); } /// /// Processes the resizing messages. /// /// The message. /// true, if the WndProc method from the base class shouldn't be invoked. [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] public bool ProcessResizing(ref Message m) { return InternalProcessResizing(ref m, true); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] private bool InternalProcessResizing(ref Message m, bool contentControl) { if (m.Msg == NativeMethods.WM_NCACTIVATE && m.WParam != IntPtr.Zero && childPopup != null && childPopup.Visible) { childPopup.Hide(); } if (!Resizable) { return false; } if (m.Msg == NativeMethods.WM_NCHITTEST) { return OnNcHitTest(ref m, contentControl); } else if (m.Msg == NativeMethods.WM_GETMINMAXINFO) { return OnGetMinMaxInfo(ref m); } return false; } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] private bool OnGetMinMaxInfo(ref Message m) { NativeMethods.MINMAXINFO minmax = (NativeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(NativeMethods.MINMAXINFO)); minmax.maxTrackSize = this.MaximumSize; minmax.minTrackSize = this.MinimumSize; Marshal.StructureToPtr(minmax, m.LParam, false); return true; } private bool OnNcHitTest(ref Message m, bool contentControl) { int x = NativeMethods.LOWORD(m.LParam); int y = NativeMethods.HIWORD(m.LParam); Point clientLocation = PointToClient(new Point(x, y)); GripBounds gripBouns = new GripBounds(contentControl ? content.ClientRectangle : ClientRectangle); IntPtr transparent = new IntPtr(NativeMethods.HTTRANSPARENT); if (resizableTop) { if (resizableRight && gripBouns.TopLeft.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTTOPLEFT; return true; } if (!resizableRight && gripBouns.TopRight.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTTOPRIGHT; return true; } if (gripBouns.Top.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTTOP; return true; } } else { if (resizableRight && gripBouns.BottomLeft.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTBOTTOMLEFT; return true; } if (!resizableRight && gripBouns.BottomRight.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTBOTTOMRIGHT; return true; } if (gripBouns.Bottom.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTBOTTOM; return true; } } if (resizableRight && gripBouns.Left.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTLEFT; return true; } if (!resizableRight && gripBouns.Right.Contains(clientLocation)) { m.Result = contentControl ? transparent : (IntPtr)NativeMethods.HTRIGHT; return true; } return false; } private VS.VisualStyleRenderer sizeGripRenderer; /// /// Paints the size grip. /// /// The instance containing the event data. public void PaintSizeGrip(PaintEventArgs e) { if (e == null || e.Graphics == null || !resizable) { return; } Size clientSize = content.ClientSize; if (Application.RenderWithVisualStyles) { if (this.sizeGripRenderer == null) { this.sizeGripRenderer = new VS.VisualStyleRenderer(VS.VisualStyleElement.Status.Gripper.Normal); } this.sizeGripRenderer.DrawBackground(e.Graphics, new Rectangle(clientSize.Width - 0x10, clientSize.Height - 0x10, 0x10, 0x10)); } else { ControlPaint.DrawSizeGrip(e.Graphics, content.BackColor, clientSize.Width - 0x10, clientSize.Height - 0x10, 0x10, 0x10); } } #endregion } }