Browse Source

prototype, allowing to draw in non-client area.

without breaking win32 frame functionality.
pull/2128/head
Dan Walmsley 8 years ago
parent
commit
1a16e42378
  1. 8
      samples/ControlCatalog/MainWindow.xaml
  2. 7
      src/Avalonia.Visuals/Rect.cs
  3. 12
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  4. 96
      src/Windows/Avalonia.Win32/WindowImpl.cs

8
samples/ControlCatalog/MainWindow.xaml

@ -1,6 +1,8 @@
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
Title="Avalonia Control Gallery"
Icon="resm:ControlCatalog.Assets.test_icon.ico?assembly=ControlCatalog"
xmlns:local="clr-namespace:ControlCatalog">
<local:MainView/>
</Window>
xmlns:local="clr-namespace:ControlCatalog" Background="Transparent">
<Grid HorizontalAlignment="Left" Width="200" Background="Red">
<TextBlock Text="Drawing in Non-client Area Win32" />
</Grid>
</Window>

7
src/Avalonia.Visuals/Rect.cs

@ -120,6 +120,8 @@ namespace Avalonia
/// </summary>
public Size Size => new Size(_width, _height);
public double Left => _x;
/// <summary>
/// Gets the right position of the rectangle.
/// </summary>
@ -130,6 +132,11 @@ namespace Avalonia
/// </summary>
public double Bottom => _y + _height;
/// <summary>
/// Gets the top position of the rectangle.
/// </summary>
public double Top => _y;
/// <summary>
/// Gets the top left point of the rectangle.
/// </summary>

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

@ -907,6 +907,18 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetWindowTextW")]
public static extern bool SetWindowText(IntPtr hwnd, string lpString);
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public int leftWidth;
public int rightWidth;
public int topHeight;
public int bottomHeight;
}
[DllImport("dwmapi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
public enum ClassLongIndex : int
{
GCL_HCURSOR = -12,

96
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -455,6 +455,54 @@ namespace Avalonia.Win32
IntPtr.Zero);
}
protected int BorderTop { get; private set; }
protected int BorderLeft { get; private set; }
protected int BorderRight { get; private set; }
protected int BorderBottom { get; private set; }
private HitTestValues NCHitText(uint m, IntPtr LParam, IntPtr wParam)
{
int lParam = (int)LParam;
Point pt = new Point(lParam & 0xffff, lParam >> 16);
var rc = new Rect(Position, ClientSize);
int row = 1;
int col = 1;
bool onResizeBorder = false;
// Determine if we are on the top or bottom border
if (pt.Y >= rc.Top && pt.Y < rc.Top + BorderTop)
{
onResizeBorder = pt.Y < (rc.Top + BorderBottom);
row = 0;
}
else if (pt.Y < rc.Bottom && pt.Y > rc.Bottom - BorderBottom)
{
row = 2;
}
// Determine if we are on the left border or the right border
if (pt.X >= rc.Left && pt.X < rc.Left + BorderLeft)
{
col = 0;
}
else if (pt.X < rc.Right && pt.X >= rc.Right - BorderRight)
{
col = 2;
}
HitTestValues[,] hitTests = new HitTestValues[,]
{
{HitTestValues.HTTOPLEFT, onResizeBorder ? HitTestValues.HTTOP : HitTestValues.HTCAPTION, HitTestValues.HTTOPRIGHT},
{HitTestValues.HTLEFT, HitTestValues.HTNOWHERE, HitTestValues.HTRIGHT},
{HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT}
};
return hitTests[row, col];
}
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
protected virtual IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
@ -465,6 +513,8 @@ namespace Avalonia.Win32
RawInputEventArgs e = null;
bool callDWP = false;
WindowsMouseDevice.Instance.CurrentWindow = this;
switch ((UnmanagedMethods.WindowsMessage)msg)
@ -484,8 +534,54 @@ namespace Avalonia.Win32
break;
}
MARGINS margins = new MARGINS();
margins.leftWidth = Math.Abs(BorderLeft);
margins.rightWidth = Math.Abs(BorderRight);
margins.bottomHeight = Math.Abs(BorderBottom);
margins.topHeight = Math.Abs(BorderTop);
// int hr = UnmanagedMethods.DwmExtendFrameIntoClientArea(hWnd, ref margins);
return IntPtr.Zero;
case WindowsMessage.WM_NCCALCSIZE:
return IntPtr.Zero;
//break;
case WindowsMessage.WM_CREATE:
RECT rcClient;
UnmanagedMethods.GetWindowRect(hWnd, out rcClient);
RECT rc = new RECT();
uint style = UnmanagedMethods.GetWindowLong(hWnd, (int)UnmanagedMethods.WindowLongParam.GWL_STYLE);
uint styleEx = UnmanagedMethods.GetWindowLong(hWnd, (int)UnmanagedMethods.WindowLongParam.GWL_EXSTYLE);
UnmanagedMethods.AdjustWindowRectEx(ref rc, style, false, styleEx);
BorderTop = Math.Abs(rc.top);
BorderLeft = Math.Abs(0);
BorderRight = Math.Abs(0);
BorderBottom = Math.Abs(0);
break;
case WindowsMessage.WM_NCHITTEST:
var ht = NCHitText(msg, lParam, wParam);
callDWP = (ht == HitTestValues.HTNOWHERE);
if (callDWP)
{
}
else
{
return new IntPtr((int)ht);
}
break;
case UnmanagedMethods.WindowsMessage.WM_CLOSE:
bool? preventClosing = Closing?.Invoke();
if (preventClosing == true)

Loading…
Cancel
Save