Exemplo n.º 1
0
        // Returns true if the message should be dropped.
        internal static IntPtr SendMessage(ref MSG msg, out bool drop, out bool quit)
        {
            drop = false;
            quit = false;
            Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);

            if (Application.FilterMessage(ref m))
            {
                drop = true;
                return(IntPtr.Zero);
            }

            switch ((Msg)msg.message)
            {
            case Msg.WM_KEYDOWN:
            case Msg.WM_SYSKEYDOWN:
            case Msg.WM_CHAR:
            case Msg.WM_SYSCHAR:
            case Msg.WM_KEYUP:
            case Msg.WM_SYSKEYUP:
                Control c = Control.FromHandle(msg.hwnd);

                // If we have a control with keyboard capture (usually a *Strip)
                // give it the message, and then drop the message
                if (keyboard_capture != null)
                {
                    // WM_SYSKEYUP does not make it into ProcessCmdKey, so do it here
                    if (msg.message == Msg.WM_SYSKEYDOWN)
                    {
                        if (m.WParam.ToInt32() == (int)Keys.Menu)
                        {
                            keyboard_capture.GetTopLevelToolStrip().Dismiss(ToolStripDropDownCloseReason.Keyboard);
                            drop = true;
                            return(IntPtr.Zero);
                        }
                    }

                    m.HWnd = keyboard_capture.Handle;

                    switch (keyboard_capture.PreProcessControlMessageInternal(ref m))
                    {
                    case PreProcessControlState.MessageProcessed:
                        drop = true;
                        return(IntPtr.Zero);

                    case PreProcessControlState.MessageNeeded:
                    case PreProcessControlState.MessageNotNeeded:
                        if (((msg.message == Msg.WM_KEYDOWN || msg.message == Msg.WM_CHAR) && keyboard_capture != null && !keyboard_capture.ProcessControlMnemonic((char)m.WParam)))
                        {
                            if (c == null || !ControlOnToolStrip(c))
                            {
                                drop = true;
                                return(IntPtr.Zero);
                            }
                            m.HWnd = msg.hwnd;
                        }
                        else
                        {
                            drop = true;
                            return(IntPtr.Zero);
                        }
                        break;
                    }
                }

                if (((c != null) && c.PreProcessControlMessageInternal(ref m) != PreProcessControlState.MessageProcessed) ||
                    (c == null))
                {
                    goto default;
                }
                return(new IntPtr(1));                        // Drop

            case Msg.WM_LBUTTONDOWN:
            case Msg.WM_MBUTTONDOWN:
            case Msg.WM_RBUTTONDOWN:
                if (keyboard_capture != null)
                {
                    Control c2 = Control.FromHandle(msg.hwnd);

                    // The target is not a winforms control (an embedded control, perhaps), so
                    // release everything
                    if (c2 == null)
                    {
                        ToolStripManager.FireAppClicked();
                        goto default;
                    }

                    // Skip clicks on owner windows, eg. expanded ComboBox
                    if (Control.IsChild(keyboard_capture.Handle, msg.hwnd))
                    {
                        goto default;
                    }

                    // Close any active toolstrips drop-downs if we click outside of them,
                    // but also don't close them all if we click outside of the top-most
                    // one, but into its owner.
                    Point c2_point = c2.PointToScreen(new Point(
                                                          (int)(short)(m.LParam.ToInt32() & 0xffff),
                                                          (int)(short)(m.LParam.ToInt32() >> 16)));
                    while (keyboard_capture != null && !keyboard_capture.ClientRectangle.Contains(keyboard_capture.PointToClient(c2_point)))
                    {
                        keyboard_capture.Dismiss();
                    }
                }
                goto default;

            case Msg.WM_QUIT:
                quit = true;                         // make sure we exit
                break;

            default:
                XplatUI.TranslateMessage(ref msg);
                return(XplatUI.DispatchMessage(ref msg));
            }

            return(IntPtr.Zero);
        }
Exemplo n.º 2
0
        internal static void RunLoop(bool Modal, ApplicationContext context)
        {
            Queue              toplevels;
            MSG                msg;
            Object             queue_id;
            MWFThread          thread;
            ApplicationContext previous_thread_context;

            thread = MWFThread.Current;

            /*
             * There is a NotWorking test for this, but since we are using this method both for Form.ShowDialog as for ApplicationContexts we'll
             * fail on nested ShowDialogs, so disable the check for the moment.
             */
            //if (thread.MessageLoop) {
            //        throw new InvalidOperationException ("Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead.");
            //}

            msg = new MSG();

            if (context == null)
            {
                context = new ApplicationContext();
            }

            previous_thread_context = thread.Context;
            thread.Context          = context;

            if (context.MainForm != null)
            {
                context.MainForm.is_modal = Modal;
                context.MainForm.context  = context;
                context.MainForm.closing  = false;
                context.MainForm.Visible  = true;                       // Cannot use Show() or scaling gets confused by menus
                // XXX the above line can be used to close the form. another problem with our handling of Show/Activate.
                if (context.MainForm != null)
                {
                    context.MainForm.Activate();
                }
            }

                        #if DebugRunLoop
            Console.WriteLine("Entering RunLoop(Modal={0}, Form={1})", Modal, context.MainForm != null ? context.MainForm.ToString() : "NULL");
                        #endif

            if (Modal)
            {
                toplevels = new Queue();
                DisableFormsForModalLoop(toplevels, context);

                // FIXME - need activate?
                /* make sure the MainForm is enabled */
                if (context.MainForm != null)
                {
                    XplatUI.EnableWindow(context.MainForm.Handle, true);
                    XplatUI.SetModal(context.MainForm.Handle, true);
                }
            }
            else
            {
                toplevels = null;
            }

            queue_id           = XplatUI.StartLoop(Thread.CurrentThread);
            thread.MessageLoop = true;

            bool quit = false;

            while (!quit && XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0))
            {
                Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);

                if (Application.FilterMessage(ref m))
                {
                    continue;
                }

                switch ((Msg)msg.message)
                {
                case Msg.WM_KEYDOWN:
                case Msg.WM_SYSKEYDOWN:
                case Msg.WM_CHAR:
                case Msg.WM_SYSCHAR:
                case Msg.WM_KEYUP:
                case Msg.WM_SYSKEYUP:
                    Control c = Control.FromHandle(msg.hwnd);

                    // If we have a control with keyboard capture (usually a *Strip)
                    // give it the message, and then drop the message
                    if (keyboard_capture != null)
                    {
                        // WM_SYSKEYUP does not make it into ProcessCmdKey, so do it here
                        if ((Msg)m.Msg == Msg.WM_SYSKEYDOWN)
                        {
                            if (m.WParam.ToInt32() == (int)Keys.Menu)
                            {
                                keyboard_capture.GetTopLevelToolStrip().Dismiss(ToolStripDropDownCloseReason.Keyboard);
                                continue;
                            }
                        }

                        m.HWnd = keyboard_capture.Handle;

                        switch (keyboard_capture.PreProcessControlMessageInternal(ref m))
                        {
                        case PreProcessControlState.MessageProcessed:
                            continue;

                        case PreProcessControlState.MessageNeeded:
                        case PreProcessControlState.MessageNotNeeded:
                            if (((m.Msg == (int)Msg.WM_KEYDOWN || m.Msg == (int)Msg.WM_CHAR) && !keyboard_capture.ProcessControlMnemonic((char)m.WParam)))
                            {
                                if (c == null || !ControlOnToolStrip(c))
                                {
                                    continue;
                                }
                                else
                                {
                                    m.HWnd = msg.hwnd;
                                }
                            }
                            else
                            {
                                continue;
                            }

                            break;
                        }
                    }

                    if (((c != null) && c.PreProcessControlMessageInternal(ref m) != PreProcessControlState.MessageProcessed) ||
                        (c == null))
                    {
                        goto default;
                    }
                    break;

                case Msg.WM_LBUTTONDOWN:
                case Msg.WM_MBUTTONDOWN:
                case Msg.WM_RBUTTONDOWN:
                    if (keyboard_capture != null)
                    {
                        Control c2 = Control.FromHandle(msg.hwnd);
                        var     contextMenuStrip = keyboard_capture.GetTopLevelToolStrip() as ContextMenuStrip;

                        // The target is not a winforms control (an embedded control, perhaps), so
                        // release everything
                        if (c2 == null)
                        {
                            ToolStripManager.FireAppClicked();
                            goto default;
                        }

                        // Skip clicks on owner windows, eg. expanded ComboBox
                        if (Control.IsChild(keyboard_capture.Handle, msg.hwnd))
                        {
                            goto default;
                        }

                        // Close any active toolstrips drop-downs if we click outside of them,
                        // but also don't close them all if we click outside of the top-most
                        // one, but into its owner.
                        Point c2_point = c2.PointToScreen(new Point(
                                                              (int)(short)(m.LParam.ToInt32() & 0xffff),
                                                              (int)(short)(m.LParam.ToInt32() >> 16)));
                        while (keyboard_capture != null && !keyboard_capture.ClientRectangle.Contains(keyboard_capture.PointToClient(c2_point)))
                        {
                            keyboard_capture.Dismiss();
                        }

                        var iter_OwnerItem = (c2 as ToolStripDropDown)?.OwnerItem;
                        while (iter_OwnerItem != null && iter_OwnerItem.Owner != contextMenuStrip)
                        {
                            iter_OwnerItem = iter_OwnerItem.OwnerItem;
                        }
                        var contextMenuStripIsOwnerOf_c2 = (iter_OwnerItem != null);

                        if (c2 != contextMenuStrip && !contextMenuStripIsOwnerOf_c2)
                        {
                            contextMenuStrip.Dismiss();
                        }
                    }
                    goto default;

                case Msg.WM_QUIT:
                    quit = true;                     // make sure we exit
                    break;

                default:
                    XplatUI.TranslateMessage(ref msg);
                    XplatUI.DispatchMessage(ref msg);
                    break;
                }

                // If our Form doesn't have a handle anymore, it means it was destroyed and we need to *wait* for WM_QUIT.
                if ((context.MainForm != null) && (!context.MainForm.IsHandleCreated))
                {
                    continue;
                }

                // Handle exit, Form might have received WM_CLOSE and set 'closing' in response.
                if ((context.MainForm != null) && (context.MainForm.closing || (Modal && !context.MainForm.Visible)))
                {
                    if (!Modal)
                    {
                        XplatUI.PostQuitMessage(0);
                    }
                    else
                    {
                        break;
                    }
                }
            }
                        #if DebugRunLoop
            Console.WriteLine("   RunLoop loop left");
                        #endif

            thread.MessageLoop = false;
            XplatUI.EndLoop(Thread.CurrentThread);

            if (Modal)
            {
                Form old = context.MainForm;

                context.MainForm = null;

                EnableFormsForModalLoop(toplevels, context);

                if (old != null && old.IsHandleCreated)
                {
                    XplatUI.SetModal(old.Handle, false);
                }
                                #if DebugRunLoop
                Console.WriteLine("   Done with the SetModal");
                                #endif
                old.RaiseCloseEvents(true, false);
                old.is_modal = false;
            }

                        #if DebugRunLoop
            Console.WriteLine("Leaving RunLoop(Modal={0}, Form={1})", Modal, context.MainForm != null ? context.MainForm.ToString() : "NULL");
                        #endif

            if (context.MainForm != null)
            {
                context.MainForm.context = null;
                context.MainForm         = null;
            }

            thread.Context = previous_thread_context;

            if (!Modal)
            {
                thread.Exit();
            }
        }
Exemplo n.º 3
0
        // Returns true if the message should be dropped.
        internal static IntPtr SendMessage(ref MSG msg, out bool drop, out bool quit)
        {
            drop = false;
            quit = false;
            Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);

            if (Application.FilterMessage(ref m))
            {
                drop = true;
                return(IntPtr.Zero);
            }

            switch ((Msg)msg.message)
            {
            case Msg.WM_KEYDOWN:
            case Msg.WM_SYSKEYDOWN:
            case Msg.WM_CHAR:
            case Msg.WM_SYSCHAR:
            case Msg.WM_KEYUP:
            case Msg.WM_SYSKEYUP:
                Control c = Control.FromHandle(msg.hwnd);

                // If we have a control with keyboard capture (usually a *Strip)
                // give it the message, and then drop the message
                if (keyboard_capture != null)
                {
                    // WM_SYSKEYUP does not make it into ProcessCmdKey, so do it here
                    if (msg.message == Msg.WM_SYSKEYDOWN)
                    {
                        if (m.WParam.ToInt32() == (int)Keys.Menu)
                        {
                            keyboard_capture.GetTopLevelToolStrip().Dismiss(ToolStripDropDownCloseReason.Keyboard);
                            drop = true;
                            return(IntPtr.Zero);
                        }
                    }

                    m.HWnd = keyboard_capture.Handle;

                    switch (keyboard_capture.PreProcessControlMessageInternal(ref m))
                    {
                    case PreProcessControlState.MessageProcessed:
                        drop = true;
                        return(IntPtr.Zero);

                    case PreProcessControlState.MessageNeeded:
                    case PreProcessControlState.MessageNotNeeded:
                        if (((msg.message == Msg.WM_KEYDOWN || msg.message == Msg.WM_CHAR) && !keyboard_capture.ProcessControlMnemonic((char)m.WParam)))
                        {
                            if (c == null || !ControlOnToolStrip(c))
                            {
                                drop = true;
                                return(IntPtr.Zero);
                            }
                            m.HWnd = msg.hwnd;
                        }
                        else
                        {
                            drop = true;
                            return(IntPtr.Zero);
                        }
                        break;
                    }
                }

                if (((c != null) && c.PreProcessControlMessageInternal(ref m) != PreProcessControlState.MessageProcessed) ||
                    (c == null))
                {
                    goto default;
                }
                break;

            case Msg.WM_LBUTTONDOWN:
            case Msg.WM_MBUTTONDOWN:
            case Msg.WM_RBUTTONDOWN:
                if (keyboard_capture != null)
                {
                    Control c2 = Control.FromHandle(msg.hwnd);

                    // the target is not a winforms control (an embedded control, perhaps), so
                    // release everything
                    if (c2 == null)
                    {
                        ToolStripManager.FireAppClicked();
                        goto default;
                    }

                    // If we clicked a ToolStrip, we have to make sure it isn't
                    // the one we are on, or any of its parents or children
                    // If we clicked off the dropped down menu, release everything
                    if (c2 is ToolStrip)
                    {
                        if ((c2 as ToolStrip).GetTopLevelToolStrip() != keyboard_capture.GetTopLevelToolStrip())
                        {
                            ToolStripManager.FireAppClicked();
                        }
                    }
                    else
                    {
                        Control dropDownParent = c2.Parent;

                        while (dropDownParent != null)
                        {
                            if (dropDownParent is ToolStripDropDown)
                            {
                                if ((dropDownParent as ToolStripDropDown).GetTopLevelToolStrip() == keyboard_capture.GetTopLevelToolStrip())
                                {
                                    goto default;
                                }
                                break;
                            }

                            dropDownParent = dropDownParent.Parent;
                        }

                        if (!Control.IsChild(keyboard_capture.Handle, c2.Handle))
                        {
                            ToolStripManager.FireAppClickedInternal();
                            goto default;
                        }

                        if (c2.TopLevelControl == null)
                        {
                            goto default;
                        }

                        ToolStripManager.FireAppClicked();
                    }
                }

                goto default;

            case Msg.WM_QUIT:
                quit = true;                         // make sure we exit
                break;

            default:
                XplatUI.TranslateMessage(ref msg);
                return(XplatUI.DispatchMessage(ref msg));
            }

            return(IntPtr.Zero);
        }