在做桌面软件时,我们大部分情况都不会使用系统自带的边框,基本上都是自己定制的。本文在Avalonia中实现自定义边框窗口。
取消系统自带边框
取消系统自带边框,通过设置 Window 的几个属性值即可。主要有以下两种方式:
- 方式1:SystemDecorations
- 方式2:ExtendClientAreaChromeHints
方式1:SystemDecorations
将Window的SystemDecorations设置为None,即可取消系统自带的Window的所有样式。此时,Window的无法显示关闭、最小化等按钮,无法通过边框拉伸窗口,也无法拖拽窗。
<Window ......
SystemDecorations="None">
</Window>
SystemDecorations是个枚举值,可以设置以下3个值:
// 系统边框的样子
// Determines system decorations (title bar, border, etc) for a Avalonia.Controls.Window
public enum SystemDecorations
{
// 没有边框
// No decorations
None = 0,
// 没有标题栏
// Window border without titlebar
BorderOnly = 1,
// 全部都有
// Fully decorated (default)
Full = 2
}
方式2:ExtendClientAreaChromeHints
Window的ExtendClientAreaChromeHints是一个枚举值,通过设置它的值来选择系统边框样式。可以设置以下三个值:
// 对于边框样式的类型的描述
// Hint for Window Chrome when ClientArea is Extended.
[Flags]
public enum ExtendClientAreaChromeHints
{
// 没有边框
// The will be no chrome at all.
NoChrome = 0,
// 使用系统边框
// Use SystemChrome
SystemChrome = 1,
// 平台默认
// The default for the platform.
Default = 2,
// 优先尝试使用系统边框,在 OSX 中使用 OSX 的边框样式,在 Windows 中使用 Windows 的边框样式。
// Use system chrome where possible. OSX system chrome is used, Windows managed
// chrome is used. This is because Windows Chrome can not be shown on top of user
// content.
PreferSystemChrome = 2,
// 在 OSX 上,标题框将会是一个更细的工具栏标题框,
// 标题栏三色的按钮的位置会比普通样式的要肉眼可见的低一点。
// On OSX the titlebar is the thicker toolbar kind.
// Causes traffic lights to be positioned slightly lower than normal.
OSXThickTitleBar = 8
}
单独使用Window的ExtendClientAreaChromeHints是无效的,需要结合 ExtendClientAreaToDecorationsHint 一起使用。ExtendClientAreaToDecorationsHint为bool值,表示是否将用户内容扩展到系统标题栏里面。
<Window ......
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome">
</Window>
如上设置这两个值时,窗口的边框和标题栏都不显示了,但窗口还是可以在边缘进行拉伸。如果要取消这个这个拉伸效果,则需要使用到另外一个值:
ExtendClientAreaTitleBarHeightHint="0"
ExtendClientAreaTitleBarHeightHint是描述标题栏的高度属性,标题栏的高度决定标题栏可拖动的地方。如果不希望窗口进行拖动拉伸,将其设置为0即可。
实现窗口拖拽
一般取消了系统自带的边框后,我们还需要自己实现窗口的拖拽的功能。
重新Window的OnPointerPressed方法即可
/// <summary>
/// 拖拽
/// </summary>
/// <param name="e"></param>
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
this.BeginMoveDrag(e);
}
}
当然,这样重新Window的OnPointerPressed,可能会导致窗口中具体的控件的功能失效,如ComboBox的下拉选项。此时,可以将OnPointerPressed应用到具体需要实现拖拽的区域。如下:
<Grid PointerPressed="Grid_PointerPressed">
<!-- 你的其他内容 -->
</Grid>