Browse Source

Add WndProcs to handle extended frame windows.

feature/managed-chrome-buttons-api
Dan Walmsley 6 years ago
parent
commit
cd496e2c61
  1. 3
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  2. 155
      src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs

3
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -1305,6 +1305,9 @@ namespace Avalonia.Win32.Interop
[DllImport("dwmapi.dll")]
public static extern int DwmIsCompositionEnabled(out bool enabled);
[DllImport("dwmapi.dll")]
public static extern bool DwmDefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref IntPtr plResult);
[DllImport("dwmapi.dll")]
public static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);

155
src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs

@ -12,11 +12,164 @@ using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia.Win32
{
public partial class WindowImpl
{
private int LEFTEXTENDWIDTH = 4;
private int RIGHTEXTENDWIDTH = 4;
private int BOTTOMEXTENDWIDTH = 4;
private int TOPEXTENDWIDTH = 100;
// Hit test the frame for resizing and moving.
HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
{
// Get the point coordinates for the hit test.
var ptMouse = PointFromLParam(lParam);
// Get the window rectangle.
GetWindowRect(hWnd, out var rcWindow);
// Get the frame rectangle, adjusted for the style without a caption.
RECT rcFrame = new RECT();
AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0);
// Determine if the hit test is for resizing. Default middle (1,1).
ushort uRow = 1;
ushort uCol = 1;
bool fOnResizeBorder = false;
// Determine if the point is at the top or bottom of the window.
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + TOPEXTENDWIDTH)
{
fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
uRow = 0;
}
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
{
uRow = 2;
}
// Determine if the point is at the left or right of the window.
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + LEFTEXTENDWIDTH)
{
uCol = 0; // left side
}
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - RIGHTEXTENDWIDTH)
{
uCol = 2; // right side
}
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
HitTestValues[][] hitTests = new[]
{
new []{ HitTestValues.HTTOPLEFT, fOnResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, HitTestValues.HTTOPRIGHT },
new []{ HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT },
new []{ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT },
};
System.Diagnostics.Debug.WriteLine(hitTests[uRow][uCol]);
return hitTests[uRow][uCol];
}
protected virtual unsafe IntPtr CustomCaptionProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool callDwp)
{
IntPtr lRet = IntPtr.Zero;
callDwp = !DwmDefWindowProc(hWnd, msg, wParam, lParam, ref lRet);
MARGINS margins = new MARGINS { cxLeftWidth = 0, cxRightWidth = 0, cyBottomHeight = 0, cyTopHeight = 100 };
RECT border_thickness = new RECT();
switch ((WindowsMessage)msg)
{
case WindowsMessage.WM_ACTIVATE:
{
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
LEFTEXTENDWIDTH = border_thickness.left;
RIGHTEXTENDWIDTH = border_thickness.right;
BOTTOMEXTENDWIDTH = border_thickness.bottom;
// Extend the frame into the client area.
margins.cxLeftWidth = border_thickness.left;
margins.cxRightWidth = border_thickness.right;
margins.cyBottomHeight = border_thickness.bottom;
margins.cyTopHeight = border_thickness.top;
var hr = DwmExtendFrameIntoClientArea(hWnd, ref margins);
//if (hr < 0)
{
// Handle the error.
}
lRet = IntPtr.Zero;
callDwp = true;
break;
}
case WindowsMessage.WM_NCCALCSIZE:
{
if (ToInt32(wParam) == 1)
{
lRet = IntPtr.Zero;
callDwp = false;
}
break;
}
case WindowsMessage.WM_NCHITTEST:
if (lRet == IntPtr.Zero)
{
lRet = (IntPtr)HitTestNCA(hWnd, wParam, lParam);
if (((HitTestValues)lRet) != HitTestValues.HTNOWHERE)
{
callDwp = false;
}
}
break;
}
return lRet;
}
}
public partial class WindowImpl
{
protected virtual unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
IntPtr lRet = IntPtr.Zero;
bool callDwp = true;
if (DwmIsCompositionEnabled(out bool enabled) == 0)
{
lRet = CustomCaptionProc(hWnd, msg, wParam, lParam, ref callDwp);
}
if (callDwp)
{
lRet = AppWndProc(hWnd, msg, wParam, lParam);
}
return lRet;
}
}
public partial class WindowImpl
{
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation",
Justification = "Using Win32 naming for consistency.")]
protected virtual unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
const double wheelDelta = 120.0;
uint timestamp = unchecked((uint)GetMessageTime());

Loading…
Cancel
Save