Files
Proftaak-RH-B4/Hashing/WPFStuff/MagicCode/WindowResizer.cs
shinichi 3acdc942bc move files and copy code
from stackoverflow :P
2020-10-19 14:53:47 +02:00

212 lines
6.4 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace Util.MagicCode
{
/// <summary>
/// Fixes the issue with Windows of Style <see cref="WindowStyle.None"/> covering the taskbar
/// </summary>
public class WindowResizer
{
#region Private Members
/// <summary>
/// The window to handle the resizing for
/// </summary>
private Window mWindow;
#endregion
#region Dll Imports
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("user32.dll")]
static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr MonitorFromPoint(POINT pt, MonitorOptions dwFlags);
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
/// <param name="window">The window to monitor and correctly maximize</param>
/// <param name="adjustSize">The callback for the host to adjust the maximum available size if needed</param>
public WindowResizer(Window window)
{
mWindow = window;
// Listen out for source initialized to setup
mWindow.SourceInitialized += Window_SourceInitialized;
}
#endregion
#region Initialize
/// <summary>
/// Initialize and hook into the windows message pump
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_SourceInitialized(object sender, System.EventArgs e)
{
// Get the handle of this window
var handle = (new WindowInteropHelper(mWindow)).Handle;
var handleSource = HwndSource.FromHwnd(handle);
// If not found, end
if (handleSource == null)
return;
// Hook into it's Windows messages
handleSource.AddHook(WindowProc);
}
#endregion
#region Windows Proc
/// <summary>
/// Listens out for all windows messages for this window
/// </summary>
/// <param name="hwnd"></param>
/// <param name="msg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <param name="handled"></param>
/// <returns></returns>
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
// Handle the GetMinMaxInfo of the Window
case 0x0024:/* WM_GETMINMAXINFO */
WmGetMinMaxInfo(hwnd, lParam);
handled = true;
break;
}
return (IntPtr)0;
}
#endregion
/// <summary>
/// Get the min/max window size for this window
/// Correctly accounting for the taskbar size and position
/// </summary>
/// <param name="hwnd"></param>
/// <param name="lParam"></param>
private void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{
POINT lMousePosition;
GetCursorPos(out lMousePosition);
IntPtr lPrimaryScreen = MonitorFromPoint(new POINT(0, 0), MonitorOptions.MONITOR_DEFAULTTOPRIMARY);
MONITORINFO lPrimaryScreenInfo = new MONITORINFO();
if (GetMonitorInfo(lPrimaryScreen, lPrimaryScreenInfo) == false)
{
return;
}
IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST);
MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
if (lPrimaryScreen.Equals(lCurrentScreen) == true)
{
lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcWork.Left;
lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcWork.Top;
lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcWork.Right - lPrimaryScreenInfo.rcWork.Left;
lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcWork.Bottom - lPrimaryScreenInfo.rcWork.Top;
}
else
{
lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcMonitor.Left;
lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcMonitor.Top;
lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcMonitor.Right - lPrimaryScreenInfo.rcMonitor.Left;
lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcMonitor.Bottom - lPrimaryScreenInfo.rcMonitor.Top;
}
// Now we have the max size, allow the host to tweak as needed
Marshal.StructureToPtr(lMmi, lParam, true);
}
}
#region Dll Helper Structures
enum MonitorOptions : uint
{
MONITOR_DEFAULTTONULL = 0x00000000,
MONITOR_DEFAULTTOPRIMARY = 0x00000001,
MONITOR_DEFAULTTONEAREST = 0x00000002
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
public Rectangle rcMonitor = new Rectangle();
public Rectangle rcWork = new Rectangle();
public int dwFlags = 0;
}
[StructLayout(LayoutKind.Sequential)]
public struct Rectangle
{
public int Left, Top, Right, Bottom;
public Rectangle(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
};
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
/// <summary>
/// x coordinate of point.
/// </summary>
public int X;
/// <summary>
/// y coordinate of point.
/// </summary>
public int Y;
/// <summary>
/// Construct a point of coordinates (x,y).
/// </summary>
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
#endregion
}