7

The default behavior of a Popup is if it is placed where it would extend beyond the edge of the screen, the Popup will reposition itself. Is there a way to turn this behavior off?

I have a Popup that the user can drag around the screen. However, when it gets to the edges it gets stuck. It gets stuck on the edge and stays there until the mouse is dragged far from the edge. Also, I have two monitors and when the Popup is dragged to the edge the two monitors share I get flickering. The Popup flickers between the two monitors.

Dan Vogel
  • 3,858
  • 7
  • 41
  • 57

2 Answers2

3

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;
        }
    }
Community
  • 1
  • 1
  • 1
    Can anyone explain in further detail how to implement this? How do I get access to the HostPopup subclass? Where does the GetWindowRect() method reside? – Saggio Jul 30 '12 at 17:28
2

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    Unfortunatly, there is functionality of a Popup that a Window doesn't have and is more important to me than freedom of motion. I guess I will have to restrict the movement so there is no chance of going beyond the screen bounds and thus no repositioning and no flickering. Thanks for the info. – Dan Vogel Nov 03 '09 at 01:17
  • 1
    Agreed. I want the popup to follow the window and prevent input into a WinForm control hosted in the WPF app (essentially a busy indicator) and if the window is dragged off the screen then the popup wont follow the window past the screen bounds. – Stephen Price Jun 23 '10 at 03:18
  • Another data point on this. Sometimes Popup is preferable to Window for dragging content since opening a Window on Windows 10 with Tablet Mode will trigger Win10's screen split action and disrupt the drag. (Context: I'm using Popup temporarily as a drag feedback window, not permenant part of the UI) – jschroedl Jul 12 '17 at 15:20