How to override form's Maximize button operation?

G

Guest

I am developing a Windows Forms application in VS.NET 2003 and C#. The
application is using the MDI style. I have one or more child forms visible
in the client area of the main form.

I want to keep the MaximizeBox property set to True so that the user can
click the maximize button on the title bar. However, I want to catch this
event and perform my own version of a maximize operation. I have tried
catching the SW_MAXIMIZE message in the child form's WndProc and call my own
max function, but it still does the normal maximize operation. See sample
code below.

How can I override this message or event?

Thanks,
Dave

######## Code #######

protected override void WndProc( ref Message m )
{
if ( m.Msg == User32DllImports.SW_MAXIMIZE )
{
Debug.WriteLine( "SW_MAXIMIZE message." );
this.Zoom( mdiParent.UsableClientAreaSize() );
return;
}
}

###################
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Thanks for your posting!!

When a form's window is maximized, no SW_MAXIMIZE is sent to the WndProc,
instead, a WM_SYSCOMMAND message(whose wParam is SC_MAXIMIZE) is sent to
the Window procedure, so we may intercept and filter the maximize operation
with the code snippet below:

const int WM_SYSCOMMAND= 0x0112;
const int SC_MAXIMIZE= 0xF030;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_SYSCOMMAND)
{
if((int)m.WParam==SC_MAXIMIZE)
{
MessageBox.Show("Maximized!!");
return;
}
}
base.WndProc (ref m);
}
It works well on my side. Hope it helps
========================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Jeffrey,

Using the WM_SYSCOMMAND and SC_MAXIMIZE worked great. I can now "zoom" the
child form to meet my needs. However, I would like to change the Maximize
button appearance to the expected Restore button when the form is zoomed.
Conversly, I would like to change the Restore button appearance to the
expected Maximize button when the form is unzoomed.

Is there a message to send, a method to call or a property to set on the
child form to change the Maximize button to Restore and to change the Restore
button to Maximize?

Thanks,
Dave
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Thanks for your feedback!

I am not sure which customized zoom operation you want to do. For your
requirement, we may just explicitly change the window style to WS_MAXIMIZE
to simulate the window maximize state effect.
To achieve this, we may P/invoke SetWindowLong win32 API with GWL_STYLE to
add WS_MAXIMIZE to the window. Also, as MSDN document said, we have to use
SetWindowPos API to refresh the window style changes. Code snippet lists
below:

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[Obsolete("This function is unsafe. Use GetWindowLongPtr instead."),
DllImport("user32.dll", SetLastError=true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);

const int WS_MAXIMIZE = 0x01000000;
const int GWL_STYLE= -16;
const int WM_SYSCOMMAND= 0x0112;
const int SC_MAXIMIZE= 0xF030;
const int SC_RESTORE=0xF120;
IntPtr HWND_TOP=(IntPtr)0;
const int SWP_SHOWWINDOW=0x0040;
const int SWP_NOZORDER=0x0004;
const int SWP_NOMOVE=0x0002;
const int SWP_DRAWFRAME=0x0020;

protected override void WndProc(ref Message m)
{
if(m.Msg==WM_SYSCOMMAND)
{
if((int)m.WParam==SC_MAXIMIZE)
{
MessageBox.Show("Maximized!!");
int iStyle=GetWindowLong(this.Handle, GWL_STYLE);
SetWindowLong(this.Handle, GWL_STYLE, iStyle|WS_MAXIMIZE);
SetWindowPos(this.Handle, HWND_TOP, 0, 0, this.Width, this.Height,
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
return;
}
if((int)m.WParam==SC_RESTORE)
{
MessageBox.Show("Restored down!!");
int iStyle=GetWindowLong(this.Handle, GWL_STYLE);
SetWindowLong(this.Handle, GWL_STYLE, iStyle&~WS_MAXIMIZE);
SetWindowPos(this.Handle, HWND_TOP, 0, 0, this.Width, this.Height,
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
return;
}
}
base.WndProc (ref m);
}
Note: I used SWP_NOMOVE in the code to make the window not move, you need
change the parameters in SetWindowPos API to do your customized zoom
operation. Hope this helps
=======================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Jeffrey,

Your suggestion does not do what I need. It is close, but not quite what I
need. Let me make sure you know what I am trying to do:

My application is using the MDI style.
The main form is not changing size.
An MDI child form is being displayed in the MDI main form's client area.
The child form is initially one-quarter the size of the client area.
Clicking the MaximizeBox button should cause the child form to double in area.
The Maximize (Restore) button should remain part of the child form's title
bar.

The problem with your suggestion is that when the maximize button is
clicked, the child form changes size as I want, but the maximize (and
minimize and close) button is no longer part of the child form's title bar,
but has been attached to the main form's menu bar.

So what I want to do is keep the control buttons on the title bar of the
child form and have the MaximizeBox switch between the Maximize and Restore
button appearance.

Can this be done?

Thanks,
Dave

"Jeffrey Tan[MSFT]" said:
Hi Dave,

Thanks for your feedback!

I am not sure which customized zoom operation you want to do. For your
requirement, we may just explicitly change the window style to WS_MAXIMIZE
to simulate the window maximize state effect.
To achieve this, we may P/invoke SetWindowLong win32 API with GWL_STYLE to
add WS_MAXIMIZE to the window. Also, as MSDN document said, we have to use
SetWindowPos API to refresh the window style changes. Code snippet lists
below:

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[Obsolete("This function is unsafe. Use GetWindowLongPtr instead."),
DllImport("user32.dll", SetLastError=true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);

const int WS_MAXIMIZE = 0x01000000;
const int GWL_STYLE= -16;
const int WM_SYSCOMMAND= 0x0112;
const int SC_MAXIMIZE= 0xF030;
const int SC_RESTORE=0xF120;
IntPtr HWND_TOP=(IntPtr)0;
const int SWP_SHOWWINDOW=0x0040;
const int SWP_NOZORDER=0x0004;
const int SWP_NOMOVE=0x0002;
const int SWP_DRAWFRAME=0x0020;

protected override void WndProc(ref Message m)
{
if(m.Msg==WM_SYSCOMMAND)
{
if((int)m.WParam==SC_MAXIMIZE)
{
MessageBox.Show("Maximized!!");
int iStyle=GetWindowLong(this.Handle, GWL_STYLE);
SetWindowLong(this.Handle, GWL_STYLE, iStyle|WS_MAXIMIZE);
SetWindowPos(this.Handle, HWND_TOP, 0, 0, this.Width, this.Height,
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
return;
}
if((int)m.WParam==SC_RESTORE)
{
MessageBox.Show("Restored down!!");
int iStyle=GetWindowLong(this.Handle, GWL_STYLE);
SetWindowLong(this.Handle, GWL_STYLE, iStyle&~WS_MAXIMIZE);
SetWindowPos(this.Handle, HWND_TOP, 0, 0, this.Width, this.Height,
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
return;
}
}
base.WndProc (ref m);
}
Note: I used SWP_NOMOVE in the code to make the window not move, you need
change the parameters in SetWindowPos API to do your customized zoom
operation. Hope this helps
=======================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Dave,

Thanks for your feedback!!

When user clicks MDI child's maximizebox button, are you doing the zoom
with yourself code or you pass the operation to the default WndProc?
Actually, for MDI forms, the default behavior is combining the MDI Child
form's minimize/maximize and restore box buttons with its MDI parent's menu
bar. This is the default behavior of Windows' default WndProc processing,
which is out of our control. So normally, I can not think of any way to
disable this behavior.

Maybe we may intercept the maximize operation and do the zoom with
ourselves code, then DO NOT pass it for the processing of the default
WndProc. This should workaround the default behavior. For example, we may
first get the client size of MDI parent, then use SetWindowPos API to zoom
the MDI Child to maximize state ourselves. But this may result in some
other side effect, for example, because the caption bar of MDI Child is
still available(which is not combined with the MDI parent form), the user
still can drag MDI Child's caption bar and move it, which is a strange
behavior for Maximized form. Certainly, we may also write some code to
disable the move operation. But I am not sure if there will be some other
tough or strange problems.

Anyway, we suggest you do not change the default behavior of MDI
application, because it will give the user more consistent user experience
for MDI app.

Hope this information helps.
===================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top