示例#1
0
        public virtual IntPtr WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch ((WM)msg)
            {
            case WM.WINDOWPOSCHANGING:
            {
                WINDOWPOS windowPos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));

                if (Helpers.WindowChanged(windowPos.flags))
                {
                    // Get the monitor area that intersect the most with the specified rectangle
                    MonitorArea monitorArea = Helpers.GetMonitorArea(hWnd, new RECT
                        {
                            left   = windowPos.x,
                            top    = windowPos.y,
                            right  = windowPos.x + windowPos.cx,
                            bottom = windowPos.y + windowPos.cy
                        });

                    UpdateDisplayDevice(monitorArea.Device);
                }

                break;
            }
            }

            return(IntPtr.Zero);
        }
示例#2
0
        /// <summary>
        /// Activate or deactivate left/right resize handles given
        /// the current window position and size
        /// </summary>
        /// <remarks>
        /// Applies to snapped window only
        /// The maximum window size is limited by the (multi) screen size
        /// </remarks>
        /// <param name="window"></param>
        /// <param name="monitorArea"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        private static void UpdateResizeBorder(Window window, MonitorArea monitorArea, double left, double right)
        {
            double borderWidth = GetResizeBorderWidth(window as CustomChrome);

            double virtualLeft  = SystemParameters.VirtualScreenLeft;
            double virtualRight = SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth;

            double leftBorder  = left <= virtualLeft + monitorArea.Offset.x ? 0 : borderWidth;
            double rightBorder = right >= virtualRight ? 0 : borderWidth;

            EnableResizeBorder(window, leftBorder, 0, rightBorder, 0);
        }
示例#3
0
        private static IntPtr WindowHookProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            CustomChrome window = GetWindow(hWnd) as CustomChrome;

            switch (msg)
            {
            // Toggle the DropShadowEffect when window is snapped or maximized
            case WM_SIZE:
            {
                int resizing = (int)wParam;

                if (resizing == SIZE_RESTORED)
                {
                    MonitorArea monitorArea = GetMonitorArea(hWnd);

                    if (monitorArea != null)
                    {
                        // LOWORD
                        int width = ((int)lParam & 0x0000ffff);

                        // HIWORD
                        int height = (int)((int)lParam & 0xffff0000) >> 16;

                        // Detect if window was snapped to screen side of current monitor
                        // or if spanning width on multiple monitors (to avoid unsnapping)
                        if (height == monitorArea.Work.Height ||
                            width >= SystemParameters.VirtualScreenWidth)
                        {
                            window.IsSnapped = true;

                            UpdateResizeBorder(window, monitorArea, window.Left, window.Left + width);
                        }
                        else
                        {
                            window.IsSnapped = false;

                            ShowDropShadow(window);

                            EnableResizeBorder(window);
                        }
                    }
                }
                else if (resizing == SIZE_MAXIMIZED)
                {
                    // Required when maximized from dragging window
                    DisableResizeBorder(window);
                }
            }
            break;


            // To handle proper resizing of the custom window
            case WM_GETMINMAXINFO:
            {
                MonitorArea monitorArea = GetMonitorArea(hWnd);

                if (monitorArea != null)
                {
                    MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));

                    mmi.ptMaxPosition.x = monitorArea.Offset.x;
                    mmi.ptMaxPosition.y = monitorArea.Offset.y;
                    mmi.ptMaxSize.x     = monitorArea.Work.Width;
                    mmi.ptMaxSize.y     = monitorArea.Work.Height;

                    // To support minimum window size
                    mmi.ptMinTrackSize.x = (int)window.MinWidth;
                    mmi.ptMinTrackSize.y = (int)window.MinHeight;

                    Marshal.StructureToPtr(mmi, lParam, true);
                    handled = true;
                }
            }
            break;

            // To activate/deactivate border resize handles from window position
            case WM_WINDOWPOSCHANGED:
            {
                WINDOWPOS windowPos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));

                // When window is snapped and position changes
                if ((windowPos.flags & SWP_NOMOVE) != SWP_NOMOVE)
                {
                    if (window.IsSnapped)
                    {
                        MonitorArea monitorArea = GetMonitorArea(hWnd);

                        if (monitorArea != null)
                        {
                            UpdateResizeBorder(window, monitorArea, windowPos.x, windowPos.x + windowPos.cx);
                        }
                    }
                }
            }
            break;
            }

            return(IntPtr.Zero);
        }
示例#4
0
        /// <summary>
        /// Support for custom window drag move and
        /// restore from maximized window state
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnDragControlMouseMove(object sender, MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (e.LeftButton == MouseButtonState.Pressed && !this.IsMaximizing && !this.SystemMenuShown)
            {
                if (this.WindowState == WindowState.Maximized)
                {
                    // When passing null to GetPosition, we get the mouse position
                    // relative to the containing window (on current screen)
                    // Remarks: Mouse.GetPosition(this), e.GetPosition(null);
                    // and e.MouseDevice.GetPosition(null) seems to get the
                    // same coordinates

                    // Local (within window) and global (screen) coordinates
                    Point local  = e.GetPosition(null);
                    Point global = this.PointToScreen(local);

                    IntPtr      hwnd        = new WindowInteropHelper(this).EnsureHandle();
                    MonitorArea monitorArea = GetMonitorArea(hwnd);

                    // Coordinates relative to the drag control
                    Point position = e.GetPosition(dragControl);
                    Point relative = this.PointToScreen(position);

                    double dragAreaWidth = dragControl.ActualWidth;

                    double leftMargin  = global.X - relative.X;
                    double rightMargin = monitorArea.Work.Width - dragAreaWidth - leftMargin;

                    double restoreDragAreaWidth = this.RestoreBounds.Width - leftMargin - rightMargin;

                    // New X coordinate relative to restored window
                    double x = Math.Round(restoreDragAreaWidth * local.X / dragAreaWidth);

                    // Compensate for the resize border (uniform) width
                    double resizeBorderWidth = GetResizeBorderWidth(this);

                    double left  = monitorArea.Work.Left - resizeBorderWidth;
                    double right = monitorArea.Work.Left + monitorArea.Work.Width + resizeBorderWidth;

                    double leftBound  = left + this.RestoreBounds.Width - rightMargin;
                    double rightBound = right - this.RestoreBounds.Width + leftMargin;

                    Point offset = new Point(0, resizeBorderWidth);

                    // The restore bounds width is within the left bound region
                    if (global.X < leftBound)
                    {
                        // Align restored window to left of screen
                        this.Left = left;

                        offset.X = resizeBorderWidth;
                    }
                    // The restore bounds width is within the right bound region
                    else if (global.X > rightBound)
                    {
                        // Align restored window to right of screen
                        this.Left = right - this.RestoreBounds.Width;

                        offset.X = -resizeBorderWidth;
                    }
                    // The restore bounds width is shorter than the left / right bound region width
                    else if ((global.X > leftBound) && (global.X < rightBound))
                    {
                        this.Left = global.X - x - leftMargin - resizeBorderWidth;
                    }

                    this.Top = global.Y - local.Y;

                    // Set and remove the horizontal offset to avoid the restored window's border
                    // to momentarily get outside the current monitor space creating a short flicker.

                    this.Left += offset.X;

                    this.WindowState = WindowState.Normal;

                    this.Left -= offset.X;
                    this.Top  -= offset.Y;
                }

                this.IsDragging = true;

                HideDropShadow(this);

                this.DragMove();

                this.IsDragging = false;

                ShowDropShadow(this);
            }

            // Reset special condition guard flags
            this.IsMaximizing    = false;
            this.SystemMenuShown = false;

            e.Handled = true;
        }