当前位置: 首页 > news >正文

C# Avalonia 20 - WindowsMenu- ModernWindow

下一个例子会把这个写成一个style + cs类,这样方便模板调用。

ModernWindow.axaml代码

<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Height="300" Width="300"x:Class="AvaloniaUI.ModernWindow"SystemDecorations="None"TransparencyLevelHint="Transparent"Background="Transparent"Title="ModernWindow"><Border x:Name="windowFrame"BorderBrush="#395984"BorderThickness="1"CornerRadius="0,20,30,40"><Border.Background><LinearGradientBrush><GradientStop Color="#E7EBF7" Offset="0"/><GradientStop Color="#CEE3FF" Offset="0.5"/></LinearGradientBrush></Border.Background><Grid RowDefinitions="auto,*,auto"><!-- 标题栏:PointerPressed 用于拖动窗口 --><Grid Grid.Row="0"Margin="1"Background="Transparent"ColumnDefinitions="*,auto"PointerPressed="titleBar_PointerPressed"><!-- 可拖拽区域 --><TextBlock Grid.Column="0"VerticalAlignment="Center"Padding="5"Text="Modern Window"/><!-- 关闭按钮 --><Button Grid.Column="1"Margin="4"Padding="6,2"VerticalAlignment="Center"Click="cmdClose_Click">x</Button></Grid><Grid Grid.Row="1" Background="#B5CBEF" ><TextBlock Grid.Row="1" VerticalAlignment="Center"HorizontalAlignment="Center"Foreground="White"FontSize="20"Text="Content Goes Here"/></Grid><!-- Footer --><Grid Grid.Row="2"Margin="1,10,1,1"ColumnDefinitions="*,auto"Background="Transparent"><!-- Footer 文本 --><TextBlock Grid.Column="0"VerticalAlignment="Center"HorizontalAlignment="Center"Padding="5"Text="Footer"/><!-- 右下角 ResizeGrip --><Border Grid.Column="1" ZIndex="100"Width="16"Height="16"Margin="5"Background="Transparent"HorizontalAlignment="Right"VerticalAlignment="Bottom"Tag="BottomRight"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"><Rectangle Margin="1"><Rectangle.Fill><VisualBrush TileMode="Tile"DestinationRect="0,0,4,4"SourceRect="0,0,8,8"><VisualBrush.Visual><Canvas Width="8" Height="8"><Rectangle Width="4"Height="4"Canvas.Left="4"Canvas.Top="4"Fill="#AAA"/></Canvas></VisualBrush.Visual></VisualBrush></Rectangle.Fill></Rectangle></Border></Grid><!-- 四边 --><Rectangle Width="5" Fill="Transparent" HorizontalAlignment="Left"  VerticalAlignment="Stretch"Cursor="SizeWestEast" Tag="Left"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Width="5" Fill="Transparent" HorizontalAlignment="Right" VerticalAlignment="Stretch"Cursor="SizeWestEast" Tag="Right"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Height="5" Fill="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Top"Cursor="SizeNorthSouth" Tag="Top"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Height="5" Fill="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"Cursor="SizeNorthSouth" Tag="Bottom"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><!-- 四角(10x10) --><Rectangle Width="10" Height="10" Fill="Transparent"HorizontalAlignment="Left" VerticalAlignment="Top"Cursor="SizeAll" Tag="TopLeft"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Width="10" Height="10" Fill="Transparent"HorizontalAlignment="Right" VerticalAlignment="Top"Cursor="SizeAll" Tag="TopRight"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Width="10" Height="10" Fill="Transparent"HorizontalAlignment="Left" VerticalAlignment="Bottom"Cursor="SizeAll" Tag="BottomLeft"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/><Rectangle Width="10" Height="10" Fill="Transparent"HorizontalAlignment="Right" VerticalAlignment="Bottom"Cursor="SizeAll" Tag="BottomRight"Grid.RowSpan="3"PointerPressed="resizeGrip_PointerPressed"PointerMoved="resizeGrip_PointerMoved"PointerReleased="resizeGrip_PointerReleased"/></Grid></Border>
</Window>

ModernWindow.axaml.cs代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using System;namespace AvaloniaUI;public partial class ModernWindow : Window
{[Flags]private enum ResizeEdges{None = 0,Left = 1,Top = 2,Right = 4,Bottom = 8}private bool isResizing;private ResizeEdges edges;private PixelPoint startWindowPos;        // Pixelprivate Size startWindowSize;             // DIPprivate PixelPoint startPointerScreenPx;  // Screen Pixelprivate double startRenderScaling;public ModernWindow(){InitializeComponent();MinWidth = 150;MinHeight = 120;}private void titleBar_PointerPressed(object? sender, PointerPressedEventArgs e){if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)BeginMoveDrag(e);}private void cmdClose_Click(object? sender, RoutedEventArgs e){Close();}private void resizeGrip_PointerPressed(object? sender, PointerPressedEventArgs e){if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)return;if (sender is not Control c)return;edges = ParseEdges(c.Tag as string);if (edges == ResizeEdges.None)return;var topLevel = TopLevel.GetTopLevel(this);if (topLevel is null)return;isResizing = true;startWindowPos = Position; // PixelstartWindowSize = new Size(Bounds.Width, Bounds.Height); // DIPstartRenderScaling = RenderScaling;startPointerScreenPx = GetPointerScreenPx(e, topLevel);e.Pointer.Capture(c);e.Handled = true;}private void resizeGrip_PointerReleased(object? sender, PointerReleasedEventArgs e){if (!isResizing)return;isResizing = false;edges = ResizeEdges.None;e.Pointer?.Capture(null);e.Handled = true;}private void resizeGrip_PointerMoved(object? sender, PointerEventArgs e){if (!isResizing || edges == ResizeEdges.None)return;var topLevel = TopLevel.GetTopLevel(this);if (topLevel is null)return;var pointerScreenPx = GetPointerScreenPx(e, topLevel);var dxPx = pointerScreenPx.X - startPointerScreenPx.X;var dyPx = pointerScreenPx.Y - startPointerScreenPx.Y;var dxDip = dxPx / startRenderScaling;var dyDip = dyPx / startRenderScaling;var newX = startWindowPos.X;var newY = startWindowPos.Y;var newW = startWindowSize.Width;var newH = startWindowSize.Height;var hasLeft = (edges & ResizeEdges.Left) != 0;var hasRight = (edges & ResizeEdges.Right) != 0;var hasTop = (edges & ResizeEdges.Top) != 0;var hasBottom = (edges & ResizeEdges.Bottom) != 0;if (hasRight)newW = Math.Max(MinWidth, startWindowSize.Width + dxDip);if (hasBottom)newH = Math.Max(MinHeight, startWindowSize.Height + dyDip);if (hasLeft){newW = Math.Max(MinWidth, startWindowSize.Width - dxDip);newX = startWindowPos.X + dxPx;if (newW <= MinWidth)newX = startWindowPos.X + ClampDeltaPxForMin(startWindowSize.Width, MinWidth);}if (hasTop){newH = Math.Max(MinHeight, startWindowSize.Height - dyDip);newY = startWindowPos.Y + dyPx;if (newH <= MinHeight)newY = startWindowPos.Y + ClampDeltaPxForMin(startWindowSize.Height, MinHeight);}Position = new PixelPoint(newX, newY);Width = newW;Height = newH;e.Handled = true;}private static ResizeEdges ParseEdges(string? tag){return tag switch{"Left" => ResizeEdges.Left,"Right" => ResizeEdges.Right,"Top" => ResizeEdges.Top,"Bottom" => ResizeEdges.Bottom,"TopLeft" => ResizeEdges.Top | ResizeEdges.Left,"TopRight" => ResizeEdges.Top | ResizeEdges.Right,"BottomLeft" => ResizeEdges.Bottom | ResizeEdges.Left,"BottomRight" => ResizeEdges.Bottom | ResizeEdges.Right,_ => ResizeEdges.None};}private static PixelPoint GetPointerScreenPx(PointerEventArgs e, TopLevel topLevel){var pInTopLevel = e.GetPosition(topLevel);      // DIPreturn topLevel.PointToScreen(pInTopLevel);     // Pixel}private int ClampDeltaPxForMin(double startSizeDip, double minSizeDip){var clampPx = (startSizeDip - minSizeDip) * startRenderScaling;return (int)Math.Round(clampPx);}
}

运行效果

image

 

http://www.jsqmd.com/news/517892/

相关文章:

  • 【GIS开发】从WKT到PostGIS:空间数据格式解析、存储与可视化实战
  • 聊聊水草种植生产商家选择,全国范围内哪家口碑好、价格合理 - myqiye
  • Arduino控制VESC电机控制器的通信协议与库开发
  • 2026年对焊弯头市场口碑解析,这些供应商值得信赖,行业内对焊弯头优质企业盘点及核心优势详细解读 - 品牌推荐师
  • VSCode远程开发踩坑实录:解决Failed to parse remote port错误的3种方法
  • Pixel Dimension Fissioner免配置环境:预置中文分词器与标点规范化模块
  • 杭州爱拉贝科技联系方式:关于其全网获客服务的客观解析与通用性使用指南 - 品牌推荐
  • 塑胶模具定做哪家靠谱?2026年市场优选指南,市面上塑胶模具厂家口碑分析优质品牌选购指南 - 品牌推荐师
  • 比迪丽LoRA模型数据管理实战:与MySQL数据库集成存储生成记录
  • 避坑指南:Dev Eco Studio4.0安装常见错误及解决方法(HarmonyOS开发环境搭建)
  • PyCharm调试Torch分布式训练的3个隐藏坑点(附2023最新解决方案)
  • 乱翻译追忆
  • 企业上线实在 Agent,多久能收回投入成本?——深度拆解企业级AI Agent的ROI转化路径
  • 2025-2026年AI营销智能体公司推荐:中大型企业智能化转型口碑服务商评测 - 品牌推荐
  • 通义千问1.5-1.8B-Chat-GPTQ-Int4:基于LSTM与Transformer的对话模型演进简析
  • Qwen3-VL-4B Pro开源镜像:支持离线部署的国产多模态大模型方案
  • 2026年分析全国热镀锌管选购要点,镀锌管加工厂哪家专业 - 工业品牌热点
  • 别再让内网裸奔了!手把手教你用VLAN和防火墙搞定网络分段(附思科/华为配置示例)
  • 51单片机温湿度检测及调节系统
  • 3.21学习总结
  • UniApp左右滑动切换页面的两种实现方案对比:哪种更适合你的项目?
  • STM32双区远程升级系统设计与实现
  • C++/Qt内存管理专题【核心机制详解】
  • 盘点2026年热镀锌管源头厂家,价格实惠的有哪些 - 工业推荐榜
  • 深信服桌面云实战:从零部署到高效运维的配置全景指南
  • 2026抗台风窗品牌排名,欧莱诺门窗凭借高品质位居前列 - 工业设备
  • htop安装不了怎么解决
  • C++/Qt开发方向详解:优势、缺点与选择建议
  • 2026年AI营销智能体公司推荐:大中企业营销全流程自动化靠谱服务商对比分析 - 品牌推荐
  • 前端组件库——shadcn/ui:轻量、自由、可拥有,解锁前端组件库的AI时代未来