|
|
|
@ -1,5 +1,4 @@ |
|
|
|
using System; |
|
|
|
using System.Diagnostics; |
|
|
|
using Avalonia.Controls; |
|
|
|
using Avalonia.Input; |
|
|
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
|
|
|
@ -11,70 +10,75 @@ namespace Avalonia.Win32 |
|
|
|
public partial class WindowImpl |
|
|
|
{ |
|
|
|
// Hit test the frame for resizing and moving.
|
|
|
|
HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam) |
|
|
|
private HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam) |
|
|
|
{ |
|
|
|
// Get the point coordinates for the hit test.
|
|
|
|
// Get the point coordinates for the hit test (screen space).
|
|
|
|
var ptMouse = PointFromLParam(lParam); |
|
|
|
|
|
|
|
// Get the window rectangle.
|
|
|
|
// Get the window rectangle.
|
|
|
|
GetWindowRect(hWnd, out var rcWindow); |
|
|
|
|
|
|
|
// Get the frame rectangle, adjusted for the style without a caption.
|
|
|
|
RECT rcFrame = new RECT(); |
|
|
|
var rcFrame = new RECT(); |
|
|
|
AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0); |
|
|
|
|
|
|
|
RECT border_thickness = new RECT(); |
|
|
|
var borderThickness = new RECT(); |
|
|
|
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME)) |
|
|
|
{ |
|
|
|
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0); |
|
|
|
border_thickness.left *= -1; |
|
|
|
border_thickness.top *= -1; |
|
|
|
AdjustWindowRectEx(ref borderThickness, (uint)(GetStyle()), false, 0); |
|
|
|
borderThickness.left *= -1; |
|
|
|
borderThickness.top *= -1; |
|
|
|
} |
|
|
|
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER)) |
|
|
|
{ |
|
|
|
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 }; |
|
|
|
borderThickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 }; |
|
|
|
} |
|
|
|
|
|
|
|
if (_extendTitleBarHint >= 0) |
|
|
|
{ |
|
|
|
border_thickness.top = (int)(_extendedMargins.Top * RenderScaling); |
|
|
|
borderThickness.top = (int)(_extendedMargins.Top * RenderScaling); |
|
|
|
} |
|
|
|
|
|
|
|
// Determine if the hit test is for resizing. Default middle (1,1).
|
|
|
|
ushort uRow = 1; |
|
|
|
ushort uCol = 1; |
|
|
|
bool fOnResizeBorder = false; |
|
|
|
bool onResizeBorder = false; |
|
|
|
|
|
|
|
// Determine if the point is at the top or bottom of the window.
|
|
|
|
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + border_thickness.top) |
|
|
|
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + borderThickness.top) |
|
|
|
{ |
|
|
|
fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top)); |
|
|
|
uRow = 0; |
|
|
|
onResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top)); |
|
|
|
|
|
|
|
if (onResizeBorder) |
|
|
|
{ |
|
|
|
uRow = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - border_thickness.bottom) |
|
|
|
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - borderThickness.bottom) |
|
|
|
{ |
|
|
|
uRow = 2; |
|
|
|
} |
|
|
|
|
|
|
|
// Determine if the point is at the left or right of the window.
|
|
|
|
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + border_thickness.left) |
|
|
|
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + borderThickness.left) |
|
|
|
{ |
|
|
|
uCol = 0; // left side
|
|
|
|
} |
|
|
|
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - border_thickness.right) |
|
|
|
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - borderThickness.right) |
|
|
|
{ |
|
|
|
uCol = 2; // right side
|
|
|
|
} |
|
|
|
|
|
|
|
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
|
|
|
|
HitTestValues[][] hitTests = new[] |
|
|
|
ReadOnlySpan<HitTestValues> hitZones = stackalloc HitTestValues[] |
|
|
|
{ |
|
|
|
new []{ HitTestValues.HTTOPLEFT, fOnResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, HitTestValues.HTTOPRIGHT }, |
|
|
|
new []{ HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT }, |
|
|
|
new []{ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT }, |
|
|
|
HitTestValues.HTTOPLEFT, onResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, |
|
|
|
HitTestValues.HTTOPRIGHT, HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT, |
|
|
|
HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT |
|
|
|
}; |
|
|
|
|
|
|
|
return hitTests[uRow][uCol]; |
|
|
|
var zoneIndex = uRow * 3 + uCol; |
|
|
|
|
|
|
|
return hitZones[zoneIndex]; |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual IntPtr CustomCaptionProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool callDwp) |
|
|
|
|