예제 #1
0
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                case NativeMethods.WM_SETTEXT:
                case NativeMethods.WM_SETICON:
                    {
                        bool modified = ModifyStyle(NativeMethods.WS_VISIBLE, 0);

                        // Setting the caption text and icon cause Windows to redraw the caption.
                        // Letting the default WndProc handle the message without the WS_VISIBLE
                        // style applied bypasses the redraw.
                        IntPtr lRet = NativeMethods.DefWindowProc(handle, msg, wParam, lParam);

                        // Put back the style we removed.
                        if (modified)
                        {
                            ModifyStyle(0, NativeMethods.WS_VISIBLE);
                        }
                        handled = true;
                        return lRet;
                    }
                case NativeMethods.WM_NCACTIVATE:
                    {
                        // Despite MSDN's documentation of lParam not being used,
                        // calling DefWindowProc with lParam set to -1 causes Windows not to draw over the caption.

                        // Directly call DefWindowProc with a custom parameter
                        // which bypasses any other handling of the message.
                        IntPtr lRet = NativeMethods.DefWindowProc(handle, NativeMethods.WM_NCACTIVATE, wParam, new IntPtr(-1));
                        IsNonClientAreaActive = (wParam != IntPtr.Zero);
                        handled = true;
                        return lRet;
                    }
                case NativeMethods.WM_NCCALCSIZE:
                    {
                        if (WindowState == WindowState.Maximized)
                        {
                            NativeMethods.APPBARDATA abd = new NativeMethods.APPBARDATA();
                            int temp = NativeMethods.SHAppBarMessage(4, ref abd);
                            if (temp == 1)
                            {
                                NativeMethods.NCCALCSIZE_PARAMS ncParams = (NativeMethods.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.NCCALCSIZE_PARAMS));
                                ncParams.rect0.Bottom -= 9;
                                Marshal.StructureToPtr(ncParams, lParam, false);
                            }
                        }

                        handled = true;
                        return new IntPtr(NativeMethods.WVR_REDRAW);
                    }
                case NativeMethods.WM_NCHITTEST:
                    {
                        return DoHitTest(msg, wParam, lParam, out handled);
                    }
                case NativeMethods.WM_NCRBUTTONUP:
                    {
                        // Emulate the system behavior of clicking the right mouse button over the caption area
                        // to bring up the system menu.
                        if (NativeMethods.HTCAPTION == wParam.ToInt32())
                        {
                            ShowSystemMenuPhysicalCoordinates(new Point(NativeMethods.LowWord(lParam), NativeMethods.HiWord(lParam)));
                        }
                        handled = false;
                        return IntPtr.Zero;
                    }
                case NativeMethods.WM_SIZE:
                    {
                        const int SIZE_MAXIMIZED = 2;

                        // Force when maximized.
                        // We can tell what's happening right now, but the Window doesn't yet know it's
                        // maximized.  Not forcing this update will eventually cause the
                        // default caption to be drawn.
                        WindowState? state = null;
                        if (wParam.ToInt32() == SIZE_MAXIMIZED)
                        {
                            state = WindowState.Maximized;
                        }
                        UpdateSystemMenu(state);

                        // Still let the default WndProc handle this.
                        handled = false;
                        return IntPtr.Zero;
                    }
                case NativeMethods.WM_WINDOWPOSCHANGED:
                    {
                        if (!IsDwmEnabled)
                        {
                            var wp = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS));
                            //ModifyStyle(NativeMethods.WS_VISIBLE, 0);
                            SetRoundingRegion(wp);
                            //ModifyStyle(0, NativeMethods.WS_VISIBLE);
                        }

                        // Still want to pass this to DefWndProc
                        handled = false;
                        return IntPtr.Zero;
                    }
                case NativeMethods.WM_DWMCOMPOSITIONCHANGED:
                    {
                        IsDwmEnabled = NativeMethods.IsDwmEnabled();

                        UpdateFrameState(false);

                        handled = false;
                        return IntPtr.Zero;
                    }
            }

            if (FrameworkHelper.PresentationFrameworkVersion < new Version("4.0"))
            {
                switch (msg)
                {
                    case NativeMethods.WM_SETTINGCHANGE:
                        {
                            FixFrameworkIssues();

                            handled = false;
                            return IntPtr.Zero;
                        }
                    case NativeMethods.WM_ENTERSIZEMOVE:
                        {
                            isUserResizing = true;

                            if (WindowState != WindowState.Maximized)
                            {
                                // Check for the docked window case.  The window can still be restored when it's in this position so 
                                // try to account for that and not update the start position.
                                if (!IsWindowDocked)
                                {
                                    windowPosAtStartOfUserMove = new Point(Left, Top);
                                }
                                // Realistically we also don't want to update the start position when moving from one docked state to another (or to and from maximized),
                                // but it's tricky to detect and this is already a workaround for a bug that's fixed in newer versions of the framework.
                                // Not going to try to handle all cases.
                            }

                            handled = false;
                            return IntPtr.Zero;
                        }
                    case NativeMethods.WM_EXITSIZEMOVE:
                        {
                            isUserResizing = false;

                            // On Win7 the user can change the Window's state by dragging the window to the top of the monitor.
                            // If they did that, then we need to try to update the restore bounds or else WPF will put the window at the maximized location (e.g. (-8,-8)).
                            if (WindowState == WindowState.Maximized)
                            {
                                Top = windowPosAtStartOfUserMove.Y;
                                Left = windowPosAtStartOfUserMove.X;
                            }

                            handled = false;
                            return IntPtr.Zero;
                        }
                    case NativeMethods.WM_MOVE:
                        {
                            if (isUserResizing)
                            {
                                hasUserMovedWindow = true;
                            }

                            handled = false;
                            return IntPtr.Zero;
                        }
                }
            }

            return IntPtr.Zero;
        }
예제 #2
0
        private void FixClientRect(IntPtr lParam)
        {
            if (WindowState == WindowState.Maximized)
            {
                var abd = new NativeMethods.APPBARDATA();
                var temp = NativeMethods.SHAppBarMessage(4, ref abd);
                if (temp == 1)
                {
                    var ncParams = (NativeMethods.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.NCCALCSIZE_PARAMS));
                    ncParams.rect0.Bottom -= 9;
                    Marshal.StructureToPtr(ncParams, lParam, false);
                }
            }

            // below code should fix issue 18229, but causes the minimize, restore and close button to be unreachable when window is maximized
            ////// Fixes the client rect to render edge to edge on one display if maximized
            ////// Issue fixed with this method:
            ////// http://fluent.codeplex.com/workitem/18229
            ////// "When maximized, client area goes 8px offscreen, killing perf on multimonitor"
            ////if (this.WindowState == WindowState.Maximized)
            ////{
            ////    var ncParams = (NativeMethods.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(lParam, typeof(NativeMethods.NCCALCSIZE_PARAMS));

            ////    ncParams.rect0.Left += 8;
            ////    ncParams.rect0.Top += 8;
            ////    ncParams.rect0.Right -= 8;
            ////    ncParams.rect0.Bottom -= 8;

            ////    Marshal.StructureToPtr(ncParams, lParam, false);

            ////    if (VisualTreeHelper.GetChildrenCount(this) != 0)
            ////    {
            ////        var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(this, 0);
            ////        rootElement.Margin = new Thickness(-8);
            ////    }
            ////}
            ////else
            ////{
            ////    if (VisualTreeHelper.GetChildrenCount(this) != 0)
            ////    {
            ////        var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(this, 0);
            ////        rootElement.Margin = new Thickness(0);
            ////    }
            ////}
        }