mirror of
https://github.com/LorenzCK/OnTopReplica.git
synced 2024-05-20 20:33:06 +12:00
Fixed client size <-> window size conversion to use official AdjustWindowRectEx Win32 API instead of handrolled difference computation.
This commit is contained in:
parent
e66be3db45
commit
b02aa1a12b
|
@ -116,7 +116,8 @@ namespace OnTopReplica {
|
||||||
MinimumSize.Width);
|
MinimumSize.Width);
|
||||||
|
|
||||||
//Determine new height while keeping aspect ratio
|
//Determine new height while keeping aspect ratio
|
||||||
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientSizeConversionWidth) / AspectRatio) + ExtraPadding.Vertical + clientSizeConversionHeight;
|
var clientConversionDifference = ClientWindowDifference;
|
||||||
|
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientConversionDifference.Width) / AspectRatio) + ExtraPadding.Vertical + clientConversionDifference.Height;
|
||||||
|
|
||||||
//Apply and move form to recenter
|
//Apply and move form to recenter
|
||||||
Size = new Size(newWidth, newHeight);
|
Size = new Size(newWidth, newHeight);
|
||||||
|
@ -161,11 +162,13 @@ namespace OnTopReplica {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void WndProc(ref Message m) {
|
protected override void WndProc(ref Message m) {
|
||||||
if (KeepAspectRatio && m.Msg == WM.SIZING) {
|
if (KeepAspectRatio && m.Msg == WM.SIZING) {
|
||||||
|
var clientSizeConversion = ClientWindowDifference;
|
||||||
|
|
||||||
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
|
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
|
||||||
int res = m.WParam.ToInt32();
|
int res = m.WParam.ToInt32();
|
||||||
|
|
||||||
int width = (rc.Right - rc.Left) - clientSizeConversionWidth - ExtraPadding.Horizontal;
|
int width = (rc.Right - rc.Left) - clientSizeConversion.Width - ExtraPadding.Horizontal;
|
||||||
int height = (rc.Bottom - rc.Top) - clientSizeConversionHeight - ExtraPadding.Vertical;
|
int height = (rc.Bottom - rc.Top) - clientSizeConversion.Height - ExtraPadding.Vertical;
|
||||||
|
|
||||||
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
|
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
|
||||||
//Left or right resize, adjust top and bottom
|
//Left or right resize, adjust top and bottom
|
||||||
|
@ -173,7 +176,7 @@ namespace OnTopReplica {
|
||||||
int diffHeight = height - targetHeight;
|
int diffHeight = height - targetHeight;
|
||||||
|
|
||||||
rc.Top += (int)(diffHeight / 2.0);
|
rc.Top += (int)(diffHeight / 2.0);
|
||||||
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversionHeight;
|
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
|
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
|
||||||
//Up or down resize, adjust left and right
|
//Up or down resize, adjust left and right
|
||||||
|
@ -181,15 +184,15 @@ namespace OnTopReplica {
|
||||||
int diffWidth = width - targetWidth;
|
int diffWidth = width - targetWidth;
|
||||||
|
|
||||||
rc.Left += (int)(diffWidth / 2.0);
|
rc.Left += (int)(diffWidth / 2.0);
|
||||||
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversionWidth;
|
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversion.Width;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
|
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
|
||||||
//Lower corner resize, adjust bottom
|
//Lower corner resize, adjust bottom
|
||||||
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversionHeight;
|
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
|
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
|
||||||
//Upper corner resize, adjust top
|
//Upper corner resize, adjust top
|
||||||
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversionHeight;
|
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Marshal.StructureToPtr(rc, m.LParam, false);
|
Marshal.StructureToPtr(rc, m.LParam, false);
|
||||||
|
@ -202,15 +205,15 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
#region ClientSize/Size conversion helpers
|
#region ClientSize/Size conversion helpers
|
||||||
|
|
||||||
int clientSizeConversionWidth, clientSizeConversionHeight;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a client size measurement to a window size measurement.
|
/// Converts a client size measurement to a window size measurement.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clientSize">Size of the window's client area.</param>
|
/// <param name="clientSize">Size of the window's client area.</param>
|
||||||
/// <returns>Size of the whole window.</returns>
|
/// <returns>Size of the whole window.</returns>
|
||||||
public Size FromClientSizeToSize(Size clientSize) {
|
public Size FromClientSizeToSize(Size clientSize) {
|
||||||
return new Size(clientSize.Width + clientSizeConversionWidth, clientSize.Height + clientSizeConversionHeight);
|
var difference = ClientWindowDifference;
|
||||||
|
|
||||||
|
return new Size(clientSize.Width + difference.Width, clientSize.Height + difference.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -219,18 +222,24 @@ namespace OnTopReplica {
|
||||||
/// <param name="size">Size of the whole window.</param>
|
/// <param name="size">Size of the whole window.</param>
|
||||||
/// <returns>Size of the window's client area.</returns>
|
/// <returns>Size of the window's client area.</returns>
|
||||||
public Size FromSizeToClientSize(Size size) {
|
public Size FromSizeToClientSize(Size size) {
|
||||||
return new Size(size.Width - clientSizeConversionWidth, size.Height - clientSizeConversionHeight);
|
var difference = ClientWindowDifference;
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnShown(EventArgs e) {
|
return new Size(size.Width - difference.Width, size.Height - difference.Height);
|
||||||
base.OnShown(e);
|
|
||||||
|
|
||||||
clientSizeConversionWidth = Size.Width - ClientSize.Width;
|
|
||||||
clientSizeConversionHeight = Size.Height - ClientSize.Height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the difference in pixels between a client size value and a window size value (depending on window decoration).
|
||||||
|
/// </summary>
|
||||||
|
protected Size ClientWindowDifference {
|
||||||
|
get {
|
||||||
|
long style = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.Style).ToInt64();
|
||||||
|
long exStyle = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
|
||||||
|
return WindowMethods.ConvertClientToWindowRect(new NRectangle(0, 0, 0, 0), style, exStyle).Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
namespace OnTopReplica.Native {
|
namespace OnTopReplica.Native {
|
||||||
|
|
||||||
/// <summary>A native Rectangle Structure.</summary>
|
/// <summary>A native Rectangle Structure.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
struct NRectangle {
|
struct NRectangle {
|
||||||
|
@ -52,4 +54,13 @@ namespace OnTopReplica.Native {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class NRectangleExtensions {
|
||||||
|
|
||||||
|
public static NRectangle ToNativeRectangle(this Size size) {
|
||||||
|
return new NRectangle(0, 0, size.Width, size.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,6 @@ namespace OnTopReplica.Native {
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MaxClassLength = 255;
|
|
||||||
|
|
||||||
public static string GetWindowClass(IntPtr hwnd) {
|
|
||||||
var sb = new StringBuilder(MaxClassLength + 1);
|
|
||||||
RealGetWindowClass(hwnd, sb, MaxClassLength);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
||||||
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder lpString, uint maxCount);
|
|
||||||
|
|
||||||
public enum WindowLong {
|
public enum WindowLong {
|
||||||
WndProc = (-4),
|
WndProc = (-4),
|
||||||
HInstance = (-6),
|
HInstance = (-6),
|
||||||
|
@ -77,11 +66,6 @@ namespace OnTopReplica.Native {
|
||||||
Id = (-12)
|
Id = (-12)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ClassLong {
|
|
||||||
Icon = -14,
|
|
||||||
IconSmall = -34
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum WindowStyles : long {
|
public enum WindowStyles : long {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -131,7 +115,23 @@ namespace OnTopReplica.Native {
|
||||||
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
|
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
|
||||||
static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLong nIndex, IntPtr dwNewLong);
|
static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLong nIndex, IntPtr dwNewLong);
|
||||||
|
|
||||||
#region Class styles
|
#region Window class
|
||||||
|
|
||||||
|
const int MaxClassLength = 255;
|
||||||
|
|
||||||
|
public static string GetWindowClass(IntPtr hwnd) {
|
||||||
|
var sb = new StringBuilder(MaxClassLength + 1);
|
||||||
|
RealGetWindowClass(hwnd, sb, MaxClassLength);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder lpString, uint maxCount);
|
||||||
|
|
||||||
|
public enum ClassLong {
|
||||||
|
Icon = -14,
|
||||||
|
IconSmall = -34
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("user32.dll", EntryPoint = "GetClassLongPtrW")]
|
[DllImport("user32.dll", EntryPoint = "GetClassLongPtrW")]
|
||||||
static extern IntPtr GetClassLong64(IntPtr hWnd, int nIndex);
|
static extern IntPtr GetClassLong64(IntPtr hWnd, int nIndex);
|
||||||
|
@ -153,5 +153,28 @@ namespace OnTopReplica.Native {
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr GetMenu(IntPtr hwnd);
|
public static extern IntPtr GetMenu(IntPtr hwnd);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts client size rectangle to window rectangle, according to window styles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientRectangle">Client area bounding box.</param>
|
||||||
|
/// <param name="windowStyle">Style of window to compute.</param>
|
||||||
|
/// <param name="extendedWindowStyle">Extended style of window to compute.</param>
|
||||||
|
public static NRectangle ConvertClientToWindowRect(NRectangle clientRectangle, long windowStyle, long extendedWindowStyle) {
|
||||||
|
NRectangle tmp = clientRectangle;
|
||||||
|
if (AdjustWindowRectEx(ref tmp, windowStyle, false, extendedWindowStyle)) {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#if DEBUG
|
||||||
|
throw new InvalidOperationException("Failed to convert client rectangle to window rectangle");
|
||||||
|
#else
|
||||||
|
return clientRectangle;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool AdjustWindowRectEx(ref NRectangle clientToWindowRect, long windowStyle, bool hasMenu, long extendedWindowStyle);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,29 +33,6 @@ namespace OnTopReplica.Platforms {
|
||||||
form.Show();
|
form.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public override void OnFormStateChange(MainForm form) {
|
|
||||||
//SetWindowStyle(form);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used to alter the window style. Not used anymore.
|
|
||||||
/// </summary>
|
|
||||||
private void SetWindowStyle(MainForm form) {
|
|
||||||
if (!form.FullscreenManager.IsFullscreen) {
|
|
||||||
//This hides the app from ALT+TAB
|
|
||||||
//Note that when minimized, it will be shown as an (ugly) minimized tool window
|
|
||||||
//thus we do not minimize, but set to transparent when hiding
|
|
||||||
long exStyle = WindowMethods.GetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
|
|
||||||
|
|
||||||
exStyle |= (long)(WindowMethods.WindowExStyles.ToolWindow);
|
|
||||||
//exStyle &= ~(long)(WindowMethods.WindowExStyles.AppWindow);
|
|
||||||
|
|
||||||
WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle, new IntPtr(exStyle));
|
|
||||||
|
|
||||||
//WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.HwndParent, WindowManagerMethods.GetDesktopWindow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue