private static IntPtr WindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr oldWndProc = GetProp(hWnd, "SystemMenu");

            try
            {
                switch (msg)
                {
                case WM_DESTROY:
                    //Automatically uninstall ourself upon Form close
                    SetWindowLongPtr(hWnd, GWL_WNDPROC, oldWndProc);
                    break;

                case WM_SYSCOMMAND:
                    //if (wParam.ToInt32() >= SC_MENUSTART) break;
                    IntPtr handler = GetProp(hWnd, "SystemMenuHandler");
                    if (handler != IntPtr.Zero)
                    {
                        //SystemMenuHandler syshandler = Marshal.GetDelegateForFunctionPointer(handler, typeof(SystemMenuHandler)) as SystemMenuHandler;   //This only works for static methods!
                        SystemMenuHandler syshandler = GCHandle.FromIntPtr(handler).Target as SystemMenuHandler;
                        if (syshandler.Invoke(wParam.ToInt32()))
                        {
                            return(IntPtr.Zero);
                        }
                    }
                    break;
                }
            }
            catch
            {
                //if we get an unhandled error, uninstall ourself.
                SetWindowLongPtr(hWnd, GWL_WNDPROC, oldWndProc);
            }
            return(CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam));
        }
        /// <summary>
        /// Assign a handler for the system menu events. There can only be one.
        /// Any previously set handler will be replaced. This cannot be called
        /// in the constructor because the underlying Win32 window has not yet
        /// been created. Should be called during the Form.Load event.
        /// </summary>
        /// <param name="form">form to assign the handler to</param>
        /// <param name="handler">Delegate handler to handle the events</param>
        public static void SetHandler(Form form, SystemMenuHandler handler)
        {
            IntPtr hWnd = form.Handle;

            if (hWnd == null || hWnd == IntPtr.Zero)
            {
                return;
            }
            //IntPtr handle = Marshal.GetFunctionPointerForDelegate(handler); //This only works for static methods!
            IntPtr handle = GCHandle.ToIntPtr(GCHandle.Alloc(handler));

            SetProp(hWnd, "SystemMenuHandler", handle);

            if (GetProp(hWnd, "SystemMenu") != IntPtr.Zero)
            {
                return;                                              //Only subclass once!
            }
            IntPtr wndProcPtr = Marshal.GetFunctionPointerForDelegate(_wndProc);

            SetProp(hWnd, "SystemMenu", SetWindowLongPtr(hWnd, GWL_WNDPROC, wndProcPtr));
        }