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 behavio
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.
Just use interop to move your popups (drag them)
Here is code for Thumb which will track the drag process
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;
}
}