protected override void OnClick(EventArgs e) { if (!this.Enabled) { return; } if (this.HasDropDownItems) { base.OnClick(e); return; } if (this.OwnerItem is ToolStripDropDownItem) { (this.OwnerItem as ToolStripDropDownItem).OnDropDownItemClicked(new ToolStripItemClickedEventArgs(this)); } if (this.IsOnDropDown) { ToolStrip ts = this.GetTopLevelToolStrip(); if (ts != null) { ts.Dismiss(ToolStripDropDownCloseReason.ItemClicked); } } if (this.IsMdiWindowListEntry) { this.mdi_client_form.MdiParent.MdiContainer.ActivateChild(this.mdi_client_form); return; } if (this.check_on_click) { this.Checked = !this.Checked; } base.OnClick(e); if (!this.IsOnDropDown && !this.HasDropDownItems) { ToolStrip ts = this.GetTopLevelToolStrip(); if (ts != null) { ts.Dismiss(ToolStripDropDownCloseReason.ItemClicked); } } }
protected override void OnClick(EventArgs e) { if (this.check_on_click) { this.Checked = !this.Checked; } base.OnClick(e); ToolStrip ts = this.GetTopLevelToolStrip(); if (ts != null) { ts.Dismiss(ToolStripDropDownCloseReason.ItemClicked); } }
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(); } }
// 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); }
// 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.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 (c != null && !c.Enabled) { break; } // If we have a control with keyboard capture (usually a *Strip) // give it the message, and then drop the message if (keyboard_capture != null && c != keyboard_capture && !Control.IsChild(keyboard_capture.Handle, c?.Handle ?? IntPtr.Zero)) { // 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; } goto default; case Msg.WM_LBUTTONDOWN: case Msg.WM_MBUTTONDOWN: case Msg.WM_RBUTTONDOWN: case Msg.WM_XBUTTONDOWN: Control c2 = Control.FromHandle(msg.hwnd); if (keyboard_capture != null) { // 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; } // Native menus have their own closing mechanism. if (ToolStripManager.DismissingHandledNatively) { 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((short)(m.LParam.ToInt32() & 0xffff), (short)(m.LParam.ToInt32() >> 16))); while (keyboard_capture != null && !keyboard_capture.ClientRectangle.Contains(keyboard_capture.PointToClient(c2_point))) { keyboard_capture.Dismiss(); } } if (c2 != null && !c2.Enabled) { break; } goto default; case Msg.WM_LBUTTONDBLCLK: case Msg.WM_MBUTTONDBLCLK: case Msg.WM_RBUTTONDBLCLK: case Msg.WM_XBUTTONDBLCLK: Control dbl = Control.FromHandle(msg.hwnd); if (dbl != null && !dbl.Enabled) { break; } goto default; case Msg.WM_LBUTTONUP: case Msg.WM_RBUTTONUP: case Msg.WM_MBUTTONUP: case Msg.WM_XBUTTONUP: Control up = Control.FromHandle(msg.hwnd); if (up != null && !up.Enabled) { break; } goto default; case Msg.WM_QUIT: quit = true; // make sure we exit break; default: if (PreTranslateMessage(ref msg)) { return((IntPtr)1); } XplatUI.TranslateMessage(ref msg); return(XplatUI.DispatchMessage(ref msg)); } return(IntPtr.Zero); }