2007-04-30 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Form.cs
index 14820ff59500faceceb2fbbce4cc179e9d6c62cb..88414bfb40435e160de931dd5b6bf98341ddf3d1 100644 (file)
@@ -49,6 +49,7 @@ namespace System.Windows.Forms {
                #region Local Variables
                internal bool                   closing;
                FormBorderStyle                 form_border_style;
+               private bool                    is_active;
                private bool                    autoscale;
                private Size                    clientsize_set;
                private Size                    autoscale_base_size;
@@ -87,11 +88,11 @@ namespace System.Windows.Forms {
                private bool                    is_loaded;
                internal bool                   is_changing_visible_state;
                internal bool                   has_been_visible;
+               private bool                    shown_raised;  // The shown event is only raised once
 
 #if NET_2_0
                private MenuStrip               main_menu_strip;
                private bool                    show_icon = true;
-               private bool                    shown_raised;  // The shown event is only raised once
 #endif
                #endregion      // Local Variables
 
@@ -101,6 +102,25 @@ namespace System.Windows.Forms {
                        default_icon = Locale.GetResource("mono.ico") as Icon;
                }
 
+               internal bool IsActive {
+                       get {
+                               return is_active;
+                       }
+                       set {
+                               if (is_active == value || IsRecreating) {
+                                       return;
+                               }
+                               
+                               is_active = value;
+                               if (is_active) {
+                                       Application.AddForm (this);
+                                       OnActivated (EventArgs.Empty);
+                               } else {
+                                       OnDeactivate (EventArgs.Empty);
+                               }
+                       }
+               }
+
                // warning: this is only hooked up when an mdi container is created.
                private void ControlAddedHandler (object sender, ControlEventArgs e)
                {
@@ -125,6 +145,25 @@ namespace System.Windows.Forms {
                        return cea.Cancel;
 #endif
                }
+               internal void OnActivatedInternal ()
+               {
+                       OnActivated (EventArgs.Empty);
+               }
+
+               internal override void UpdateWindowText ()
+               {
+                       if (!IsHandleCreated) {
+                               return;
+                       }
+                       
+                       if (shown_raised) {
+                               /* we need to call .SetWindowStyle here instead of just .Text
+                                  because the presence/absence of Text (== "" or not) can cause
+                                  other window style things to appear/disappear */
+                               XplatUI.SetWindowStyle (window.Handle, CreateParams);
+                       }
+                       base.UpdateWindowText ();
+               }
                
                private void SelectActiveControl ()
                {
@@ -191,15 +230,20 @@ namespace System.Windows.Forms {
                                return;
                        }
                        
+                       bool recreate_necessary = false;
+                       
                        if (new_parent == null) {
+                               recreate_necessary = window_manager is FormWindowManager;
                                window_manager = null;
                        } else if (new_parent is MdiClient) {
                                window_manager = new MdiWindowManager (this, (MdiClient) new_parent);
                        } else {
                                window_manager = new FormWindowManager (this);
-                               if (IsHandleCreated) {
-                                       XplatUI.SetWindowStyle (Handle, CreateParams);
-                               }
+                               recreate_necessary = true;
+                       }
+                       
+                       if (recreate_necessary && IsHandleCreated) {
+                               RecreateHandle ();
                        }
                
                        if (window_manager != null) {
@@ -211,7 +255,8 @@ namespace System.Windows.Forms {
                {
                        if (IsMdiChild) {
                                // MS always creates handles when Focus () is called for mdi clients.
-                               CreateHandle ();
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
                        } 
                        return base.FocusInternal (skip_check);
                }
@@ -1001,32 +1046,7 @@ namespace System.Windows.Forms {
                        }
 
                        set {
-                               if (start_position == FormStartPosition.WindowsDefaultLocation) {               // Only do this if it's not set yet
-                                       start_position = value;
-                                       if (IsHandleCreated) {
-                                               switch(start_position) {
-                                                       case FormStartPosition.CenterParent: {
-                                                               CenterToParent();
-                                                               break;
-                                                       }
-
-                                                       case FormStartPosition.CenterScreen: {
-                                                               CenterToScreen();
-                                                               break;
-                                                       }
-
-                                                       case FormStartPosition.Manual: {
-                                                               Left = CreateParams.X;
-                                                               Top = CreateParams.Y;
-                                                               break;
-                                                       }
-
-                                                       default: {
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                               }
+                               start_position = value;
                        }
                }
 
@@ -1101,7 +1121,8 @@ namespace System.Windows.Forms {
                [MWFCategory("Layout")]
                public FormWindowState WindowState {
                        get {
-                               if (IsHandleCreated) {
+                               // Don't actually rely on the WM until we've been shown
+                               if (IsHandleCreated && shown_raised) {
 
                                        if (window_manager != null)
                                                return window_manager.GetWindowState ();
@@ -1117,7 +1138,7 @@ namespace System.Windows.Forms {
                        set {
                                FormWindowState old_state = window_state;
                                window_state = value;
-                               if (IsHandleCreated) {
+                               if (IsHandleCreated && shown_raised) {
 
                                        if (window_manager != null) {
                                                window_manager.SetWindowState (old_state, value);
@@ -1146,17 +1167,40 @@ namespace System.Windows.Forms {
                                cp.menu = ActiveMenu;
                                cp.control = this;
 
-                               if (start_position == FormStartPosition.WindowsDefaultLocation && !IsMdiChild && Parent == null) {
-                                       cp.X = unchecked ((int)0x80000000);
-                                       cp.Y = unchecked ((int)0x80000000);
-                               } else {
+                               if (((Parent != null || !TopLevel) && !IsMdiChild)) {
+                                       // Parented forms and non-toplevel forms always gets the specified location, no matter what
                                        cp.X = Left;
                                        cp.Y = Top;
+                               } else {
+                                       switch (start_position) {
+                                       case FormStartPosition.Manual:
+                                               cp.X = Left;
+                                               cp.Y = Top;
+                                               break;
+                                       case FormStartPosition.CenterScreen:
+                                               if (IsMdiChild) {
+                                                       cp.X = Math.Max ((MdiParent.mdi_container.ClientSize.Width - Width) / 2, 0);
+                                                       cp.Y = Math.Max ((MdiParent.mdi_container.ClientSize.Height - Height) / 2, 0);
+                                               } else {
+                                                       cp.X = Math.Max ((Screen.PrimaryScreen.WorkingArea.Width - Width) / 2, 0);
+                                                       cp.Y = Math.Max ((Screen.PrimaryScreen.WorkingArea.Height - Height) / 2, 0);
+                                               }
+                                               break;
+                                       case FormStartPosition.CenterParent:
+                                       case FormStartPosition.WindowsDefaultBounds:
+                                       case FormStartPosition.WindowsDefaultLocation:
+                                               cp.X = int.MinValue;
+                                               cp.Y = int.MinValue;
+                                               break;
+                                       }
                                }
                                cp.Width = Width;
                                cp.Height = Height;
 
-                               cp.Style = (int)(WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS);
+                               cp.Style = (int)(WindowStyles.WS_CLIPCHILDREN);
+                               if (!Modal) {
+                                       cp.WindowStyle |= WindowStyles.WS_CLIPSIBLINGS;
+                               }
 
                                if (Parent != null) {
                                        cp.Parent = Parent.Handle;
@@ -1266,8 +1310,8 @@ namespace System.Windows.Forms {
                                if (HelpButton && !MaximizeBox && !MinimizeBox) {
                                        cp.ExStyle |= (int)WindowExStyles.WS_EX_CONTEXTHELP;
                                }
-                               
-                               if (VisibleInternal)
+
+                               if (VisibleInternal || this.IsRecreating)
                                        cp.Style |= (int)WindowStyles.WS_VISIBLE;
 
                                if (opacity < 1.0 || TransparencyKey != Color.Empty) {
@@ -1278,6 +1322,19 @@ namespace System.Windows.Forms {
                                        cp.Style |= (int)(WindowStyles.WS_DISABLED);
                                }
 
+                               if (!ControlBox && Text == string.Empty) {
+                                       cp.WindowStyle &= ~WindowStyles.WS_DLGFRAME;
+                               }
+                               
+                               // Fake the window styles for mdi, toolwindows and parented forms
+                               if (cp.HasWindowManager) {
+                                       // Remove all styles but WS_VISIBLE.
+                                       cp.WindowStyle &= WindowStyles.WS_VISIBLE;
+                                       // Set styles that enables us to use the window manager.
+                                       cp.WindowStyle |= WindowStyles.WS_CHILD | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS;
+                                       cp.ExStyle = 0;
+                               }
+                               
                                return cp;
                        }
                }
@@ -1385,7 +1442,7 @@ namespace System.Windows.Forms {
                        if (IsDisposed)
                                return;
 
-                       if (!is_visible)
+                       if (!IsHandleCreated)
                                return;
 
                        XplatUI.SendMessage(this.Handle, Msg.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
@@ -1431,7 +1488,7 @@ namespace System.Windows.Forms {
 #endif
 
                public DialogResult ShowDialog() {
-                       return ShowDialog(this.owner);
+                       return ShowDialog (null);
                }
 
                public DialogResult ShowDialog(IWin32Window ownerWin32) {
@@ -1442,7 +1499,10 @@ namespace System.Windows.Forms {
                        Form owner_to_be = null;
 
                        if ((ownerWin32 == null) && (Application.MWFThread.Current.Context != null)) {
-                               ownerWin32 = Application.MWFThread.Current.Context.MainForm;
+                               IntPtr active = XplatUI.GetActive ();
+                               if (active != IntPtr.Zero) {
+                                       ownerWin32 = Control.FromHandle (active) as Form;
+                               }
                        }
 
                        if (ownerWin32 != null) {
@@ -1584,7 +1644,8 @@ namespace System.Windows.Forms {
 
                        // MS creates the handle here.
                        if (TopLevel) {
-                               CreateHandle ();
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
                        }
                        
                        if (Width > 0) {
@@ -1618,7 +1679,8 @@ namespace System.Windows.Forms {
 
                        // MS creates the handle here.
                        if (TopLevel) {
-                               CreateHandle ();
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
                        }
                        
                        if (Width > 0) {
@@ -1650,8 +1712,6 @@ namespace System.Windows.Forms {
                                return;
                        }
                        
-                       Application.AddForm (this);
-                       
                        UpdateBounds();
 
                        if ((XplatUI.SupportsTransparency() & TransparencySupport.Set) != 0) {
@@ -1739,10 +1799,6 @@ namespace System.Windows.Forms {
                        
                        // Send initial location
                        OnLocationChanged(EventArgs.Empty);
-
-                       if (IsMdiContainer) {
-                               mdi_container.LayoutMdi (MdiLayout.Cascade);
-                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -1765,6 +1821,7 @@ namespace System.Windows.Forms {
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected override void OnHandleDestroyed(EventArgs e) {
+                       Application.RemoveForm (this);
                        base.OnHandleDestroyed (e);
                }
 
@@ -1783,7 +1840,9 @@ namespace System.Windows.Forms {
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
-               protected virtual void OnLoad(EventArgs e) {
+               protected virtual void OnLoad (EventArgs e){
+                       Application.AddForm (this);
+
                        if (AutoScale){
                                ApplyAutoScaling ();
                                AutoScale = false;
@@ -2005,7 +2064,9 @@ namespace System.Windows.Forms {
 
 
                        // MS causes the handle to be created here.
-                       CreateHandle ();
+                       if (!IsHandleCreated)
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
                        
                        if (directed) {
                                base.SelectNextControl(null, forward, true, true, true);
@@ -2044,7 +2105,7 @@ namespace System.Windows.Forms {
 
                        clientsize_set = new Size(x, y);
 
-                       if (XplatUI.CalculateWindowRect(ref ClientRect, cp.Style, cp.ExStyle, cp.menu, out WindowRect)) {
+                       if (XplatUI.CalculateWindowRect(ref ClientRect, cp, cp.menu, out WindowRect)) {
                                SetBounds(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
                        }
                }
@@ -2063,6 +2124,13 @@ namespace System.Windows.Forms {
                                is_changing_visible_state = true;
                                has_been_visible = value || has_been_visible;
                                base.SetVisibleCore (value);
+                               if (value) {
+                                       Application.AddForm (this);
+                               }
+                               
+                               if (value && WindowState != FormWindowState.Normal)
+                                       XplatUI.SendMessage (Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
+                                       
                                is_changing_visible_state = false;
                        }
                        
@@ -2082,13 +2150,14 @@ namespace System.Windows.Forms {
                                PerformLayout ();
                                ThemeEngine.Current.ManagedWindowSetButtonLocations (window_manager);
                        }
-#if NET_2_0
+                       
                        // Shown event is only called once, the first time the form is made visible
                        if (value && !shown_raised) {
+#if NET_2_0
                                this.OnShown (EventArgs.Empty);
+#endif
                                shown_raised = true;
                        }
-#endif
                }
 
                protected override void UpdateDefaultButton() {
@@ -2105,349 +2174,444 @@ namespace System.Windows.Forms {
                                return;
                        }
 
-                       switch((Msg)m.Msg) {
-                               case Msg.WM_DESTROY: {
-                                       if (!RecreatingHandle)
-                                               this.closing = true;
-
-                                       base.WndProc(ref m);
-                                       return;
-                               }
+                       switch ((Msg)m.Msg) {
+                       case Msg.WM_DESTROY: {
+                               WmDestroy (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_CLOSE: {
-                                       Form act = Form.ActiveForm;
-                                       // Don't close this form if there's another modal form visible.
-                                       if (act != null && act != this && act.Modal == true) {
-                                               // Check if any of the parents up the tree is the modal form, 
-                                               // in which case we can still close this form.
-                                               Control current = this;
-                                               while (current != null && current.Parent != act) {
-                                                       current = current.Parent;
-                                               }
-                                               if (current == null || current.Parent != act) {
-                                                       return;
-                                               }
-                                       }
+                       case Msg.WM_CLOSE: {
+                               WmClose (ref m);
+                               return;
+                       }
 
-                                       if (mdi_container != null) {
-                                               foreach (Form mdi_child in mdi_container.MdiChildren) {
-                                                       mdi_child.FireClosingEvents (CloseReason.MdiFormClosing);
-                                               }
-                                       }
+                       case Msg.WM_WINDOWPOSCHANGED: {
+                               WmWindowPosChanged (ref m);
+                               return;
+                       }
 
-                                       if (!is_modal) {
-                                               if (!FireClosingEvents (CloseReason.UserClosing)) {
-                                                       OnClosed (EventArgs.Empty);
-#if NET_2_0
-                                                       OnFormClosed (new FormClosedEventArgs (CloseReason.UserClosing));
-#endif
-                                                       closing = true;
-                                                       Dispose ();
-                                               }
-                                               else {
-                                                       closing = false;
-                                               }
-                                       } else {
-                                               if (FireClosingEvents (CloseReason.UserClosing)) {
-                                                       DialogResult = DialogResult.None;
-                                                       closing = false;
-                                               }
-                                               else {
-                                                       OnClosed (EventArgs.Empty);
 #if NET_2_0
-                                                       OnFormClosed (new FormClosedEventArgs (CloseReason.UserClosing));
+                       case Msg.WM_SYSCOMMAND: {
+                               WmSysCommand (ref m);
+                               break;
+                       }
 #endif
-                                                       closing = true;
-                                                       Hide ();
-                                               }
-                                       }
 
-                                       return;
-                               }
+                       case Msg.WM_ACTIVATE: {
+                               WmActivate (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_WINDOWPOSCHANGED: {
-                                       if (WindowState != FormWindowState.Minimized) {
-                                               base.WndProc(ref m);
-                                       }
-                                       return;
-                               }
+                       case Msg.WM_KILLFOCUS: {
+                               WmKillFocus (ref m);
+                               return;
+                       }
 
-#if NET_2_0
-                               case Msg.WM_SYSCOMMAND: {
-                                       // Let *Strips know the app's title bar was clicked
-                                       if (XplatUI.IsEnabled (Handle))
-                                               ToolStripManager.FireAppClicked ();
-                                               
-                                       base.WndProc(ref m);
-                                       break;
-                               }
-#endif
-       
-                               case Msg.WM_ACTIVATE: {
-                                       if (m.WParam != (IntPtr)WindowActiveFlags.WA_INACTIVE) {
-                                               if (is_loaded) {
-                                                       SelectActiveControl ();
+                       case Msg.WM_SETFOCUS: {
+                               WmSetFocus (ref m);
+                               return;
+                       }
 
-                                                       if (ActiveControl != null && !ActiveControl.Focused)
-                                                               SendControlFocus (ActiveControl);
-                                               }
+                       // Menu drawing
+                       case Msg.WM_NCHITTEST: {
+                               WmNcHitTest (ref m);
+                               return;
+                       }
 
-                                               OnActivated(EventArgs.Empty);
-                                       } else {
-                                               OnDeactivate(EventArgs.Empty);
-                                       }
-                                       return;
-                               }
+                       case Msg.WM_NCLBUTTONDOWN: {
+                               WmNcLButtonDown (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_KILLFOCUS: {
-                                       base.WndProc(ref m);
-                                       return;
-                               }
+                       case Msg.WM_NCLBUTTONUP: {
+                               WmNcLButtonUp (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_SETFOCUS: {
-                                       if (ActiveControl != null && ActiveControl != this) {
-                                               ActiveControl.Focus();
-                                               return; // FIXME - do we need to run base.WndProc, even though we just changed focus?
-                                       }
-                                       if (IsMdiContainer) {
-                                               mdi_container.SendFocusToActiveChild ();
-                                               return;
-                                       }
-                                       base.WndProc(ref m);
-                                       return;
-                               }
+                       case Msg.WM_NCMOUSELEAVE: {
+                               WmNcMouseLeave (ref m);
+                               return;
+                       }
 
-                               // Menu drawing
-                case Msg.WM_NCHITTEST: {
-                                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
-                                               int x = LowOrder ((int)m.LParam.ToInt32 ());
-                                               int y = HighOrder ((int)m.LParam.ToInt32 ());
+                       case Msg.WM_NCMOUSEMOVE: {
+                               WmNcMouseMove (ref m);
+                               return;
+                       }
 
-                                               XplatUI.ScreenToMenu (ActiveMenu.Wnd.window.Handle, ref x, ref y);
+                       case Msg.WM_NCPAINT: {
+                               WmNcPaint (ref m);
+                               return;
+                       }
 
-                                               // If point is under menu return HTMENU, it prevents Win32 to return HTMOVE.
-                                               if ((x > 0) && (y > 0) && (x < ActiveMenu.Rect.Width) && (y < ActiveMenu.Rect.Height)) {
-                                                       m.Result = new IntPtr ((int)HitTest.HTMENU);
-                                                       return;
-                                               }
-                                       }
+                       case Msg.WM_NCCALCSIZE: {
+                               WmNcCalcSize (ref m);
+                               break;
+                       }
 
-                                       base.WndProc (ref m);
-                                       return;
-                               }
+                       case Msg.WM_MOUSEMOVE: {
+                               WmMouseMove (ref m);
+                               break;
+                       }
 
-                case Msg.WM_NCLBUTTONDOWN: {
-                                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
-                                               ActiveMenu.OnMouseDown(this, new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), mouse_clicks, Control.MousePosition.X, Control.MousePosition.Y, 0));
-                                       }
+                       case Msg.WM_LBUTTONDOWN:
+                       case Msg.WM_MBUTTONDOWN:
+                       case Msg.WM_RBUTTONDOWN: {
+                               WmButtonDown (ref m);
+                               return;
+                       }
 
-                                       if (ActiveMaximizedMdiChild != null) {
-                                               if (ActiveMaximizedMdiChild.HandleMenuMouseDown (ActiveMenu,
-                                                               LowOrder ((int) m.LParam.ToInt32 ()),
-                                                               HighOrder ((int) m.LParam.ToInt32 ()))) {
-                                                       // Don't let base process this message, otherwise we won't
-                                                       // get a WM_NCLBUTTONUP.
-                                                       return;
-                                               }
-                                       }
-                                       base.WndProc(ref m);
+                       case Msg.WM_LBUTTONUP:
+                       case Msg.WM_MBUTTONUP:
+                       case Msg.WM_RBUTTONUP: {
+                               WmButtonUp (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_GETMINMAXINFO: {
+                               WmGetMinMaxInfo (ref m);
+                               break;
+                       }
+
+                       default: {
+                               base.WndProc (ref m);
+                               break;
+                       }
+                       }
+               }
+               #endregion      // Protected Instance Methods
+
+#region WM methods
+
+               private void WmDestroy (ref Message m)
+               {
+                       if (!RecreatingHandle)
+                               this.closing = true;
+
+                       base.WndProc (ref m);
+               }
+               
+               private void WmClose (ref Message m)
+               {
+                       Form act = Form.ActiveForm;
+                       // Don't close this form if there's another modal form visible.
+                       if (act != null && act != this && act.Modal == true) {
+                               // Check if any of the parents up the tree is the modal form, 
+                               // in which case we can still close this form.
+                               Control current = this;
+                               while (current != null && current.Parent != act) {
+                                       current = current.Parent;
+                               }
+                               if (current == null || current.Parent != act) {
                                        return;
                                }
+                       }
 
-                case Msg.WM_NCLBUTTONUP: {
-                                       if (ActiveMaximizedMdiChild != null) {
-                                               ActiveMaximizedMdiChild.HandleMenuMouseUp (ActiveMenu,
-                                                               LowOrder ((int)m.LParam.ToInt32 ()),
-                                                               HighOrder ((int)m.LParam.ToInt32 ()));
-                                       }
-                                       base.WndProc (ref m);
-                                       return;
+                       if (mdi_container != null) {
+                               foreach (Form mdi_child in mdi_container.MdiChildren) {
+                                       mdi_child.FireClosingEvents (CloseReason.MdiFormClosing);
                                }
+                       }
 
-                               case Msg.WM_NCMOUSELEAVE: {
-                                       if (ActiveMaximizedMdiChild != null) {
-                                               ActiveMaximizedMdiChild.HandleMenuMouseLeave(ActiveMenu,
-                                                               LowOrder((int)m.LParam.ToInt32()),
-                                                               HighOrder((int)m.LParam.ToInt32()));
-                                       }
-                                       base.WndProc(ref m);
-                                       return;
+                       if (!is_modal) {
+                               if (!FireClosingEvents (CloseReason.UserClosing)) {
+                                       OnClosed (EventArgs.Empty);
+#if NET_2_0
+                                       OnFormClosed (new FormClosedEventArgs (CloseReason.UserClosing));
+#endif
+                                       closing = true;
+                                       Dispose ();
+                               } else {
+                                       closing = false;
                                }
-                               
-                               case Msg.WM_NCMOUSEMOVE: {
-                                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
-                                               ActiveMenu.OnMouseMove(this, new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 0));
-                                       }
-                                       
-                                       if (ActiveMaximizedMdiChild != null) {
-                                               XplatUI.RequestAdditionalWM_NCMessages (Handle, false, true);
-                                               ActiveMaximizedMdiChild.HandleMenuMouseMove (ActiveMenu,
-                                                               LowOrder ((int)m.LParam.ToInt32 ()),
-                                                               HighOrder ((int)m.LParam.ToInt32 ()));
-                                       }
-                                       base.WndProc(ref m);
-                                       return;
+                       } else {
+                               if (FireClosingEvents (CloseReason.UserClosing)) {
+                                       DialogResult = DialogResult.None;
+                                       closing = false;
+                               } else {
+                                       OnClosed (EventArgs.Empty);
+#if NET_2_0
+                                       OnFormClosed (new FormClosedEventArgs (CloseReason.UserClosing));
+#endif
+                                       closing = true;
+                                       Hide ();
                                }
+                       }
 
-                               case Msg.WM_NCPAINT: {
-                                       if (ActiveMenu != null) {
-                                               PaintEventArgs  pe;
-                                               Point           pnt;
 
-                                               pe = XplatUI.PaintEventStart(Handle, false);
-                                               pnt = XplatUI.GetMenuOrigin(window.Handle);
+                       mdi_parent = null;
+               }
+               
+               private void WmWindowPosChanged (ref Message m)
+               {
+                       if (WindowState != FormWindowState.Minimized) {
+                               base.WndProc (ref m);
+                       }
+               }
 
-                                               // The entire menu has to be in the clip rectangle because the 
-                                               // control buttons are right-aligned and otherwise they would
-                                               // stay painted when the window gets resized.
-                                               Rectangle clip = new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0);
-                                               clip = Rectangle.Union(clip, pe.ClipRectangle);
-                                               pe.SetClip(clip);
-                                               pe.Graphics.SetClip(clip);
-                                               
-                                               ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0));
+#if NET_2_0
+               private void WmSysCommand (ref Message m)
+               {
+                       // Let *Strips know the app's title bar was clicked
+                       if (XplatUI.IsEnabled (Handle))
+                               ToolStripManager.FireAppClicked ();
 
-                                               if (ActiveMaximizedMdiChild != null) {
-                                                       ActiveMaximizedMdiChild.DrawMaximizedButtons (ActiveMenu, pe);
-                                               }
+                       base.WndProc (ref m);
+               }
+#endif 
+               private void WmActivate (ref Message m)
+               {
+                       if (m.WParam != (IntPtr)WindowActiveFlags.WA_INACTIVE) {
+                               if (is_loaded) {
+                                       SelectActiveControl ();
 
-                                               XplatUI.PaintEventEnd(Handle, false);
-                                       }
+                                       if (ActiveControl != null && !ActiveControl.Focused)
+                                               SendControlFocus (ActiveControl);
+                               }
+
+                               IsActive = true;
+                       } else {
+#if NET_2_0
+                               if (XplatUI.IsEnabled (Handle))
+                                       ToolStripManager.FireAppFocusChanged (this);
+#endif
+                               IsActive = false;
+                       }
+               }
+               
+               private void WmKillFocus (ref Message m)
+               {
+                       base.WndProc (ref m);
+               }
+               
+               private void WmSetFocus (ref Message m)
+               {
+                       if (ActiveControl != null && ActiveControl != this) {
+                               ActiveControl.Focus ();
+                               return; // FIXME - do we need to run base.WndProc, even though we just changed focus?
+                       }
+                       if (IsMdiContainer) {
+                               mdi_container.SendFocusToActiveChild ();
+                               return;
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcHitTest (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
+                               int x = LowOrder ((int)m.LParam.ToInt32 ());
+                               int y = HighOrder ((int)m.LParam.ToInt32 ());
+
+                               XplatUI.ScreenToMenu (ActiveMenu.Wnd.window.Handle, ref x, ref y);
 
-                                       base.WndProc(ref m);
+                               // If point is under menu return HTMENU, it prevents Win32 to return HTMOVE.
+                               if ((x > 0) && (y > 0) && (x < ActiveMenu.Rect.Width) && (y < ActiveMenu.Rect.Height)) {
+                                       m.Result = new IntPtr ((int)HitTest.HTMENU);
                                        return;
                                }
+                       }
 
-                               case Msg.WM_NCCALCSIZE: {
-                                       XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
-
-                                       if ((ActiveMenu != null) && (m.WParam == (IntPtr)1)) {
-                                               ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcLButtonDown (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
+                               ActiveMenu.OnMouseDown (this, new MouseEventArgs (FromParamToMouseButtons ((int)m.WParam.ToInt32 ()), mouse_clicks, Control.MousePosition.X, Control.MousePosition.Y, 0));
+                       }
 
-                                               // Adjust for menu
-                                               ncp.rgrc1.top += ThemeEngine.Current.CalcMenuBarSize (DeviceContext, ActiveMenu, ClientSize.Width);
-                                               Marshal.StructureToPtr(ncp, m.LParam, true);
-                                       }
-                                       DefWndProc(ref m);
-                                       break;
+                       if (ActiveMaximizedMdiChild != null) {
+                               if (ActiveMaximizedMdiChild.HandleMenuMouseDown (ActiveMenu,
+                                               LowOrder ((int)m.LParam.ToInt32 ()),
+                                               HighOrder ((int)m.LParam.ToInt32 ()))) {
+                                       // Don't let base process this message, otherwise we won't
+                                       // get a WM_NCLBUTTONUP.
+                                       return;
                                }
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcLButtonUp (ref Message m)
+               {
+                       if (ActiveMaximizedMdiChild != null) {
+                               ActiveMaximizedMdiChild.HandleMenuMouseUp (ActiveMenu,
+                                               LowOrder ((int)m.LParam.ToInt32 ()),
+                                               HighOrder ((int)m.LParam.ToInt32 ()));
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcMouseLeave (ref Message m)
+               {
+                       if (ActiveMaximizedMdiChild != null) {
+                               ActiveMaximizedMdiChild.HandleMenuMouseLeave (ActiveMenu,
+                                               LowOrder ((int)m.LParam.ToInt32 ()),
+                                               HighOrder ((int)m.LParam.ToInt32 ()));
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcMouseMove (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && ActiveMenu != null) {
+                               ActiveMenu.OnMouseMove (this, new MouseEventArgs (FromParamToMouseButtons ((int)m.WParam.ToInt32 ()), mouse_clicks, LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()), 0));
+                       }
 
-                               case Msg.WM_MOUSEMOVE: {
-                                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
-                                               MouseEventArgs args;
+                       if (ActiveMaximizedMdiChild != null) {
+                               XplatUI.RequestAdditionalWM_NCMessages (Handle, false, true);
+                               ActiveMaximizedMdiChild.HandleMenuMouseMove (ActiveMenu,
+                                               LowOrder ((int)m.LParam.ToInt32 ()),
+                                               HighOrder ((int)m.LParam.ToInt32 ()));
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcPaint (ref Message m)
+               {
+                       if (ActiveMenu != null) {
+                               PaintEventArgs pe;
+                               Point pnt;
 
-                                               args = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
-                                                       mouse_clicks,  LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),  0);
-                                               active_tracker.OnMotion(new MouseEventArgs (args.Button, args.Clicks, Control.MousePosition.X, Control.MousePosition.Y, args.Delta));
-                                               break;
-                                       }
-                                       base.WndProc(ref m);
-                                       break;
+                               pe = XplatUI.PaintEventStart (Handle, false);
+                               pnt = XplatUI.GetMenuOrigin (window.Handle);
+
+                               // The entire menu has to be in the clip rectangle because the 
+                               // control buttons are right-aligned and otherwise they would
+                               // stay painted when the window gets resized.
+                               Rectangle clip = new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0);
+                               clip = Rectangle.Union (clip, pe.ClipRectangle);
+                               pe.SetClip (clip);
+                               pe.Graphics.SetClip (clip);
+
+                               ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0));
+
+                               if (ActiveMaximizedMdiChild != null) {
+                                       ActiveMaximizedMdiChild.DrawMaximizedButtons (ActiveMenu, pe);
                                }
 
-                               case Msg.WM_LBUTTONDOWN:
-                               case Msg.WM_MBUTTONDOWN:
-                               case Msg.WM_RBUTTONDOWN: {                                      
-                                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
-                                               MouseEventArgs args;
+                               XplatUI.PaintEventEnd (Handle, false);
+                       }
+
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcCalcSize (ref Message m)
+               {
+                       XplatUIWin32.NCCALCSIZE_PARAMS ncp;
 
-                                               args = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
-                                                       mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 0);
-                                               active_tracker.OnMouseDown(new MouseEventArgs (args.Button, args.Clicks, Control.MousePosition.X, Control.MousePosition.Y, args.Delta));
-                                               return;
+                       if ((ActiveMenu != null) && (m.WParam == (IntPtr)1)) {
+                               ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (m.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
+
+                               // Adjust for menu
+                               ncp.rgrc1.top += ThemeEngine.Current.CalcMenuBarSize (DeviceContext, ActiveMenu, ClientSize.Width);
+                               Marshal.StructureToPtr (ncp, m.LParam, true);
+                       }
+                       DefWndProc (ref m);             
+               }
+               
+               private void WmMouseMove (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
+                               MouseEventArgs args = new MouseEventArgs (
+                                       FromParamToMouseButtons ((int)m.WParam.ToInt32 ()),
+                                       mouse_clicks,
+                                       Control.MousePosition.X,
+                                       Control.MousePosition.Y,
+                                       0);
+
+                               active_tracker.OnMotion (args);
+                               return;
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmButtonDown (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
+                               MouseEventArgs args = new MouseEventArgs (
+                                       FromParamToMouseButtons ((int)m.WParam.ToInt32 ()),
+                                       mouse_clicks,
+                                       Control.MousePosition.X,
+                                       Control.MousePosition.Y,
+                                       0);
+
+                               if (!active_tracker.OnMouseDown (args)) {
+                                       Control control = GetRealChildAtPoint (Cursor.Position);
+                                       if (control != null) {
+                                               Point pt = control.PointToClient (Cursor.Position);
+                                               XplatUI.SendMessage (control.Handle, (Msg)m.Msg, m.WParam, MakeParam (pt.X, pt.Y));
                                        }
+                               }
+
+                               return;
+                       }
 #if NET_2_0
-                                       ToolStripManager.FireAppClicked ();
+                       ToolStripManager.FireAppClicked ();
 #endif
-                                       base.WndProc (ref m);
-                                       return;
-                               }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmButtonUp (ref Message m)
+               {
+                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
+                               MouseButtons mb = FromParamToMouseButtons ((int)m.WParam.ToInt32 ());
 
+                               // We add in the button that was released (not sent in WParam)
+                               switch ((Msg)m.Msg) {
                                case Msg.WM_LBUTTONUP:
+                                       mb |= MouseButtons.Left;
+                                       break;
                                case Msg.WM_MBUTTONUP:
-                               case Msg.WM_RBUTTONUP: {
-                                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
-                                               MouseEventArgs args;
-                                               MouseButtons mb = FromParamToMouseButtons ((int) m.WParam.ToInt32());
-                                               
-                                               // We add in the button that was released (not sent in WParam)
-                                               switch((Msg)m.Msg) {
-                                                       case Msg.WM_LBUTTONUP:
-                                                               mb |= MouseButtons.Left;
-                                                               break;
-                                                       case Msg.WM_MBUTTONUP:
-                                                               mb |= MouseButtons.Middle;
-                                                               break;
-                                                       case Msg.WM_RBUTTONUP:
-                                                               mb |= MouseButtons.Right;
-                                                               break;
-                                               }
-                                               
-                                               args = new MouseEventArgs (mb, mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 0);
-                                               active_tracker.OnMouseUp(new MouseEventArgs (args.Button, args.Clicks, Control.MousePosition.X, Control.MousePosition.Y, args.Delta));
-                                               mouse_clicks = 1;
-                                               return;
-                                       }
-                                       base.WndProc(ref m);
-                                       return;
+                                       mb |= MouseButtons.Middle;
+                                       break;
+                               case Msg.WM_RBUTTONUP:
+                                       mb |= MouseButtons.Right;
+                                       break;
                                }
 
-                               case Msg.WM_GETMINMAXINFO: {
-                                       MINMAXINFO      mmi;
+                               MouseEventArgs args = new MouseEventArgs (
+                                       mb,
+                                       mouse_clicks,
+                                       Control.MousePosition.X,
+                                       Control.MousePosition.Y,
+                                       0);
 
-                                       if (m.LParam != IntPtr.Zero) {
-                                               mmi = (MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
-
-                                               default_maximized_bounds = new Rectangle(mmi.ptMaxPosition.x, mmi.ptMaxPosition.y, mmi.ptMaxSize.x, mmi.ptMaxSize.y);
-                                               if (maximized_bounds != Rectangle.Empty) {
-                                                       mmi.ptMaxPosition.x = maximized_bounds.Left;
-                                                       mmi.ptMaxPosition.y = maximized_bounds.Top;
-                                                       mmi.ptMaxSize.x = maximized_bounds.Width;
-                                                       mmi.ptMaxSize.y = maximized_bounds.Height;
-                                               }
+                               active_tracker.OnMouseUp (args);
+                               mouse_clicks = 1;
+                               return;
+                       }
+                       base.WndProc (ref m);
+               }
+               
+               private void WmGetMinMaxInfo (ref Message m)
+               {
+                       MINMAXINFO mmi;
 
-                                               if (minimum_size != Size.Empty) {
-                                                       mmi.ptMinTrackSize.x = minimum_size.Width;
-                                                       mmi.ptMinTrackSize.y = minimum_size.Height;
-                                               }
+                       if (m.LParam != IntPtr.Zero) {
+                               mmi = (MINMAXINFO)Marshal.PtrToStructure (m.LParam, typeof (MINMAXINFO));
 
-                                               if (maximum_size != Size.Empty) {
-                                                       mmi.ptMaxTrackSize.x = maximum_size.Width;
-                                                       mmi.ptMaxTrackSize.y = maximum_size.Height;
-                                               }
-                                               Marshal.StructureToPtr(mmi, m.LParam, false);
-                                       }
-                                       break;
-                               }
-                               
-#if NET_2_0
-                               case Msg.WM_MOUSEACTIVATE: {
-                                       // Let *Strips know the form or another control has been clicked
-                                       if (XplatUI.IsEnabled (Handle))
-                                               ToolStripManager.FireAppClicked ();
-                                               
-                                       base.WndProc (ref m);
-                                       break;                          
+                               default_maximized_bounds = new Rectangle (mmi.ptMaxPosition.x, mmi.ptMaxPosition.y, mmi.ptMaxSize.x, mmi.ptMaxSize.y);
+                               if (maximized_bounds != Rectangle.Empty) {
+                                       mmi.ptMaxPosition.x = maximized_bounds.Left;
+                                       mmi.ptMaxPosition.y = maximized_bounds.Top;
+                                       mmi.ptMaxSize.x = maximized_bounds.Width;
+                                       mmi.ptMaxSize.y = maximized_bounds.Height;
                                }
-                               
-                               case Msg.WM_ACTIVATEAPP: {
-                                       // Let *Strips know the app lost focus
-                                       if (m.WParam == (IntPtr)0) 
-                                               if (XplatUI.IsEnabled (Handle))
-                                                       ToolStripManager.FireAppFocusChanged (this);
-                                                       
-                                       base.WndProc (ref m);
-                                       break;                          
+
+                               if (minimum_size != Size.Empty) {
+                                       mmi.ptMinTrackSize.x = minimum_size.Width;
+                                       mmi.ptMinTrackSize.y = minimum_size.Height;
                                }
-#endif
 
-                               default: {
-                                       base.WndProc (ref m);
-                                       break;
+                               if (maximum_size != Size.Empty) {
+                                       mmi.ptMaxTrackSize.x = maximum_size.Width;
+                                       mmi.ptMaxTrackSize.y = maximum_size.Height;
                                }
+                               Marshal.StructureToPtr (mmi, m.LParam, false);
                        }
                }
-               #endregion      // Protected Instance Methods
+#endregion
 
                internal override void FireEnter ()
                {
@@ -2707,6 +2871,7 @@ namespace System.Windows.Forms {
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                protected virtual void OnFormClosed (FormClosedEventArgs e) {
+                       Application.RemoveForm (this);
                        FormClosedEventHandler eh = (FormClosedEventHandler)(Events[FormClosedEvent]);
                        if (eh != null)
                                eh (this, e);