make a WPF Popup not screen bound

亡梦爱人 提交于 2019-12-01 16:53:49

Just use interop to move your popups (drag them)

Here is code for Thumb which will track the drag process

region 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

The HostPopup class is subclass of Popup, and it hase the following methods using interop to move the window:

    [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;
        }
    }

If you want the popup to behave more like a Window, I'd just make a Window instead of a Popup.

Having a popup that doesn't position itself like a standard popup, and allows you to drag it around the screen, just seems like a recipe for low usability and confusion.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!