예제 #1
0
        /// <summary>
        /// Shows the specified Form as a popup window, keeping the
        /// Owner's title bar active and preparing to cancel the popup
        /// should the user click anywhere outside the popup window.
        /// <para>Typical code to use this message is as follows:</para>
        /// <code>
        ///    frmPopup popup = new frmPopup();
        ///    Point location = this.PointToScreen(new Point(button1.Left, button1.Bottom));
        ///    popupHelper.ShowPopup(this, popup, location);
        /// </code>
        /// <para>Put as much initialisation code as possible
        /// into the popup form's constructor, rather than the <see cref="System.Windows.Forms.Load"/>
        /// event as this will improve visual appearance.</para>
        /// </summary>
        /// <param name="Owner">Main form which owns the popup</param>
        /// <param name="Popup">Window to show as a popup</param>
        /// <param name="v">Location relative to the screen to show the popup at.</param>
        public void ShowDropDown(Form Owner, Form DropDown, Point Location)
        {
            _owner    = Owner;
            _dropDown = DropDown;
            Application.AddMessageFilter(_filter);                              // Start checking for the popup being cancelled
            DropDown.StartPosition = FormStartPosition.Manual;                  // Set the location of the popup form:
            DropDown.Location      = Location;
            Owner.AddOwnedForm(DropDown);                                       // Make it owned by the window that's displaying it:
            DropDownClosedHandler = new EventHandler(Popup_Closed);             // Respond to the Closed event in case the popup is closed by its own internal means
            DropDown.Closed      += DropDownClosedHandler;

            _dropDownShowing = true;                                                                            // Show the popup:
            DropDown.Show();
            DropDown.Activate();

            // A little bit of fun.  We've shown the popup, but because we've kept the main window's
            // title bar in focus the tab sequence isn't quite right.  This can be fixed by sending a tab,
            // but that on its own would shift focus to the second control in the form.  So send a tab,
            // followed by a reverse-tab.
            UIApiCalls.keybd_event((byte)Keys.Tab, 0, 0, 0);
            UIApiCalls.keybd_event((byte)Keys.Tab, 0, UIApiCalls.KEYEVENTF_KEYUP, 0);
            UIApiCalls.keybd_event((byte)Keys.ShiftKey, 0, 0, 0);
            UIApiCalls.keybd_event((byte)Keys.Tab, 0, 0, 0);
            UIApiCalls.keybd_event((byte)Keys.Tab, 0, UIApiCalls.KEYEVENTF_KEYUP, 0);
            UIApiCalls.keybd_event((byte)Keys.ShiftKey, 0, UIApiCalls.KEYEVENTF_KEYUP, 0);

            _filter.DropDown = DropDown;                                                                // Start filtering for mouse clicks outside the popup
        }
예제 #2
0
        /// <summary>
        /// Subclasses the owning form's existing Window Procedure to enables the
        /// title bar to remain active when a popup is show, and to detect if
        /// the user clicks onto another application whilst the popup is visible.
        /// </summary>
        /// <param name="m">Window Procedure Message</param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (DropDownShowing)
            {
                if (m.Msg == UIApiCalls.WM_NCACTIVATE)
                {
                    if (((int)m.WParam) == 0)                                                          // Check if the title bar will made inactive:
                    {                                                                                  // Note it's no good to try and consume this message; if you try to do that you'll end up with windows
                        UIApiCalls.SendMessage(this.Handle, UIApiCalls.WM_NCACTIVATE, 1, IntPtr.Zero); // If so reactivate it.
                    }
                }
                else if (m.Msg == UIApiCalls.WM_ACTIVATEAPP)
                {
                    if ((int)m.WParam == 0)                                                                                             // Check if the application is being deactivated.
                    {
                        CloseDropDown();                                                                                                // It is so cancel the popup:
                        UIApiCalls.PostMessage(this.Handle, UIApiCalls.WM_NCACTIVATE, 0, IntPtr.Zero);                                  // And put the title bar into the inactive state:
                    }
                }
            }
        }