cool hit counter [C#] Share a pop-up container layer, like a right-click menu_Intefrankly

[C#] Share a pop-up container layer, like a right-click menu


Applies to. net2.0+ Winform project

------------------201508261813 update( source code (computing)have update、Demo not update)------------------

  • Redraw to adjust the small and large handles (SizeGrip, the one in the bottom right corner), because the system self-drawn ones are too close to the corners, and under XP they cover that part of the border, which is not a good visual experience. Improvements are shown in the figure.

newDrawSizeGrip method is the draw method, which isprotected virtual So if you don't like what I've drawn, you can rewrite that method in a subclass to draw your own to your satisfaction (off topic, I also referenced the VS2010 effect for drawing this, but it's the opposite, VS's is a raised effect, mine is a collapsed style)

  • backing Four sides + four corners All around dragging to change the size of the floating layer and improve the experience. As pictured.

note: Is the floating layer may The resizing is based on theSizeGripStyle properties decisions, a point (in sports or games)3 kind of situation:

  • SizeGripStyle isShow, always allows the user to resize, The handle will appear、 Mouse-over edge corners produce visual changes and may drag (mouse operation) (computing)
  • SizeGripStyle isHide, then user resizing is always disabled, The handle will not appear、 Mouse over edge corners does not produce visual changes, nor may Drag to change size
  • SizeGripStyle isAuto This is also the logic of the original Form, except that the original Form will also be based on FormBorderStyle, but this class has solidified that property, so please pay attention to this Auto stuff, and it is recommended to always explicitly specify Show/Hide for good

------------------201508251458 update------------------

  • Activating the first control was previously done in OnShown, but after some research, changing it to make TopMost=true gives the floating layer the same behavior as the normal form for activating the first control, while eliminating the need to override OnShown
  • Solve the problem that child controls sometimes do not have a focus box (focus dotted box). As pictured.

Note: the last demo is not updated, please just re-fetch the FloatLayerBase.cs source code

------------------201508240846 original article (updated) ------------------

Background.

Sometimes we need to open a simple window to do something like type something, tap on an item, or something like this, maybe like this.

When you're done, return to the original form and get the input you just received, There's nothing wrong with that., But a few days ago I had some sudden thoughts: Why do you have to have a board to pop up a form to the user, whether or not may What about quickly rendering a layer near the button to do this, It's like a shortcut menu., Users are happy to just do what they need to do in there, If you're not happy, just tap it somewhere else and it'll go away., It's a quick and easy operation.,DUANG~ Will a pop-up form make the user's heart stutter?, Things on a feeling level are often very subtle, however, Now that I've got the idea.,just try it。

I first looked for an off-the-shelf solution, and sure enough, there are already cowboys at the awesome codeproject.com who have done something like this.

http://www.codeproject.com/Articles/17502/Simple-Popup-Control

A brief experience, A remarkable creation indeed.。 The principle is to useToolStripControlHost may This ability to host custom controls, Make drop-down controlsToolStripDropDown Bring up any custom control like a right-click menu( Don't forget the right-click menuContextMenuStrip It is the inheritance fromToolStripDropDown), This would be the same as using the menu as a container, may Pop up any combination of simple or complex controls, With the convenience of a menu, call as often as you like and wipe away。 I was so happy when I found out about the program, Just the effect I was looking for., Feel better now., Don't bother building your own.。

However, I soon discovered a shortcoming that seemed quite concerning to me, that ToolStripDown only has Show, no ShowDialog, that is, it cannot be popped up in a modal (Modal, also called modal, given that MSDN calls it modal, I also call it modal) way, which is determined by the inherent ability of ToolStripDropDown, and since the solution is based on ToolStripDropDown, it is naturally limited by this, and cannot be popped up in a modal way. The problem with this is that the call experience is not good in some cases (the experience is not exclusive to the user, of course, we coders are also people, we also have to talk about the experience), for example, the pop-up control is to let the user enter something, after the user clicks a button or something to return to the original form, and then in the original form to get the user just entered, and then go on to do the next thing. Since a non-modal Show doesn't block code, you can't take it for granted that you can get values and use them underneath the Show ~ that's obvious. To get the value you might have to do something extra, like responding to the close event of the popup control, or passing the original form into the popup control and then doing in the latter what should have been done in the original form ~ etc. There are certainly many ways to do this, but it's all because of the redundancy that only Show brings, and what better way to do it than to popup the control in a method, the wait for Return, continue to deal with the smooth it, like this is not very natural: the

string s;
using (Popup p = new Popup())
{
    if (p.ShowDialog() != DialogResult.OK) { return; }

    s = p.InputText;
}
//go on
...

So sadly, had to wave off this excellent solution and build my own wheels. But inspired by that solution, I thought of using ContextMenu as a container (note that this menu class is quite different from the above mentioned ContextMenuStrip which inherits from ToolStripDropDown, the former is an OS native menu, the kind of menu that pops up on the desktop, icons and right-click in the text box, .net is the way to operate such a menu by calling the API, while the latter is a full .net implementation, for more information please refer toMSDN, Not expanded here), owing toContextMenu ofShow It's blocking., Just what I need.。 But after some attempts to give up, It has menu itemsMenuItem unlikeToolStripItem that kind may pass (a bill or inspection)ToolStripControlHost Load custom controls, I hope I'm the one with limited abilities., Anyway, I can't do it to get the custom controls toContextMenu upper, Haven't seen a text box on the native menu either、 Weird stuff like checkboxes, If you know how to extend the native menu, please do not hesitate to ask, thank you in advance!

Net, I still did a lot of different things, such as Form, Panel, UserControl, ContainerControl, Control, etc. I tried everything that seemed to be suitable for a container layer, and even replayed the idea on ToolStripDropDown, and finally chose Form, modified it a bit, and felt that it was ideal to achieve what I wanted: something calledFloatLayerBase Forms class, while applications that need to be displayed as a float layer inherit from FloatLayerBase for implementation, such as the following NumInputDemo implementation that accepts user input values.

Looks and features.

  • Does not cause the parent window to lose focus (a layer that does not steal focus is a good layer).

Of course, there is more than one side to a man.

There are other border styles , to be experienced by users themselves, with demos available at the end.

  • may Adjustable size handle available
  • may Tap and hold the client area to drag

Some other applications.

These are justdemo, Not that nice and powerful., The point is with thisFloatLayerBase, just (emphasis) may Implement your own floating application。

Instructions for use.

  1. Make sure the FloatLayerBase class is in the project ~crap. source code (computing) Here.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace AhDung.WinForm.Controls
{
    /// <summary>
     /// Floating layer base class
    /// </summary>
    //Update:201508251451
     //- Change the first control activation from OnShow to TopMost=true and remove the OnShow override.
     //- Solve the problem of child controls without focus boxes (focus dashed boxes, FocusCues)
    //Update:201508261806
     //- Redraw the bottom right corner to adjust the size of the handle, to solve the problem that the system self-draw is too close to the corner under XP and thus covers the border
    //-  backing Edge and corner dragging to change the size of the form
     //- Enable double buffering
    public class FloatLayerBase : Form
    {
        /// <summary>
         /// Mouse message filter
        /// </summary>
         // Since this form is WS_CHILD, no mouse clicks outside the form will be received
         // The purpose of this message filter is to let this form know about mouse clicks, and then handle them accordingly, depending on whether the mouse is clicked in an area other than this form.
        readonly AppMouseMessageHandler _mouseMsgFilter;

        /// <summary>
         /// Indicates whether this form has been ShowDialog
        /// </summary>
         // Since ShowDialog multiple times will cause OnLoad/OnShown to reenter, this flag needs to be set to determine when reentering
        bool _isShowDialogAgain;

         //Border-related fields
        BorderStyle _borderType;
        Border3DStyle _border3DStyle;
        ButtonBorderStyle _borderSingleStyle;
        Color _borderColor;
         int _borderWidth;//border width, used to calculate the corner offset when drawing SizeGrip

        /// <summary>
         /// Get the size of the drawn border (border width x2)
        /// </summary>
        [Browsable(false)]
        public Size BorderSize
        {
            get { return new Size(_borderWidth, _borderWidth); }
        }

        /// <summary>
         /// Indicates whether the form is in a resizable state
        /// </summary>
        [Browsable(false)]
        public bool CanReSize
        {
            get
            {
                return this.SizeGripStyle == System.Windows.Forms.SizeGripStyle.Show
                || (this.SizeGripStyle == System.Windows.Forms.SizeGripStyle.Auto && Modal);
            }
        }

        /// <summary>
         /// Get or set the border type
        /// </summary>
        [Description(" Get or set the border type。")]
        [DefaultValue(BorderStyle.Fixed3D)]
        public BorderStyle BorderType
        {
            get { return _borderType; }
            set
            {
                if (_borderType == value) { return; }
                _borderType = value;
                this.UpdateBorderWidth();
                Invalidate();
            }
        }

        /// <summary>
         /// Get or set the 3D border style
        /// </summary>
        [Description(" Get or set the 3D border style。")]
        [DefaultValue(Border3DStyle.RaisedInner)]
        public Border3DStyle Border3DStyle
        {
            get { return _border3DStyle; }
            set
            {
                if (_border3DStyle == value) { return; }
                _border3DStyle = value;
                this.UpdateBorderWidth();
                Invalidate();
            }
        }

        /// <summary>
         /// Get or set the line border style
        /// </summary>
        [Description(" Get or set the line border style。")]
        [DefaultValue(ButtonBorderStyle.Solid)]
        public ButtonBorderStyle BorderSingleStyle
        {
            get { return _borderSingleStyle; }
            set
            {
                if (_borderSingleStyle == value) { return; }
                _borderSingleStyle = value;
                this.UpdateBorderWidth();
                Invalidate();
            }
        }

        /// <summary>
         /// Get or set border color (only valid if border type is line)
        /// </summary>
        [Description(" Get or set the border color( Valid only if the border type is line)。")]
        [DefaultValue(typeof(Color), "DarkGray")]
        public Color BorderColor
        {
            get { return _borderColor; }
            set
            {
                if (_borderColor == value) { return; }
                _borderColor = value;
                Invalidate();
            }
        }

        protected override sealed CreateParams CreateParams
        {
            get
            {
                CreateParams prms = base.CreateParams;

                //prms.Style = 0;
                //prms.Style |= -2147483648;   //WS_POPUP
                 prms. Style |= 0x40000000;       //WS_CHILD Important, only CHILD forms don't steal focus from parent forms
                prms.Style |= 0x4000000;       //WS_CLIPSIBLINGS
                prms.Style |= 0x10000;         //WS_TABSTOP
                prms.Style &= ~0x40000;        //WS_SIZEBOX        dislodge
                prms.Style &= ~0x800000;       //WS_BORDER         dislodge
                prms.Style &= ~0x400000;       //WS_DLGFRAME       dislodge
                //prms.Style &= ~0x20000;      //WS_MINIMIZEBOX    dislodge
                //prms.Style &= ~0x10000;      //WS_MAXIMIZEBOX    dislodge

                prms.ExStyle = 0;
                 //prms. ExStyle |= 0x1;          //WS_EX_DLGMODALFRAME Stereo border
                //prms.ExStyle |= 0x8;         //WS_EX_TOPMOST
                prms.ExStyle |= 0x10000;       //WS_EX_CONTROLPARENT
                //prms.ExStyle |= 0x80;        //WS_EX_TOOLWINDOW
                //prms.ExStyle |= 0x100;       //WS_EX_WINDOWEDGE
                //prms.ExStyle |= 0x8000000;   //WS_EX_NOACTIVATE
                //prms.ExStyle |= 0x4;         //WS_EX_NOPARENTNOTIFY

                return prms;
            }
        }

         // Constructor
        public FloatLayerBase()
        {
             // Initialize the message filter. Adding and removing is responsible when showing/hiding
            _mouseMsgFilter = new AppMouseMessageHandler(this);

            this.DoubleBuffered = true;

            // Initializing the base class properties
            InitBaseProperties();

             // Initialize border-related
            _borderType = BorderStyle.Fixed3D;
            _border3DStyle = System.Windows.Forms.Border3DStyle.RaisedInner;
            _borderSingleStyle = ButtonBorderStyle.Solid;
            _borderColor = Color.DarkGray;
            this.UpdateBorderWidth();
        }

        protected override void OnLoad(EventArgs e)
        {
             // Prevents re-entry
            if (_isShowDialogAgain) { return; }

             // Mark the first ShowDialog
            if (Modal) { _isShowDialogAgain = true; }

             // Need to subtract two layers of border width to run exactly as designed, for unknown reasons
// Determined to be related to ControlBox, FormBorderStyle, but the exact connection is unknown
            if (!DesignMode)
            {
                Size size = SystemInformation.FrameBorderSize;
                this.Size -= size + size;// not may usefulnessClientSize, The latter will be readjusted to the window styleSize
            }
            base.OnLoad(e);
        }

        protected override void WndProc(ref Message m)
        {
             // When this form pops up as a ShowDialog, the Owner is Disable before receiving WM_SHOWWINDOW
             // So you need to Enable this message as soon as you receive it, otherwise both the Owner form and this form will be in an unresponsive state
            if (m.Msg == 0x18 && m.WParam != IntPtr.Zero && m.LParam == IntPtr.Zero
                && Modal && Owner != null && !Owner.IsDisposed)
            {
                if (Owner.IsMdiChild)
                {
                     // When Owner is an MDI child form, it is the MDI main form that is Disable
                     // and Parent will also point to the MDI main form, so it needs to be changed back to Owner so that the Location of the popup form will be relative to Owner and not MDIParent
                    NativeMethods.EnableWindow(Owner.MdiParent.Handle, true);
                     NativeMethods.SetParent(this. Handle, Owner.Handle);// You can only set Parent with the API because the modal form is TopLevel, . Net refuses to set Parent for the top-level form
                }
                else
                {
                    NativeMethods.EnableWindow(Owner.Handle, true);
                }
            }
            else if (m.Msg == 0x84 && this.CanReSize)//WM_NCHITTEST。 Implement edge and corner dragging to change the size of the form
            {
                Point pt = this.PointToClient(NativeMethods.MakePoint(m.LParam));
                Size size = this.ClientSize;
                if (new Rectangle(0, 0, 5, 5).Contains(pt))
                {
                    m.Result = (IntPtr)13;//HTTOPLEFT
                    return;
                }
                if (new Rectangle(5, 0, size.Width - 10, 3).Contains(pt))
                {
                    m.Result = (IntPtr)12;//HTTOP
                    return;
                }
                if (new Rectangle(size.Width - 5, 0, 5, 5).Contains(pt))
                {
                    m.Result = (IntPtr)14;//HTTOPRIGHT
                    return;
                }
                if (new Rectangle(size.Width - 3, 5, 3, size.Height - 5 - 16).Contains(pt))
                {
                    m.Result = (IntPtr)11;//HTRIGHT
                    return;
                }
                if (new Rectangle(5, size.Height - 3, size.Width - 5 - 16, 3).Contains(pt))
                {
                    m.Result = (IntPtr)15;//HTBOTTOM
                    return;
                }
                if (new Rectangle(0, size.Height - 5, 5, 5).Contains(pt))
                {
                    m.Result = (IntPtr)16;//HTBOTTOMLEFT
                    return;
                }
                if (new Rectangle(0, 5, 3, size.Height - 10).Contains(pt))
                {
                    m.Result = (IntPtr)10;//HTLEFT
                    return;
                }
            }
            base.WndProc(ref m);
        }

         /drawing borders
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);

             if (_borderType == BorderStyle.Fixed3D)// draws a 3D border
            {
                ControlPaint.DrawBorder3D(e.Graphics, ClientRectangle, Border3DStyle);
            }
             else if (_borderType == BorderStyle.FixedSingle)// draw a line border
            {
                ControlPaint.DrawBorder(e.Graphics, ClientRectangle, BorderColor, BorderSingleStyle);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (this.CanReSize)
            {
                Size clientSize = this.ClientSize;
                Rectangle rect = new Rectangle(clientSize.Width - 16, clientSize.Height - 16, 16, 16);

                 //Paint Handle
                DrawSizeGrip(e.Graphics, new Rectangle(rect.Location - BorderSize - new Size(1, 1), rect.Size));

                 // shave off the SizeGrip area to prevent the base class from drawing again
                e.Graphics.SetClip(rect, System.Drawing.Drawing2D.CombineMode.Exclude);
            }
            base.OnPaint(e);
            e.Graphics.ResetClip();
        }

        /// <summary>
         /// Draw SizeGrip (resize grip), subclasses can be overridden
        /// </summary>
        /// <param name="g"> plotter</param>
        /// <param name="rect"> Suggested areas for mapping</param>
        protected virtual void DrawSizeGrip(Graphics g, Rectangle rect)
        {
            Color backColor = this.BackColor;
            Brush color1 = new SolidBrush(ControlPaint.Dark(backColor));
            Brush color2 = new SolidBrush(ControlPaint.Dark(backColor, -0.5F));
            Brush color3 = new SolidBrush(ControlPaint.Dark(backColor, -0.1F));
            Brush color4 = new SolidBrush(ControlPaint.Light(backColor));
             Point pt = new Point(rect. X + 5, rect. Y + 5);//top-left offset

            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (j >= 3 - i)
                    {
                        g.FillRectangle(color1, new Rectangle(pt.X + j * 3, pt.Y + i * 3, 1, 1));
                        g.FillRectangle(color2, new Rectangle(pt.X + j * 3 + 1, pt.Y + i * 3, 1, 1));
                        g.FillRectangle(color3, new Rectangle(pt.X + j * 3, pt.Y + i * 3 + 1, 1, 1));
                        g.FillRectangle(color4, new Rectangle(pt.X + j * 3 + 1, pt.Y + i * 3 + 1, 1, 1));
                    }
                }
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            if (!DesignMode)
            {
                if (Visible)
                {
                     // Make the focus child control have a focus box, rewriting ShowFocusCues is trickier
                    NativeMethods.SendMessage(this.Handle, 0x127/*WM_CHANGEUISTATE*/, (IntPtr)0x10002/*UISF_HIDEFOCUS | UIS_CLEAR*/, IntPtr.Zero);
                    NativeMethods.SendMessage(this.Handle, 0x128/*WM_UPDATEUISTATE*/, (IntPtr)0x10002/*UISF_HIDEFOCUS | UIS_CLEAR*/, IntPtr.Zero);

                     //Add mouse message filter to start capturing after /display
                    Application.AddMessageFilter(_mouseMsgFilter);
                }
                else
                {
                     //hide removes the filter. The reason for not putting it in Dispose is to remove the filter as early as possible
                    Application.RemoveMessageFilter(_mouseMsgFilter);
                }
            }
            base.OnVisibleChanged(e);
        }

         // Implementing the form client area dragging
         // It's more of a pain to implement this in WndProc, so put it here to do
        protected override void OnMouseDown(MouseEventArgs e)
        {
             // Make mouse clicks on the client area have the same effect as clicks on the title bar, thus enabling client area dragging
            NativeMethods.ReleaseCapture();
            NativeMethods.SendMessage(Handle, 0xA1/*WM_NCLBUTTONDOWN*/, (IntPtr)2/*CAPTION*/, IntPtr.Zero);

            base.OnMouseDown(e);
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="control"> Displayed below this control</param>
        public DialogResult ShowDialog(Control control)
        {
            return ShowDialog(control, 0, control.Height);
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="control"> Controls that trigger pop-up forms</param>
        /// <param name="offsetX"> opposecontrol Horizontal offset</param>
        /// <param name="offsetY"> opposecontrol vertical offset</param>
        public DialogResult ShowDialog(Control control, int offsetX, int offsetY)
        {
            return ShowDialog(control, new Point(offsetX, offsetY));
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="control"> Controls that trigger pop-up forms</param>
        /// <param name="offset"> opposecontrol drift</param>
        public DialogResult ShowDialog(Control control, Point offset)
        {
            return this.ShowDialogInternal(control, offset);
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="item"> Displayed below this toolbar item</param>
        public DialogResult ShowDialog(ToolStripItem item)
        {
            return ShowDialog(item, 0, item.Height);
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="item"> Triggers a toolbar item on the popup form</param>
        /// <param name="offsetX"> opposeitem Horizontal offset</param>
        /// <param name="offsetY"> opposeitem vertical offset</param>
        public DialogResult ShowDialog(ToolStripItem item, int offsetX, int offsetY)
        {
            return ShowDialog(item, new Point(offsetX, offsetY));
        }

        /// <summary>
         /// Displayed as a modal form
        /// </summary>
        /// <param name="item"> Triggers a toolbar item on the popup form</param>
        /// <param name="offset"> opposeitem drift</param>
        public DialogResult ShowDialog(ToolStripItem item, Point offset)
        {
            return this.ShowDialogInternal(item, offset);
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="control"> Displayed below this control</param>
        public void Show(Control control)
        {
            Show(control, 0, control.Height);
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="control"> Controls that trigger pop-up forms</param>
        /// <param name="offsetX"> opposecontrol Horizontal offset</param>
        /// <param name="offsetY"> opposecontrol vertical offset</param>
        public void Show(Control control, int offsetX, int offsetY)
        {
            Show(control, new Point(offsetX, offsetY));
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="control"> Controls that trigger pop-up forms</param>
        /// <param name="offset"> opposecontrol drift</param>
        public void Show(Control control, Point offset)
        {
            this.ShowInternal(control, offset);
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="item"> Displayed below this toolbar</param>
        public void Show(ToolStripItem item)
        {
            Show(item, 0, item.Height);
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="item"> Triggers a toolbar item on the popup form</param>
        /// <param name="offsetX"> opposeitem Horizontal offset</param>
        /// <param name="offsetY"> opposeitem vertical offset</param>
        public void Show(ToolStripItem item, int offsetX, int offsetY)
        {
            Show(item, new Point(offsetX, offsetY));
        }

        /// <summary>
         /// Displaying the form
        /// </summary>
        /// <param name="item"> Triggers a toolbar item on the popup form</param>
        /// <param name="offset"> opposeitem drift</param>
        public void Show(ToolStripItem item, Point offset)
        {
            this.ShowInternal(item, offset);
        }

        /// <summary>
        /// ShowDialog inside (part, section) approach
        /// </summary>
        private DialogResult ShowDialogInternal(Component controlOrItem, Point offset)
        {
             //Fast successive popups of this form will likely encounter another popup if it has not yet been Hide, which will raise an exception and needs to be handled.
            if (this.Visible) { return System.Windows.Forms.DialogResult.None; }

            this.SetLocationAndOwner(controlOrItem, offset);
            return base.ShowDialog();
        }

        /// <summary>
        /// Show inside (part, section) approach
        /// </summary>
        private void ShowInternal(Component controlOrItem, Point offset)
        {
             if (this. Visible) { return;  }// See ShowDialogInternal for the reason

            this.SetLocationAndOwner(controlOrItem, offset);
            base.Show();
        }

        /// <summary>
         /// Set coordinates and owner
        /// </summary>
        /// <param name="controlOrItem"> Controls or toolbar items</param>
        /// <param name="offset"> relative offset</param>
        private void SetLocationAndOwner(Component controlOrItem, Point offset)
        {
            Point pt = Point.Empty;

            if (controlOrItem is ToolStripItem)
            {
                ToolStripItem item = (ToolStripItem)controlOrItem;
                pt.Offset(item.Bounds.Location);
                controlOrItem = item.Owner;
            }

            Control c = (Control)controlOrItem;
            pt.Offset(GetControlLocationInForm(c));
            pt.Offset(offset);
            this.Location = pt;

            // set upOwner properties together withShow[Dialog](Owner) differing, properOwner beMDIChild time, The latter will changeOwner because ofMDIParent
            this.Owner = c.FindForm();
        }

        /// <summary>
         /// Get the coordinates of the control in the form
        /// </summary>
        private static Point GetControlLocationInForm(Control c)
        {
            Point pt = c.Location;
            while (!((c = c.Parent) is Form))
            {
                pt.Offset(c.Location);
            }
            return pt;
        }

        /// <summary>
        ///  update Border width
        /// </summary>
        private void UpdateBorderWidth()
        {
            if (_borderType == BorderStyle.None)
            {
                _borderWidth = 0;
            }
            else if (_borderType == BorderStyle.Fixed3D)
            {
                if (_border3DStyle == System.Windows.Forms.Border3DStyle.Adjust) { _borderWidth = 0; }
                else if (_border3DStyle == System.Windows.Forms.Border3DStyle.Flat) { _borderWidth = 1; }
                else { _borderWidth = CountOneInBits((uint)_border3DStyle); }
            }
            else
            {
                if (_borderSingleStyle == ButtonBorderStyle.None) { _borderWidth = 0; }
                else if (_borderSingleStyle == ButtonBorderStyle.Outset) { _borderWidth = 2; }
                else { _borderWidth = 1; }
            }
        }

        /// <summary>
         /// Counting the number of 1's in binary
        /// </summary>
        private static int CountOneInBits(uint num)
        {
            int count = 0;
            while (num != 0)
            {
                num &= num - 1;
                count++;
            }
            return count;
        }

        #region  Shield base classes that have a significant impact on this class approach harmony properties

        /// <summary>
        ///  Initializing some base classes properties
        /// </summary>
        private void InitBaseProperties()
        {
             base. ControlBox = false;                            /Important
            // It has to be.SizableToolWindow ability backing While resizing, free fromSystemInformation.MinWindowTrackSize restrictions
            base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
             base. Text = string. Empty;                           /Important
            base.HelpButton = false;
            base.Icon = null;
            base.IsMdiContainer = false;
            base.MaximizeBox = false;
            base.MinimizeBox = false;
            base.ShowIcon = false;
            base.ShowInTaskbar = false;
            base.StartPosition = FormStartPosition.Manual;     // important
             base. TopMost = true;  // Make this form automatically activate the first control after displaying it like a normal form
            base.WindowState = FormWindowState.Normal;
        }

        // shieldogen approach
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Please use another reload!", true)]
        public new DialogResult ShowDialog() { throw new NotImplementedException(); }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Please use another reload!", true)]
        public new DialogResult ShowDialog(IWin32Window owner) { throw new NotImplementedException(); }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Please use another reload!", true)]
        public new void Show() { throw new NotImplementedException(); }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Please use another reload!", true)]
        public new void Show(IWin32Window owner) { throw new NotImplementedException(); }

        // shieldogen properties
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool ControlBox { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" To set the border, use theBorder (statistics) correlation properties!", true)]
        public new FormBorderStyle FormBorderStyle { get { return System.Windows.Forms.FormBorderStyle.SizableToolWindow; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public override sealed string Text { get { return string.Empty; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool HelpButton { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new Image Icon { get { return null; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool IsMdiContainer { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool MaximizeBox { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool MinimizeBox { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool ShowIcon { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool ShowInTaskbar { get { return false; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new FormStartPosition StartPosition { get { return FormStartPosition.Manual; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new bool TopMost { get { return true; } set { } }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [Obsolete(" Disable the properties!", true)]
        public new FormWindowState WindowState { get { return FormWindowState.Normal; } set { } }

        #endregion

        /// <summary>
         /// Program mouse message filter
        /// </summary>
        private class AppMouseMessageHandler : IMessageFilter
        {
            readonly FloatLayerBase _layerForm;

            public AppMouseMessageHandler(FloatLayerBase layerForm)
            {
                _layerForm = layerForm;
            }

            public bool PreFilterMessage(ref Message m)
            {
// Hide this form if you click the mouse outside this form
                 // If you want to make this form disappear even when clicking on non-client areas such as title bars, scrollbars, etc., just uncomment 0xA1
                // This example is based on the coordinates, also may Change to based on the handle, But consider the controls of your children and grandchildren
                 //The reason why the API is used instead of Form.DesktopBounds is because the latter is unreliable
                if ((m.Msg == 0x201/*|| m.Msg==0xA1*/)
                    && _layerForm.Visible && !NativeMethods.GetWindowRect(_layerForm.Handle).Contains(MousePosition))
                {
                     _layerForm.Hide();// The reason for not Closing is that the caller should be responsible for destroying
                }

                return false;
            }
        }

        /// <summary>
         /// API wrapper class
        /// </summary>
        private static class NativeMethods
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

            [DllImport("user32.dll")]
            public static extern bool ReleaseCapture();

            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

            [DllImport("user32.dll", SetLastError = true)]
            private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;

                public static explicit operator Rectangle(RECT rect)
                {
                    return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
                }
            }

            public static Rectangle GetWindowRect(IntPtr hwnd)
            {
                RECT rect;
                GetWindowRect(hwnd, out rect);
                return (Rectangle)rect;
            }

            public static int LOWORD(IntPtr n)
            {
                return ((int)n) & 0xFFFF;
            }

            public static int HIWORD(IntPtr n)
            {
                return (((int)n) >> 16) & 0xFFFF;
            }

            public static Point MakePoint(IntPtr n)
            {
                return new Point(LOWORD(n), HIWORD(n));
            }
        }
    }
}
  1. New Inherited Form, Choose to inherit fromFloatLayerBase kind; too may Create a new normal form, Then put the base class byForm Change toFloatLayerBase
  2. In the designer and source code (computing) create floating apps
  3. Use it where you need it。 About use, Let's take a lookFloatLayerBase some of the public members: topmost4 piece properties It's all about borders, The borders are there in total3 form, three-dimensional、 linear、 not, due toBorderType designate; When in three-dimensional form, due toBorder3DStyle Specify a specific style; When linear, due toBorderSingleStyle harmonyBorderColor Specify specific line types and colors, respectively。 originalForm.FormBorderStyle properties Blocked, Do not allow subclasses to access, There are also a number of originalForm of properties Also blocked, The reasons are all in source code (computing) Li (surname)。 additionally, originalForm.SizeGripStyle Use as usual, Whether it is allowed to resize the floating layer depends on it approach Just say itShow harmonyShowDialog, Obviously they are used for de-modalization/ The pattern shows the floating layer, The big difference between the two in the call angle is, The former does not block the code, The latter will, In practice, it is chosen according to the situation。 each approach From the parameters and dividedControl harmonyToolStripItem There are two types, are all meanings for popping a floating layer from what control, The former acceptsButton、TextBox and other controls( Cannot be passed inForm, The consequences will be unpleasant.), The latter accepts the items above the toolbar, for exampleToolStripButton、ToolStripTextBox class。 heavy load (on a truck) may Designated relativecontrol perhapsitem The offset position of, The default is incontrol/item a floating layer pops up below。 Finally eitherShow Still isShowDialog Bounce out of the floating layer, all may Make it disappear by clicking the mouse elsewhere, as is the case with the right-click menu, A few words of clarification are needed here:
    • Make the floating layer disappear when the mouse will only click in a form within this program. Tapping on windows outside the program, desktop, taskbar and these do not. The reason why this is necessary is because to do exactly what the right-click menu does with global mouse sensitivity would require global hooks, which would increase the amount of code (performance aside, I don't presume to say without testing), and I don't think global sensitivity is necessary
    • The floating layer disappears by calling the Hide method, so for a floating layer opened modally, it returns DialogResult.Cancel, which is what the .net design of modal dialogs makes possible; when a modal dialog is Hide or Close, it is Cancel that is returned. This is also a reminder to callers to always consider the case of having a return Cancel when using modal dialogs, not limited to this example, but all dialogs

    originalShow()/Show(IWin32Window) harmonyShowDialog()/ShowDialog(IWin32Window) Blocked, The reasons for this can be found in source code (computing)。

// properties
public BorderStyle BorderType { get; set; }
public Border3DStyle Border3DStyle { get; set; }
public ButtonBorderStyle BorderSingleStyle { get; set; }
public Color BorderColor { get; set; }

// approach
public void Show(Control control);
public void Show(Control control, Point offset);
public void Show(Control control, int offsetX, int offsetY);
public void Show(ToolStripItem item);
public void Show(ToolStripItem item, Point offset);
public void Show(ToolStripItem item, int offsetX, int offsetY);
public DialogResult ShowDialog(Control control);
public DialogResult ShowDialog(Control control, Point offset);
public DialogResult ShowDialog(Control control, int offsetX, int offsetY);
public DialogResult ShowDialog(ToolStripItem item);
public DialogResult ShowDialog(ToolStripItem item, Point offset);
public DialogResult ShowDialog(ToolStripItem item, int offsetX, int offsetY);

Other.

PopupFormBase was used as the class name during writing, and was changed to the current FloatLayerBase at the last moment of release, so there may still be subclasses, method names, etc. in the demo based on the original name.

Demo Download.

http://pan.baidu.com/s/1mgnGPGc

There's a Tester inside for you to experience.

-Bunbi-


Recommended>>
1、Blockchain industryspecific terminology sentiment category
2、Travel sites use big data to kill the people who know you best hurt you the most
3、May 16 Summary of Quality Candy Information
4、The most important thing is that you can see what you are doing The cheat hanging software for all of us The most important thing is that you have to be able to use it
5、Californias Largest Hospital Never Deletes Data Heres How They Do It

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号