Search code examples
c#winformssubclassing

How can I find out if a user is trying to maximize a window before it happens with subclassing?


I'm trying to catch a message in a subclassed form and make a new event from it so I can check things before it happens and then cancel the message if needed.

I want to know if the user is trying to maximize the form, then based on a global variable, pass along the message to the base.

public class APIConstants
{
    public const uint SWP_NOSIZE = 0x0001;
}

public class APIs
{
    [DllImport("kernel32", CharSet = CharSet.Auto)]
    public static extern void CopyMemory(WINDOWPOS pDst, IntPtr pSrc, int ByteLen);
}

public class Structures
{
    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public uint flags;
    }
}

How I'm currently subclassing the form...

protected override void WndProc(ref Message m)
{
    WinMsgs msg = new WinMsgs(m.Msg);

    switch (msg.Message)
    {
        case WinMsgs.WinMessages.WM_WINDOWPOSCHANGING:
            Structures.WINDOWPOS wPos = new Structures.WINDOWPOS();
            APIs.CopyMemory(wPos, m.LParam, Marshal.SizeOf(wPos));
            if ((wPos.flags & APIConstants.SWP_NOSIZE) != 0)
            {
                Debug.WriteLine("NOSIZE");
            }

            break;
    }
}

Reading around I thought the key was to just look if the flags passed with the message included SWP_NOSIZE. My form has a FormBorderStyle of FixedSingle (not sure if that affects the results or not). But for some reason it doesn't feel like I'm getting any good data in the wPos structure I fill with CopyMemory.

What am I doing wrong?


Solution

  • Check for the Window's message WM_SYSCOMMAND.

    A window receives this message when the user chooses a command from the Window menu (formerly known as the system or control menu) or when the user chooses the maximize button, minimize button, restore button, or close button.

    Then check the WParam property to see if it is equal to SC_MAXIMIZE to determine if a maximize window request has been issued.

    protected override void WndProc(ref Message m)
    {
        const Int32 WM_SYSCOMMAND = 0x112;
        const Int32 SC_MAXIMIZE = 0xF030;
    
        if (m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MAXIMIZE)
        {
            // do what you need to before maximizing
        }
    
        base.WndProc(ref m); // let the base class process the message
    }