Restoring a Maximized or Minimized MDI Parent Form Causes its Height to Shrink

Article ID: 967173 – Last Review: January 29, 2009 – Revision: 1.0

Restoring a Maximized or Minimized MDI Parent Form Causes its Height to Shrink

Source: Microsoft Support

RAPID PUBLISHING

RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.

Symptom

When restoring a maximized or minimized MDI parent form, the height of the restored MDI parent form shrinks.

Cause

This behavior occurs when the MDI parent form does not contain a menu, and if it contains a maximized MDI child form. Under these circumstances, the MDI parent window calculates the window size incorrectly when trying to restore from a maximized or minimized window. This is a bug in Windows Forms (System.Windows.Forms.dll) within the Microsoft .NET Framework.

Resolution

If possible, add a MenuStrip control to the MDI parent form. This is the easiest workaround. Alternatively, you can override the form’s WndProc procedure, and reset the appropriate height of the form when it is restored. The following sample code demonstrates how to do this.

Sample Code in Visual Basic .NET
============================
 
Public Class Form1
    Inherits System.Windows.Forms.Form

    Private currentHeight As Integer
    Const WM_SYSCOMMAND As Integer = &H112
    Const SC_RESTORE As Integer = &HF120

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
       If m.Msg = WM_SYSCOMMAND Then
          ‘Check to see if the window state is being restored.
          ‘If so, reset the Height to the value we cached
          If IsRestoring(m.WParam) Then
             Me.Height = currentHeight
          End If
       End If

       ‘If the current state is normal (restored), then cache the height
       If Me.WindowState = FormWindowState.Normal Then
          currentHeight = Me.Size.Height
       End If
       MyBase.WndProc(m)
    End Sub

    Function IsRestoring(ByVal WParam As IntPtr) As Boolean
       ‘Used to determine the state of the WParam to see if it is SC_RESTORE
       ‘RETURNS: True or False depending on if SC_RESTORE is set

       ‘We must determine the size of the pointer from the OS we are using.
       ‘If using 32-bit pointers, we need to cast WParam to Int32. If using
       ’64-bit pointers, we cast to Int64. Then we assign to our UInt32 variable.

       ‘Note that when processing WM_SYSCOMMAND, we must use the AND operator to combine with &HFFF0 as
       ‘documented on MSDN at http://msdn.microsoft.com/en-us/library/ms646360.aspx

       Dim param As UInt32
       If IntPtr.Size = 4 Then ’32-bit
          param = CUInt(WParam.ToInt32)
       Else
          param = CUInt(WParam.ToInt64) ’64-bit
       End If
       Return ((param And &HFFF0) = SC_RESTORE)
    End Function
End Class

Sample Code in Visual C#
======================
public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();
   }

   private int currentHeight;
   private const int WM_SYSCOMMAND = 0x112;
   private const int SC_RESTORE = 0xF120;

   protected override void WndProc(ref Message m)
   {
      if (m.Msg == WM_SYSCOMMAND)
      {
         //Check to see if the window state is being restored.
         //If so, reset the Height to the value we cached
         if (IsRestoring(m.WParam))
         {
            this.Height = currentHeight;
         }
      }

      //If the current state is normal (restored), then cache the height
      if (this.WindowState == FormWindowState.Normal)
      {
         currentHeight = this.Size.Height;
      }
      base.WndProc(ref m);
   }

   bool IsRestoring(IntPtr WParam)
   {
      //Used to determine the state of the WParam to see if it is SC_RESTORE
      //RETURNS: True or False depending on if SC_RESTORE is set

      //We must determine the size of the pointer from the OS we are using.
      //If using 32-bit pointers, we need to cast WParam to Int32. If using
      //64-bit pointers, we cast to Int64. Then we assign to our UInt32 variable.

      //Note that when processing WM_SYSCOMMAND, we must use the AND operator to combine with 0xHFFF0 as
      //documented on MSDN at http://msdn.microsoft.com/en-us/library/ms646360.aspx 

      UInt32 param;
      if(IntPtr.Size == 4)// 32-bit
      {
         param = (UInt32)(WParam.ToInt32());
      }
      else // 64-bit
      {
         param = (UInt32)(WParam.ToInt64());
      }
      return ((param & 0xFFF0) == SC_RESTORE);
   }
}

More Information

Steps To Reproduce Problem
========================
1. Create a new Windows Forms application using Visual Basic 2005 or 2008.
2. For the default form (Form1), set the IsMDIContainer property to True in the Windows Form Designer.
3. On the Project menu, select Add Windows Form.
4. Keep the default name (Form2), and click Add.
5. Save Form2 and close it.
6. Add the following code to the Load event handler in Form1.

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   Me.StartPosition = FormStartPosition.Manual
   Dim f2 As New Form2
   f2.MdiParent = Me
   f2.WindowState = FormWindowState.Maximized
   f2.Show()
End Sub

7. On the Debug menu, click Start Debugging. Note that the MDI Parent form is displayed in a restored window, with a maximized child window.
8. Maximize or minimize the MDI Parent form.
9. Restore the MDI Parent form. Note the bottom edge of MDI Parent form has crept up slightly.
10. Repeat steps 8-9 as needed to see the effect occur over time.

DISCLAIMER

MICROSOFT AND/OR ITS SUPPLIERS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY, RELIABILITY OR ACCURACY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS WEBSITE (THE “MATERIALS”) FOR ANY PURPOSE. THE MATERIALS MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS AND MAY BE REVISED AT ANY TIME WITHOUT NOTICE.

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND/OR ITS SUPPLIERS DISCLAIM AND EXCLUDE ALL REPRESENTATIONS, WARRANTIES, AND CONDITIONS WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO REPRESENTATIONS, WARRANTIES, OR CONDITIONS OF TITLE, NON INFRINGEMENT, SATISFACTORY CONDITION OR QUALITY, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE MATERIALS.


APPLIES TO
  • Microsoft .NET Framework 2.0
  • Microsoft .NET Framework 3.0
  • Microsoft .NET Framework 3.5
Keywords: 
kbnomt kbrapidpub KB967173

 

Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
Microsoft Corporation. All rights reserved. Terms of Use | Trademarks


You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

AddThis Social Bookmark Button

Leave a Reply

*
To prove that you're not a bot, enter this code
Anti-Spam Image