2007-04-30 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Form.cs
index 5c623345f121ee550bd45ed0ce937711af903323..88414bfb40435e160de931dd5b6bf98341ddf3d1 100644 (file)
@@ -39,11 +39,17 @@ namespace System.Windows.Forms {
        [DesignTimeVisible(false)]
        [Designer("System.Windows.Forms.Design.FormDocumentDesigner, " + Consts.AssemblySystem_Design, typeof(IRootDesigner))]
        [DefaultEvent("Load")]
+#if NET_2_0
+       [ClassInterface (ClassInterfaceType.AutoDispatch)]
+       [InitializationEvent ("Load")]
+       [ComVisible (true)]
+#endif
        [ToolboxItem(false)]
        public class Form : ContainerControl {
                #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;
@@ -72,6 +78,7 @@ namespace System.Windows.Forms {
                private Size                    maximum_size;
                private Size                    minimum_size;
                private SizeGripStyle           size_grip_style;
+               private SizeGrip                size_grip;
                private Rectangle               maximized_bounds;
                private Rectangle               default_maximized_bounds;
                private double                  opacity;
@@ -81,9 +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;
 #endif
                #endregion      // Local Variables
 
@@ -93,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)
                {
@@ -101,10 +129,46 @@ namespace System.Windows.Forms {
                        }
                }
 
+               // Convenience method for fire BOTH OnClosing and OnFormClosing events
+               // Returns the value of Cancel, so true means the Close was cancelled,
+               // and you shouldn't close the form.
+               internal bool FireClosingEvents (CloseReason reason)
+               {
+                       CancelEventArgs cea = new CancelEventArgs ();
+                       this.OnClosing (cea);
+                       
+#if NET_2_0
+                       FormClosingEventArgs fcea = new FormClosingEventArgs (reason, cea.Cancel);
+                       this.OnFormClosing (fcea);
+                       return fcea.Cancel;
+#else
+                       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 ()
                {
                        if (this.IsMdiContainer) {
-                               SendControlFocus (this.mdi_container);
+                               mdi_container.SendFocusToActiveChild ();
                                return;
                        }
                                
@@ -125,9 +189,83 @@ namespace System.Windows.Forms {
                                Select (ActiveControl);
                        }
                }
+               
+               private new void UpdateSizeGripVisible ()
+               {
+                       // Following link explains when to show size grip:
+                       // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=138687&SiteID=1
+                       // if SizeGripStyle.Auto, only shown if form is shown using ShowDialog and is sizable
+                       // if SizeGripStyle.Show, only shown if form is sizable
+                       
+                       bool show = false;
+                       
+                       switch (size_grip_style) {
+                       case SizeGripStyle.Auto:
+                               show = is_modal && (form_border_style == FormBorderStyle.Sizable || form_border_style == FormBorderStyle.SizableToolWindow);
+                               break;
+                       case SizeGripStyle.Hide:
+                               show = false;
+                               break;
+                       case SizeGripStyle.Show:
+                               show = (form_border_style == FormBorderStyle.Sizable || form_border_style == FormBorderStyle.SizableToolWindow);
+                               break;
+                       }
+                       
+                       if (!show) {
+                               if (size_grip != null && size_grip.Visible)
+                                       size_grip.Visible = false;
+                       } else {
+                               if (size_grip == null) {
+                                       size_grip = new SizeGrip (this);
+                                       size_grip.Virtual = true;
+                                       size_grip.FillBackground = false;
+                               }
+                               size_grip.Visible = true;
+                       }
+               }
+               
+               internal void ChangingParent (Control new_parent)
+               {
+                       if (IsMdiChild) {
+                               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);
+                               recreate_necessary = true;
+                       }
+                       
+                       if (recreate_necessary && IsHandleCreated) {
+                               RecreateHandle ();
+                       }
+               
+                       if (window_manager != null) {
+                               window_manager.UpdateWindowState (window_state, window_state, true);
+                       }
+               }
+
+               internal override bool FocusInternal (bool skip_check)
+               {
+                       if (IsMdiChild) {
+                               // MS always creates handles when Focus () is called for mdi clients.
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
+                       } 
+                       return base.FocusInternal (skip_check);
+               }
                #endregion      // Private & Internal Methods
 
                #region Public Classes
+#if NET_2_0
+               [ComVisible (false)]
+#endif         
                public new class ControlCollection : Control.ControlCollection {
                        Form    form_owner;
 
@@ -182,10 +320,7 @@ namespace System.Windows.Forms {
                        default_maximized_bounds = Rectangle.Empty;
                        owned_forms = new Form.ControlCollection(this);
                        transparency_key = Color.Empty;
-
-                       // FIXME: this should disappear just as soon as the handle creation is done in the right place (here is too soon()
-                       UpdateBounds();
-
+                       InternalClientSize = new Size (this.Width - (SystemInformation.FrameBorderSize.Width * 2), this.Height - (SystemInformation.FrameBorderSize.Height * 2) - SystemInformation.CaptionHeight);
                }
                #endregion      // Public Constructor & Destructor
 
@@ -258,6 +393,10 @@ namespace System.Windows.Forms {
                }
 
 #if NET_2_0
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               [Obsolete ("This property has been deprecated in favor of AutoScaleMode.")]
 #else
                [DefaultValue(true)]
 #endif
@@ -272,9 +411,14 @@ namespace System.Windows.Forms {
                        }
                }
 
+#if NET_2_0
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               [EditorBrowsable(EditorBrowsableState.Never)]
+#else
+               [EditorBrowsable(EditorBrowsableState.Advanced)]
+#endif
                [Localizable(true)]
                [Browsable(false)]
-               [EditorBrowsable(EditorBrowsableState.Advanced)]
                public virtual Size AutoScaleBaseSize {
                        get {
                                return autoscale_base_size;
@@ -406,7 +550,13 @@ namespace System.Windows.Forms {
                                        window_manager.UpdateBorderStyle (value);
                                }
 
+                               Size current_client_size = ClientSize;
                                UpdateStyles();
+                               
+                               if (this.IsHandleCreated) {
+                                       this.Size = InternalSizeFromClientSize (current_client_size);
+                                       XplatUI.InvalidateNC (this.Handle);
+                               }
                        }
                }
 
@@ -503,9 +653,23 @@ namespace System.Windows.Forms {
                }
 
 #if NET_2_0
+               [DefaultValue (null)]
+               [TypeConverter (typeof (ReferenceConverter))]
                public MenuStrip MainMenuStrip {
                        get { return this.main_menu_strip; }
-                       set { this.main_menu_strip = value; }
+                       set { 
+                               if (this.main_menu_strip != value) {
+                                       this.main_menu_strip = value;
+                                       this.main_menu_strip.RefreshMdiItems ();
+                               }
+                       }
+               }
+               
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               [Browsable (false)]
+               public new Padding Margin {
+                       get { return base.Margin; }
+                       set { base.Margin = value; }
                }
 #endif
 
@@ -518,9 +682,6 @@ namespace System.Windows.Forms {
                        set {
                                if (maximize_box != value) {
                                        maximize_box = value;
-                                       if (IsHandleCreated) {
-                                               RecreateHandle();
-                                       }
                                        UpdateStyles();
                                }
                        }
@@ -570,7 +731,8 @@ namespace System.Windows.Forms {
 
                        set {
                                if (value != null && !value.IsMdiContainer)
-                                       throw new ArgumentException ();
+                                       throw new ArgumentException ("Form that was specified to be "
+                                               + "the MdiParent for this form is not an MdiContainer.");
 
                                if (mdi_parent != null) {
                                        mdi_parent.MdiContainer.Controls.Remove (this);
@@ -578,13 +740,15 @@ namespace System.Windows.Forms {
 
                                if (value != null) {
                                        mdi_parent = value;
-                                       window_manager = new MdiWindowManager (this,
-                                                       mdi_parent.MdiContainer);
+                                       if (window_manager == null) {
+                                               window_manager = new MdiWindowManager (this, mdi_parent.MdiContainer);
+                                       }
+                                       
                                        mdi_parent.MdiContainer.Controls.Add (this);
                                        mdi_parent.MdiContainer.Controls.SetChildIndex (this, 0);
-
-                                       RecreateHandle ();
-
+                                       
+                                       if (IsHandleCreated)
+                                               RecreateHandle ();
                                } else if (mdi_parent != null) {
                                        mdi_parent = null;
 
@@ -592,8 +756,10 @@ namespace System.Windows.Forms {
                                        window_manager = null;
                                        FormBorderStyle = form_border_style;
 
-                                       RecreateHandle ();
+                                       if (IsHandleCreated)
+                                               RecreateHandle ();
                                }
+                               is_toplevel = mdi_parent == null;
                        }
                }
 
@@ -616,6 +782,10 @@ namespace System.Windows.Forms {
                        get { return window_manager; }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+               [TypeConverter (typeof (ReferenceConverter))]
+#endif
                [DefaultValue(null)]
                [MWFCategory("Window Style")]
                public MainMenu Menu {
@@ -697,9 +867,6 @@ namespace System.Windows.Forms {
                        set {
                                if (minimize_box != value) {
                                        minimize_box = value;
-                                       if (IsHandleCreated) {
-                                               RecreateHandle();
-                                       }
                                        UpdateStyles();
                                }
                        }
@@ -805,15 +972,33 @@ namespace System.Windows.Forms {
                                                owner.AddOwnedForm(this);
                                        if (IsHandleCreated) {
                                                if (owner != null && owner.IsHandleCreated) {
-                                                       XplatUI.SetTopmost(this.window.Handle, owner.window.Handle, true);
+                                                       XplatUI.SetOwner(this.window.Handle, owner.window.Handle);
                                                } else {
-                                                       XplatUI.SetTopmost(this.window.Handle, IntPtr.Zero, false);
+                                                       XplatUI.SetOwner(this.window.Handle, IntPtr.Zero);
                                                }
                                        }
                                }
                        }
                }
 
+#if NET_2_0
+               [DefaultValue (true)]
+               public bool ShowIcon {
+                       get { return this.show_icon; }
+                       set {
+                               if (this.show_icon != value ) {
+                                       this.show_icon = value;
+                                       UpdateStyles ();
+                                       
+                                       if (IsHandleCreated) {
+                                               XplatUI.SetIcon (this.Handle, value == true ? this.Icon : null);
+                                               XplatUI.InvalidateNC (this.Handle);
+                                       }
+                               }
+                       }
+               }                       
+#endif
+       
                [DefaultValue(true)]
                [MWFCategory("Window Style")]
                public bool ShowInTaskbar {
@@ -839,7 +1024,6 @@ namespace System.Windows.Forms {
                        set { base.Size = value; }
                }
 
-               [MonoTODO("Trigger something when GripStyle is set")]
                [DefaultValue(SizeGripStyle.Auto)]
                [MWFCategory("Window Style")]
                public SizeGripStyle SizeGripStyle {
@@ -849,6 +1033,7 @@ namespace System.Windows.Forms {
 
                        set {
                                size_grip_style = value;
+                               UpdateSizeGripVisible ();
                        }
                }
 
@@ -861,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;
                        }
                }
 
@@ -899,6 +1059,17 @@ namespace System.Windows.Forms {
                        set { base.TabIndex = value; }
                }
 
+#if NET_2_0
+               [Browsable(false)]
+               [DefaultValue (true)]
+               [DispIdAttribute (-516)]
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               public new bool TabStop {
+                       get { return base.TabStop; }
+                       set { base.TabStop = value; }
+               }
+#endif
+
                [Browsable(false)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -925,7 +1096,7 @@ namespace System.Windows.Forms {
                                if (topmost != value) {
                                        topmost = value;
                                        if (IsHandleCreated)
-                                               XplatUI.SetTopmost(window.Handle, owner != null ? owner.window.Handle : IntPtr.Zero, value);
+                                               XplatUI.SetTopmost(window.Handle, value);
                                }
                        }
                }
@@ -941,7 +1112,7 @@ namespace System.Windows.Forms {
 
                                AllowTransparency = true;
                                UpdateStyles();
-                               if ((XplatUI.SupportsTransparency () & TransparencySupport.Set) != 0)
+                               if (IsHandleCreated && (XplatUI.SupportsTransparency () & TransparencySupport.Set) != 0)
                                        XplatUI.SetWindowTransparency(Handle, Opacity, transparency_key);
                        }
                }
@@ -950,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 ();
@@ -966,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);
@@ -993,18 +1165,47 @@ namespace System.Windows.Forms {
                                cp.Param = 0;
                                cp.Parent = IntPtr.Zero;
                                cp.menu = ActiveMenu;
+                               cp.control = this;
 
-                               if (start_position == FormStartPosition.WindowsDefaultLocation && !IsMdiChild) {
-                                       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;
+                                       cp.Style |= (int) WindowStyles.WS_CHILD;
+                               }
 
                                if (IsMdiChild) {
                                        cp.Style |= (int)(WindowStyles.WS_CHILD | WindowStyles.WS_CAPTION);
@@ -1100,11 +1301,17 @@ namespace System.Windows.Forms {
                                        cp.Style |= (int)WindowStyles.WS_SYSMENU;
                                }
 
+#if NET_2_0
+                               if (!this.show_icon) {
+                                       cp.ExStyle |= (int)WindowExStyles.WS_EX_DLGMODALFRAME;
+                               }
+#endif
+
                                if (HelpButton && !MaximizeBox && !MinimizeBox) {
                                        cp.ExStyle |= (int)WindowExStyles.WS_EX_CONTEXTHELP;
                                }
-                               
-                               if (Visible)
+
+                               if (VisibleInternal || this.IsRecreating)
                                        cp.Style |= (int)WindowStyles.WS_VISIBLE;
 
                                if (opacity < 1.0 || TransparencyKey != Color.Empty) {
@@ -1115,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;
                        }
                }
@@ -1147,10 +1367,25 @@ namespace System.Windows.Forms {
                                }
                        }
                }
+               
+#if !NET_2_0
+               internal
+#else
+               [MonoTODO ("Implemented for Win32, needs X11 implementation")]
+               protected 
+#endif
+               virtual bool ShowWithoutActivation {
+                       get { return false; }
+               }
                #endregion      // Protected Instance Properties
 
                #region Public Static Methods
+#if NET_2_0
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               [Obsolete ("This method has been deprecated.  Use AutoScaleDimensions instead")]
+#else
                [EditorBrowsable(EditorBrowsableState.Advanced)]
+#endif
                public static SizeF GetAutoScaleSize (Font font)
                {
                        return XplatUI.GetAutoScaleSize(font);
@@ -1177,7 +1412,8 @@ namespace System.Windows.Forms {
                        return new SizeF (width, font.Height);
                }
                                                 
-               public void Activate() {
+               public void Activate ()
+               {
                        Form    active;
 
                        // The docs say activate only activates if our app is already active
@@ -1185,7 +1421,7 @@ namespace System.Windows.Forms {
                                if (IsMdiChild) {
                                        MdiParent.ActivateMdiChild (this);
                                } else if (IsMdiContainer) {
-                                       SendControlFocus (mdi_container);
+                                       mdi_container.SendFocusToActiveChild ();
                                } else {
                                        active = ActiveForm;
                                        if ((active != null) && (this != active)) {
@@ -1206,15 +1442,9 @@ namespace System.Windows.Forms {
                        if (IsDisposed)
                                return;
 
-                       if (!is_visible)
+                       if (!IsHandleCreated)
                                return;
 
-#if NET_2_0
-                       FormClosingEventArgs ce = new FormClosingEventArgs (CloseReason.FormOwnerClosing, false);
-                       OnFormClosing (ce);
-                       if (ce.Cancel)
-                               return;
-#endif
                        XplatUI.SendMessage(this.Handle, Msg.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                }
 
@@ -1236,8 +1466,29 @@ namespace System.Windows.Forms {
                        DesktopLocation = new Point(x, y);
                }
 
+#if NET_2_0
+               public void Show (IWin32Window owner)
+               {
+                       if (owner == null)
+                               this.Owner = null;
+                       else
+                               this.Owner = Control.FromHandle (owner.Handle).TopLevelControl as Form;
+
+                       if (owner == this)
+                               throw new InvalidOperationException ("The 'owner' cannot be the form being shown.");
+
+                       if (TopLevelControl != this) {
+                               throw new InvalidOperationException ("Forms that are not top level"
+                                       + " forms cannot be displayed as a modal dialog. Remove the"
+                                       + " form from any parent form before calling Show.");
+                       }
+
+                       base.Show ();
+               }
+#endif
+
                public DialogResult ShowDialog() {
-                       return ShowDialog(this.owner);
+                       return ShowDialog (null);
                }
 
                public DialogResult ShowDialog(IWin32Window ownerWin32) {
@@ -1245,34 +1496,51 @@ namespace System.Windows.Forms {
                        bool            confined;
                        IntPtr          capture_window;
 
-                       owner = null;
+                       Form owner_to_be = null;
+
+                       if ((ownerWin32 == null) && (Application.MWFThread.Current.Context != null)) {
+                               IntPtr active = XplatUI.GetActive ();
+                               if (active != IntPtr.Zero) {
+                                       ownerWin32 = Control.FromHandle (active) as Form;
+                               }
+                       }
 
                        if (ownerWin32 != null) {
                                Control c = Control.FromHandle (ownerWin32.Handle);
                                if (c != null)
-                                       owner = c.TopLevelControl as Form;
+                                       owner_to_be = c.TopLevelControl as Form;
                        }
 
-                       if (owner == this) {
-                               throw new InvalidOperationException("The 'ownerWin32' cannot be the form being shown.");
+                       if (owner_to_be == this) {
+                               throw new ArgumentException ("Forms cannot own themselves or their owners.", "owner");
                        }
 
                        if (is_modal) {
-                               throw new InvalidOperationException("The form is already displayed as a modal dialog.");
+                               throw new InvalidOperationException ("The form is already displayed as a modal dialog.");
                        }
 
                        if (Visible) {
-                               throw new InvalidOperationException("Already visible forms cannot be displayed as a modal dialog. Set the Visible property to 'false' prior to calling Form.ShowDialog.");
+                               throw new InvalidOperationException ("Forms that are already "
+                                       + " visible cannot be displayed as a modal dialog. Set the"
+                                       + " form's visible property to false before calling"
+                                       + " ShowDialog.");
                        }
 
                        if (!Enabled) {
-                               throw new InvalidOperationException("Cannot display a disabled form as modal dialog.");
+                               throw new InvalidOperationException ("Forms that are not enabled"
+                                       + " cannot be displayed as a modal dialog. Set the form's"
+                                       + " enabled property to true before calling ShowDialog.");
                        }
 
                        if (TopLevelControl != this) {
-                               throw new InvalidOperationException("Can only display TopLevel forms as modal dialog.");
+                               throw new InvalidOperationException ("Forms that are not top level"
+                                       + " forms cannot be displayed as a modal dialog. Remove the"
+                                       + " form from any parent form before calling ShowDialog.");
                        }
 
+                       if (owner_to_be != null)
+                               owner = owner_to_be;
+                               
                        #if broken
                        // Can't do this, will screw us in the modal loop
                        form_parent_window.Parent = this.owner;
@@ -1327,7 +1595,12 @@ namespace System.Windows.Forms {
                        base.AdjustFormScrollbars (displayScrollbars);
                }
 
+#if NET_2_0
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               [Obsolete ("This method has been deprecated")] // XXX what to use instead?
+#else
                [EditorBrowsable(EditorBrowsableState.Advanced)]
+#endif
                protected void ApplyAutoScaling()
                {
                        SizeF current_size_f = GetAutoScaleSize (DeviceContext, Font);
@@ -1369,6 +1642,12 @@ namespace System.Windows.Forms {
                        int     w;
                        int     h;
 
+                       // MS creates the handle here.
+                       if (TopLevel) {
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
+                       }
+                       
                        if (Width > 0) {
                                w = Width;
                        } else {
@@ -1398,6 +1677,12 @@ namespace System.Windows.Forms {
                        int     w;
                        int     h;
 
+                       // MS creates the handle here.
+                       if (TopLevel) {
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
+                       }
+                       
                        if (Width > 0) {
                                w = Width;
                        } else {
@@ -1423,7 +1708,9 @@ namespace System.Windows.Forms {
                protected override void CreateHandle() {
                        base.CreateHandle ();
 
-                       Application.AddForm (this);
+                       if (!IsHandleCreated) {
+                               return;
+                       }
                        
                        UpdateBounds();
 
@@ -1439,16 +1726,23 @@ namespace System.Windows.Forms {
                        }
 
                        if ((owner != null) && (owner.IsHandleCreated)) {
-                               XplatUI.SetTopmost(window.Handle, owner.window.Handle, true);
+                               XplatUI.SetOwner(window.Handle, owner.window.Handle);
+                       }
+
+                       if (topmost) {
+                               XplatUI.SetTopmost(window.Handle, topmost);
                        }
 
                        for (int i = 0; i < owned_forms.Count; i++) {
                                if (owned_forms[i].IsHandleCreated)
-                                       XplatUI.SetTopmost(owned_forms[i].window.Handle, window.Handle, true);
+                                       XplatUI.SetOwner(owned_forms[i].window.Handle, window.Handle);
                        }
                        
-                       if (window_manager != null && window_state != FormWindowState.Normal) {
-                               window_manager.SetWindowState (FormWindowState.Normal, window_state);
+                       if (window_manager != null) {
+                               if (window_state != FormWindowState.Normal) {
+                                       window_manager.SetWindowState ((FormWindowState) int.MaxValue, window_state);
+                               }
+                               XplatUI.RequestNCRecalc (window.Handle);
                        }
 
                }
@@ -1473,9 +1767,6 @@ namespace System.Windows.Forms {
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnActivated(EventArgs e)
                {
-                       if (is_loaded)
-                               SelectActiveControl ();
-
                        EventHandler eh = (EventHandler)(Events [ActivatedEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -1488,7 +1779,8 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               [EditorBrowsable(EditorBrowsableState.Advanced)]
+               // Consider calling FireClosingEvents instead of calling this directly.
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
                protected virtual void OnClosing(System.ComponentModel.CancelEventArgs e) {
                        CancelEventHandler eh = (CancelEventHandler)(Events [ClosingEvent]);
                        if (eh != null)
@@ -1505,14 +1797,8 @@ namespace System.Windows.Forms {
 
                        OnLoad(EventArgs.Empty);
                        
-                       SelectActiveControl ();
-
                        // Send initial location
                        OnLocationChanged(EventArgs.Empty);
-
-                       if (IsMdiContainer) {
-                               mdi_container.LayoutMdi (MdiLayout.Cascade);
-                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -1535,6 +1821,7 @@ namespace System.Windows.Forms {
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected override void OnHandleDestroyed(EventArgs e) {
+                       Application.RemoveForm (this);
                        base.OnHandleDestroyed (e);
                }
 
@@ -1553,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;
@@ -1625,16 +1914,16 @@ namespace System.Windows.Forms {
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected override void OnPaint (PaintEventArgs pevent) {
                        base.OnPaint (pevent);
+
+                       if (size_grip != null) {
+                               size_grip.HandlePaint (this, pevent);
+                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected override void OnResize(EventArgs e) {
                        base.OnResize(e);
 
-                       if (this.IsMdiChild && ParentForm != null) {
-                               ParentForm.PerformLayout();
-                               ParentForm.Size = ParentForm.Size;
-                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -1670,6 +1959,24 @@ namespace System.Windows.Forms {
                                return ActiveMenu.ProcessCmdKey(ref msg, keyData);
                        }
 
+                       if (IsMdiChild) {
+                               switch (keyData)
+                               {
+                               case Keys.Control | Keys.F4:
+                               case Keys.Control | Keys.Shift | Keys.F4:
+                                       Close ();
+                                       return true;
+                               case Keys.Control | Keys.Tab:
+                               case Keys.Control | Keys.F6:
+                                       MdiParent.MdiContainer.ActivateNextChild ();
+                                       return true;
+                               case Keys.Control | Keys.Shift | Keys.Tab:
+                               case Keys.Control | Keys.Shift | Keys.F6:
+                                       MdiParent.MdiContainer.ActivatePreviousChild ();
+                                       return true;
+                               }
+                       }
+
                        return false;
                }
 
@@ -1713,7 +2020,11 @@ namespace System.Windows.Forms {
                        return SelectNextControl(ActiveControl, forward, true, true, true);
                }
 
+#if NET_2_0
+               [EditorBrowsable(EditorBrowsableState.Never)]
+#else
                [EditorBrowsable(EditorBrowsableState.Advanced)]
+#endif
                protected override void ScaleCore(float dx, float dy) {
                        try {
                                SuspendLayout();
@@ -1751,6 +2062,12 @@ namespace System.Windows.Forms {
                protected override void Select(bool directed, bool forward) {
                        Form    parent;
 
+
+                       // MS causes the handle to be created here.
+                       if (!IsHandleCreated)
+                               if (!IsHandleCreated)
+                                       CreateHandle ();
+                       
                        if (directed) {
                                base.SelectNextControl(null, forward, true, true, true);
                        }
@@ -1788,17 +2105,59 @@ 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);
                        }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
-               protected override void SetVisibleCore(bool value) {
-                       is_changing_visible_state = true;
-                       has_been_visible = value || has_been_visible;
-                       base.SetVisibleCore (value);
-                       is_changing_visible_state = false;
+               protected override void SetVisibleCore(bool value)
+               {
+                       if (IsMdiChild && !MdiParent.Visible) {
+                               if (value != Visible) {
+                                       MdiWindowManager wm = (MdiWindowManager) window_manager;
+                                       wm.IsVisiblePending = value;
+                                       OnVisibleChanged (EventArgs.Empty);
+                                       return;
+                               }
+                       } else {
+                               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;
+                       }
+                       
+                       if (value && IsMdiContainer) {
+                               Form [] children = MdiChildren;
+                               for (int i = 0; i < children.Length; i++) {
+                                       Form child = children [i];
+                                       MdiWindowManager wm = (MdiWindowManager) child.window_manager;
+                                       if (!child.IsHandleCreated && wm.IsVisiblePending) {
+                                               wm.IsVisiblePending = false;
+                                               child.Visible = true;
+                                       }
+                               }
+                       }
+                       
+                       if (value && IsMdiChild){
+                               PerformLayout ();
+                               ThemeEngine.Current.ManagedWindowSetButtonLocations (window_manager);
+                       }
+                       
+                       // 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;
+                       }
                }
 
                protected override void UpdateDefaultButton() {
@@ -1807,311 +2166,462 @@ namespace System.Windows.Forms {
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected override void WndProc(ref Message m) {
+#if debug
+                       Console.WriteLine(DateTime.Now.ToLongTimeString () + " Form {0} ({2}) received message {1}", window.Handle == IntPtr.Zero ? this.Text : XplatUI.Window(window.Handle), m.ToString (), Text);
+#endif
 
-                       if (window_manager != null && window_manager.HandleMessage (ref m)) {
+                       if (window_manager != null && window_manager.WndProc (ref m)) {
                                return;
                        }
 
-                       switch((Msg)m.Msg) {
-                               case Msg.WM_DESTROY: {
-                                       base.WndProc(ref m);
-                                       if (!RecreatingHandle) {
-                                               this.closing = true;
-                                       }
-                                       return;
-                               }
+                       switch ((Msg)m.Msg) {
+                       case Msg.WM_DESTROY: {
+                               WmDestroy (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_CLOSE_INTERNAL: {
-                                       DestroyHandle();
-                                       break;
-                               }
+                       case Msg.WM_CLOSE: {
+                               WmClose (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_CLOSE: {
-                                       Form act = Form.ActiveForm;
-                                       if (act != null && act != this && act.Modal == true) {
-                                               return;
-                                       }
+                       case Msg.WM_WINDOWPOSCHANGED: {
+                               WmWindowPosChanged (ref m);
+                               return;
+                       }
 
-                                       CancelEventArgs args = new CancelEventArgs ();
+#if NET_2_0
+                       case Msg.WM_SYSCOMMAND: {
+                               WmSysCommand (ref m);
+                               break;
+                       }
+#endif
 
-                                       if (mdi_container != null) {
-                                               foreach (Form mdi_child in mdi_container.MdiChildren) {
-                                                       mdi_child.OnClosing (args);
-                                               }
-                                       }
+                       case Msg.WM_ACTIVATE: {
+                               WmActivate (ref m);
+                               return;
+                       }
 
-                                       if (!is_modal) {
-                                               OnClosing (args);
-                                               if (!args.Cancel) {
-                                                       OnClosed (EventArgs.Empty);
-                                                       closing = true;
-                                               }
-                                               Dispose ();
-                                       } else {
-                                               OnClosing (args);
-                                               if (args.Cancel) {
-                                                       DialogResult = DialogResult.None;
-                                                       closing = false;
-                                               } else {
-                                                       OnClosed (EventArgs.Empty);
-                                                       closing = true;
-                                                       Hide ();
-                                               }
-                                       }
+                       case Msg.WM_KILLFOCUS: {
+                               WmKillFocus (ref m);
+                               return;
+                       }
 
-                                       return;
-                               }
+                       case Msg.WM_SETFOCUS: {
+                               WmSetFocus (ref m);
+                               return;
+                       }
 
-                               case Msg.WM_WINDOWPOSCHANGED: {
-                                       if (WindowState != FormWindowState.Minimized) {
-                                               base.WndProc(ref m);
-                                       }
+                       // Menu drawing
+                       case Msg.WM_NCHITTEST: {
+                               WmNcHitTest (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCLBUTTONDOWN: {
+                               WmNcLButtonDown (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCLBUTTONUP: {
+                               WmNcLButtonUp (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCMOUSELEAVE: {
+                               WmNcMouseLeave (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCMOUSEMOVE: {
+                               WmNcMouseMove (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCPAINT: {
+                               WmNcPaint (ref m);
+                               return;
+                       }
+
+                       case Msg.WM_NCCALCSIZE: {
+                               WmNcCalcSize (ref m);
+                               break;
+                       }
+
+                       case Msg.WM_MOUSEMOVE: {
+                               WmMouseMove (ref m);
+                               break;
+                       }
+
+                       case Msg.WM_LBUTTONDOWN:
+                       case Msg.WM_MBUTTONDOWN:
+                       case Msg.WM_RBUTTONDOWN: {
+                               WmButtonDown (ref m);
+                               return;
+                       }
+
+                       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;
                                }
+                       }
 
+                       if (mdi_container != null) {
+                               foreach (Form mdi_child in mdi_container.MdiChildren) {
+                                       mdi_child.FireClosingEvents (CloseReason.MdiFormClosing);
+                               }
+                       }
+
+                       if (!is_modal) {
+                               if (!FireClosingEvents (CloseReason.UserClosing)) {
+                                       OnClosed (EventArgs.Empty);
 #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;
+                                       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));
 #endif
-       
-                               case Msg.WM_ACTIVATE: {
-                                       if (m.WParam != (IntPtr)WindowActiveFlags.WA_INACTIVE) {
-                                               OnActivated(EventArgs.Empty);
-                                       } else {
-                                               OnDeactivate(EventArgs.Empty);
-                                       }
-                                       return;
+                                       closing = true;
+                                       Hide ();
                                }
+                       }
 
-                               case Msg.WM_KILLFOCUS: {
-                                       base.WndProc(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?
-                                       }
-                                       base.WndProc(ref m);
-                                       return;
-                               }
+                       mdi_parent = null;
+               }
+               
+               private void WmWindowPosChanged (ref Message m)
+               {
+                       if (WindowState != FormWindowState.Minimized) {
+                               base.WndProc (ref m);
+                       }
+               }
 
-                               // Menu drawing
-                               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));
-                                       }
+#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) {
-                                               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);
-                                       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;
-                               }
+                       base.WndProc (ref m);
+               }
+#endif 
+               private void WmActivate (ref Message m)
+               {
+                       if (m.WParam != (IntPtr)WindowActiveFlags.WA_INACTIVE) {
+                               if (is_loaded) {
+                                       SelectActiveControl ();
 
-                               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;
-                               }
-                               
-                               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;
+                                       if (ActiveControl != null && !ActiveControl.Focused)
+                                               SendControlFocus (ActiveControl);
                                }
 
-                               case Msg.WM_NCPAINT: {
-                                       if (ActiveMenu != null) {
-                                               PaintEventArgs  pe;
-                                               Point           pnt;
-
-                                               pe = XplatUI.PaintEventStart(Handle, false);
-                                               pnt = XplatUI.GetMenuOrigin(window.Handle);
+                               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 ());
 
-                                               // 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));
+                               XplatUI.ScreenToMenu (ActiveMenu.Wnd.window.Handle, ref x, ref y);
 
-                                               if (ActiveMaximizedMdiChild != null) {
-                                                       ActiveMaximizedMdiChild.DrawMaximizedButtons (ActiveMenu, pe);
-                                               }
+                               // 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;
+                               }
+                       }
 
-                                               XplatUI.PaintEventEnd(Handle, false);
-                                       }
+                       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));
+                       }
 
-                                       base.WndProc(ref m);
+                       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_NCCALCSIZE: {
-                                       XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
+                       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;
 
-                                       if ((ActiveMenu != null) && (m.WParam == (IntPtr)1)) {
-                                               ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
+                               pe = XplatUI.PaintEventStart (Handle, false);
+                               pnt = XplatUI.GetMenuOrigin (window.Handle);
 
-                                               // Adjust for menu
-                                               ncp.rgrc1.top += ThemeEngine.Current.CalcMenuBarSize (DeviceContext, ActiveMenu, ncp.rgrc1.right - ncp.rgrc1.left);
-                                               Marshal.StructureToPtr(ncp, m.LParam, true);
-                                       }
-                                       DefWndProc(ref m);
-                                       break;
-                               }
+                               // 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);
 
-                               case Msg.WM_MOUSEMOVE: {
-                                       if (XplatUI.IsEnabled (Handle) && active_tracker != null) {
-                                               MouseEventArgs args;
+                               ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0));
 
-                                               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;
+                               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);
+                       }
 
-                                               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;
+                       base.WndProc (ref m);
+               }
+               
+               private void WmNcCalcSize (ref Message m)
+               {
+                       XplatUIWin32.NCCALCSIZE_PARAMS ncp;
+
+                       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));
                                        }
-                                       base.WndProc(ref m);
-                                       return;
                                }
 
+                               return;
+                       }
+#if NET_2_0
+                       ToolStripManager.FireAppClicked ();
+#endif
+                       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;
-
-                                       if (m.LParam != IntPtr.Zero) {
-                                               mmi = (MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
+                               MouseEventArgs args = new MouseEventArgs (
+                                       mb,
+                                       mouse_clicks,
+                                       Control.MousePosition.X,
+                                       Control.MousePosition.Y,
+                                       0);
 
-                                               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 ()
+               {
+                       // do nothing - forms don't generate OnEnter
+               }
+
+               internal override void FireLeave ()
+               {
+                       // do nothing - forms don't generate OnLeave
+               }
 
                internal void RemoveWindowManager ()
                {
@@ -2136,6 +2646,8 @@ namespace System.Windows.Forms {
                                }
                        }
                }
+
+               internal override bool ActivateOnShow { get { return !this.ShowWithoutActivation; } }
                
                #region Events
                static object ActivatedEvent = new object ();
@@ -2157,11 +2669,19 @@ namespace System.Windows.Forms {
                        remove { Events.RemoveHandler (ActivatedEvent, value); }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+#endif
                public event EventHandler Closed {
                        add { Events.AddHandler (ClosedEvent, value); }
                        remove { Events.RemoveHandler (ClosedEvent, value); }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+#endif
                public event CancelEventHandler Closing {
                        add { Events.AddHandler (ClosingEvent, value); }
                        remove { Events.RemoveHandler (ClosingEvent, value); }
@@ -2202,11 +2722,17 @@ namespace System.Windows.Forms {
                        remove { Events.RemoveHandler (MdiChildActivateEvent, value); }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+#endif
                public event EventHandler MenuComplete {
                        add { Events.AddHandler (MenuCompleteEvent, value); }
                        remove { Events.RemoveHandler (MenuCompleteEvent, value); }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+#endif
                public event EventHandler MenuStart {
                        add { Events.AddHandler (MenuStartEvent, value); }
                        remove { Events.RemoveHandler (MenuStartEvent, value); }
@@ -2224,9 +2750,9 @@ namespace System.Windows.Forms {
                        add { base.TabIndexChanged += value; }
                        remove { base.TabIndexChanged -= value; }
                }
-               #endregion      // Events
 
 #if NET_2_0
+               [SettingsBindable (true)]
                public override string Text {
                        get {
                                return base.Text;
@@ -2237,6 +2763,7 @@ namespace System.Windows.Forms {
                        }
                }
 
+               [SettingsBindable (true)]
                public new Point Location {
                        get {
                                return base.Location;
@@ -2249,6 +2776,25 @@ namespace System.Windows.Forms {
 
                static object FormClosingEvent = new object ();
                static object FormClosedEvent = new object ();
+               static object HelpButtonClickedEvent = new object ();
+               static object ResizeEndEvent = new object ();
+               static object ResizeBeginEvent = new object ();
+               static object RightToLeftLayoutChangedEvent = new object ();
+               static object ShownEvent = new object ();
+
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               public new event EventHandler AutoSizeChanged {
+                       add { base.AutoSizeChanged += value; }
+                       remove { base.AutoSizeChanged -= value; }
+               }
+
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               public new event EventHandler AutoValidateChanged {
+                       add { base.AutoValidateChanged += value; }
+                       remove { base.AutoValidateChanged -= value; }
+               }
 
                public event FormClosingEventHandler FormClosing {
                        add { Events.AddHandler (FormClosingEvent, value); }
@@ -2259,13 +2805,125 @@ namespace System.Windows.Forms {
                        add { Events.AddHandler (FormClosedEvent, value); }
                        remove { Events.RemoveHandler (FormClosedEvent, value); }
                }
+
+               [Browsable (true)]
+               [EditorBrowsable (EditorBrowsableState.Always)]
+               public event CancelEventHandler HelpButtonClicked {
+                       add { Events.AddHandler (HelpButtonClickedEvent, value); }
+                       remove { Events.RemoveHandler (HelpButtonClickedEvent, value); }
+               }
+
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public new event EventHandler MarginChanged {
+                       add { base.MarginChanged += value; }
+                       remove { base.MarginChanged -= value; }
+               }
+
+               public event EventHandler RightToLeftLayoutChanged {
+                       add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
+                       remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
+               }
+
+               public event EventHandler ResizeBegin {
+                       add { Events.AddHandler (ResizeBeginEvent, value); }
+                       remove { Events.RemoveHandler (ResizeBeginEvent, value); }
+               }
+
+               public event EventHandler ResizeEnd {
+                       add { Events.AddHandler (ResizeEndEvent, value); }
+                       remove { Events.RemoveHandler (ResizeEndEvent, value); }
+               }
+
+               public event EventHandler Shown {
+                       add { Events.AddHandler (ShownEvent, value); }
+                       remove { Events.RemoveHandler (ShownEvent, value); }
+               }
+
+               [Browsable (false)]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public new event EventHandler TabStopChanged {
+                       add { base.TabStopChanged += value; }
+                       remove { base.TabStopChanged -= value; }
+               }
+
+               protected override void OnBackgroundImageChanged (EventArgs e)
+               {
+                       base.OnBackgroundImageChanged (e);
+               }
+
+               protected override void OnBackgroundImageLayoutChanged (EventArgs e)
+               {
+                       base.OnBackgroundImageLayoutChanged (e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override void OnEnabledChanged (EventArgs e)
+               {
+                       base.OnEnabledChanged (e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected override void OnEnter (EventArgs e)
+               {
+                       base.OnEnter (e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected virtual void OnFormClosed (FormClosedEventArgs e) {
+                       Application.RemoveForm (this);
+                       FormClosedEventHandler eh = (FormClosedEventHandler)(Events[FormClosedEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
                
+               // Consider calling FireClosingEvents instead of calling this directly.
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
                protected virtual void OnFormClosing (FormClosingEventArgs e)
                {
                        FormClosingEventHandler eh = (FormClosingEventHandler)(Events [FormClosingEvent]);
                        if (eh != null)
                                eh (this, e);
                }
+
+               [MonoTODO ("Not hooked up to event")]
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected virtual void OnHelpButtonClicked (CancelEventArgs e)
+               {
+                       CancelEventHandler eh = (CancelEventHandler)(Events[HelpButtonClickedEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
+
+               protected override void OnLayout (LayoutEventArgs levent)
+               {
+                       base.OnLayout (levent);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected virtual void OnResizeBegin (EventArgs e)
+               {
+                       EventHandler eh = (EventHandler) (Events [ResizeBeginEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected virtual void OnResizeEnd (EventArgs e)
+               {
+                       EventHandler eh = (EventHandler) (Events [ResizeEndEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               protected virtual void OnShown (EventArgs e)
+               {
+                       EventHandler eh = (EventHandler) (Events [ShownEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
 #endif
+               #endregion      // Events
        }
 }