Skip to content

Commit

Permalink
Improving Dual Monitor Support - repositioning floating Tool Window a…
Browse files Browse the repository at this point in the history
…nd/or Documents when they get out of bound of the current view.
  • Loading branch information
Dirkster99 committed Apr 26, 2019
1 parent 5f40974 commit fbf3b7e
Showing 1 changed file with 26 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace Xceed.Wpf.AvalonDock.Layout
{
using System;
using System.Runtime.InteropServices;
using System.Windows;

Expand All @@ -12,7 +11,6 @@
public static class ILayoutElementForFloatingWindowExtension
{
// RECT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
Expand All @@ -30,23 +28,6 @@ public RECT(int left, int top, int right, int bottom)
}
}

[StructLayout(LayoutKind.Sequential)]
public struct MONITORINFO
{
public int cbSize;
internal RECT rcMonitor;
internal RECT rcWork;
private uint dwFlags;
}

[DllImport("user32.dll")]
private static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags);

[DllImport("user32.dll")]
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

private const uint MONITOR_DEFAULTTONEAREST = 0x00000002;

internal static void KeepInsideNearestMonitor(this ILayoutElementForFloatingWindow paneInsideFloatingWindow)
{
RECT normalPosition = new RECT();
Expand All @@ -73,23 +54,31 @@ internal static void KeepInsideNearestMonitor(this ILayoutElementForFloatingWind

return;
}
else
{
RECT primaryscreen = new RECT(0, 0, (int)SystemParameters.VirtualScreenWidth, (int)SystemParameters.VirtualScreenHeight);

IntPtr closestMonitorPtr = MonitorFromRect(ref normalPosition, MONITOR_DEFAULTTONEAREST);
MONITORINFO closestMonitorInfo = new MONITORINFO();
closestMonitorInfo.cbSize = Marshal.SizeOf(typeof(MONITORINFO));
bool getInfoSucceeded = GetMonitorInfo(closestMonitorPtr, ref closestMonitorInfo);
if (!RectanglesIntersect(normalPosition, primaryscreen))
{
normalPosition = PlaceOnScreen(primaryscreen, normalPosition);

if (getInfoSucceeded && !RectanglesIntersect(normalPosition, closestMonitorInfo.rcMonitor))
{
normalPosition = PlaceOnScreen(closestMonitorInfo.rcMonitor, normalPosition);
paneInsideFloatingWindow.FloatingLeft = normalPosition.Left;
paneInsideFloatingWindow.FloatingTop = normalPosition.Top;
paneInsideFloatingWindow.FloatingHeight = normalPosition.Bottom - normalPosition.Top;
paneInsideFloatingWindow.FloatingWidth = normalPosition.Right - normalPosition.Left;
}

paneInsideFloatingWindow.FloatingLeft = normalPosition.Left;
paneInsideFloatingWindow.FloatingTop = normalPosition.Top;
paneInsideFloatingWindow.FloatingHeight = normalPosition.Bottom - normalPosition.Top;
paneInsideFloatingWindow.FloatingWidth = normalPosition.Right - normalPosition.Left;
return;
}
}

/// <summary>
/// Determine whether <paramref name="a"/> and <paramref name="b"/>
/// have an intersection or not.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
private static bool RectanglesIntersect(RECT a, RECT b)
{
if (a.Left > b.Right || a.Right < b.Left)
Expand All @@ -105,6 +94,13 @@ private static bool RectanglesIntersect(RECT a, RECT b)
return true;
}

/// <summary>
/// Determine the place where <paramref name="windowRect"/> should be placed
/// inside the <paramref name="monitorRect"/>.
/// </summary>
/// <param name="monitorRect"></param>
/// <param name="windowRect"></param>
/// <returns></returns>
private static RECT PlaceOnScreen(RECT monitorRect, RECT windowRect)
{
int monitorWidth = monitorRect.Right - monitorRect.Left;
Expand Down

0 comments on commit fbf3b7e

Please sign in to comment.