使WPF弹出窗口不受屏幕限制

时间:2009-10-30 23:27:13

标签: c# wpf popup

Popup的默认行为是,如果它被放置在超出屏幕边缘的位置,Popup将重新定位自身。有没有办法解决这个问题?

我有一个Popup,用户可以在屏幕上拖动。但是,当它到达边缘时会卡住。它会卡在边缘并停留在那里,直到鼠标被拖离边缘。此外,我有两个监视器,当弹出窗口被拖到边缘时,两个监视器共享我闪烁。弹出窗口在两个监视器之间闪烁。

2 个答案:

答案 0 :(得分:3)

只需使用互操作来移动弹出窗口(拖动它们)

这是Thumb的代码,它将跟踪拖动过程

区域Thumb

    private Thumb mThumb = null;
    public Thumb Thumb
    {
        get { return mThumb; }
        set
        {
            if (mThumb != value)
            {
                if (mThumb != null)
                {
                    DetachThumb();
                }
                mThumb = value;
                if (mThumb != null)
                {
                    AttachThumb();
                }
            }
        }
    }

    private void AttachThumb()
    {
        Thumb.DragStarted += Thumb_DragStarted;
        Thumb.DragDelta += Thumb_DragDelta;
        Thumb.DragCompleted += Thumb_DragCompleted;
    }

    private void DetachThumb()
    {
        Thumb.DragStarted -= Thumb_DragStarted;
        Thumb.DragDelta -= Thumb_DragDelta;
        Thumb.DragCompleted -= Thumb_DragCompleted;
    }

    private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
    {
        mIsThumbDragging = true;
        mPreviousDiffX = 0;
        mPreviousDiffY = 0;
    }

    private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        if (mIsMoving)
        {
            return;
        }
        mIsMoving = true;
        try
        {
            if (mIsThumbDragging)
            {
                var doubleDetaX = e.HorizontalChange + mPreviousDiffX;
                var doubleDetaY = e.VerticalChange + mPreviousDiffY;

                var deltaX = (int)doubleDetaX;
                var deltaY = (int)doubleDetaY;

                mPreviousDiffX = (double)deltaX - doubleDetaX;
                mPreviousDiffY = (double)deltaY - doubleDetaY;

                HostPopup.Move(deltaX, deltaY);
            }
        }
        finally
        {
            mIsMoving = false;
        }
    }

    private void Thumb_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        mIsThumbDragging = false;
    }

    #endregion

HostPopup类是Popup的子类,它使用interop来移动窗口时使用以下方法:

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

     [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

    internal void Move(int deltaX, int deltaY)
    {
        if (mIsMoving)
        {
            return;
        }
        mIsMoving = true;
        try
        {
            if (Child == null)
                return;

            var hwndSource = (PresentationSource.FromVisual(Child)) as HwndSource;

            if (hwndSource == null)
                return;
            var hwnd = hwndSource.Handle;

            RECT rect;

            if (!GetWindowRect(hwnd, out rect))
                return;

            MoveWindow(hwnd, rect.Left + deltaX, rect.Top + deltaY, (int)Width, (int)Height, true);
        }
        finally
        {
            mIsMoving = false;
        }
    }

答案 1 :(得分:2)

如果你希望弹出窗口的行为更像Window,我只需要创建一个Window而不是Popup。

弹出窗口不会像标准弹出窗口那样定位,并允许您将其拖动到屏幕上,这似乎是低可用性和混乱的一种方法。