public static Create ( |
||
hWnd | ||
msg | int | |
wparam | ||
lparam | ||
return |
static public bool TrackPopupMenu(Menu menu, Point pnt) { if (menu.MenuItems.Count <= 0) // No submenus to track { return(true); } MenuTracker tracker = menu.tracker; tracker.active = true; tracker.popup_active = true; // Set GrabControl Control src_ctrl = (tracker.TopMenu as ContextMenu).SourceControl; tracker.GrabControl = src_ctrl.FindForm(); if (tracker.GrabControl == null) { tracker.GrabControl = src_ctrl.FindRootParent(); } tracker.GrabControl.ActiveTracker = tracker; menu.Wnd = new PopUpWindow(tracker.GrabControl, menu); menu.Wnd.Location = menu.Wnd.PointToClient(pnt); ((PopUpWindow)menu.Wnd).ShowWindow(); bool no_quit = true; Object queue_id = XplatUI.StartLoop(Thread.CurrentThread); while ((menu.Wnd != null) && menu.Wnd.Visible && no_quit) { MSG msg = new MSG(); no_quit = XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0); 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 (c != null) { Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam); c.PreProcessControlMessageInternal(ref m); } break; default: XplatUI.TranslateMessage(ref msg); XplatUI.DispatchMessage(ref msg); break; } } if (tracker.GrabControl.IsDisposed) { return(true); } if (!no_quit) { XplatUI.PostQuitMessage(0); } if (menu.Wnd != null) { menu.Wnd.Dispose(); menu.Wnd = null; } return(true); }
// 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; } // 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( (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); }
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; 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); // 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 { if (c2.Parent != null) { if (c2.Parent is ToolStripDropDownMenu) { if ((c2.Parent as ToolStripDropDownMenu).GetTopLevelToolStrip() == keyboard_capture.GetTopLevelToolStrip()) { 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); 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(); } }
/// <summary> /// Invokes the default window procedure associated with this window. /// </summary> /// <param name="m">A <see cref="System.Windows.Forms.Message" /> that is associated with the current Windows message. </param> protected override void WndProc(ref Message m) { switch (m.Msg) { //Do all painting in WM_PAINT to reduce flicker. case (int)WindowsMessage.WM_ERASEBKGND: return; case (int)WindowsMessage.WM_PAINT: // This code is influenced by Steve McMahon's article: // "Painting in the MDI Client Area". // http://vbaccelerator.com/article.asp?id=4306 // Use Win32 to get a Graphics object. var paintStruct = new PAINTSTRUCT(); var screenHdc = NativeMethods.BeginPaint(m.HWnd, ref paintStruct); using (var screenGraphics = Graphics.FromHdc(screenHdc)) { // Get the area to be updated. var clipRect = new Rectangle( paintStruct.rcPaint.Left, paintStruct.rcPaint.Top, paintStruct.rcPaint.Right - paintStruct.rcPaint.Left, paintStruct.rcPaint.Bottom - paintStruct.rcPaint.Top); // Double-buffer by painting everything to an image and // then drawing the image. var width = (MdiClient.ClientRectangle.Width > 0 ? MdiClient.ClientRectangle.Width : 0); var height = (MdiClient.ClientRectangle.Height > 0 ? MdiClient.ClientRectangle.Height : 0); using (Image i = new Bitmap(width, height)) { using (var g = Graphics.FromImage(i)) { // This code comes from J Young's article: // "Generating missing Paint event for TreeView and ListView". // http://www.codeproject.com/cs/miscctrl/genmissingpaintevent.asp // Draw base graphics and raise the base Paint event. var hdc = g.GetHdc(); var printClientMessage = Message.Create(m.HWnd, (int)WindowsMessage.WM_PRINTCLIENT, hdc, IntPtr.Zero); DefWndProc(ref printClientMessage); g.ReleaseHdc(hdc); // Draw the image here. if (image != null) { DrawImage(g, clipRect); } // Call our OnPaint here to draw graphics over the // original and raise our Paint event. OnPaint(new PaintEventArgs(g, clipRect)); } // Now draw all the graphics at once. screenGraphics.DrawImage(i, MdiClient.ClientRectangle); } } NativeMethods.EndPaint(m.HWnd, ref paintStruct); return; case (int)WindowsMessage.WM_SIZE: // Repaint on every resize. MdiClient.Invalidate(); break; case (int)WindowsMessage.WM_NCCALCSIZE: // If AutoScroll is set to false, hide the scrollbars when the control // calculates its non-client area. if (!autoScroll) { ShowScrollBar(m.HWnd, SB.SB_BOTH, 0 /*false*/); } break; } base.WndProc(ref m); }