mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 18:04:26 +08:00
394 lines
9.9 KiB
Markdown
394 lines
9.9 KiB
Markdown
|
|
# 02-桌面组件系统
|
|||
|
|
|
|||
|
|
桌面组件(Desktop Component)是阑山桌面插件的核心功能。本文详细讲解组件系统的工作原理和开发方法。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 什么是桌面组件
|
|||
|
|
|
|||
|
|
桌面组件是显示在阑山桌面上的可视化元素,用户可以自由:
|
|||
|
|
- 添加/删除组件
|
|||
|
|
- 拖动调整位置
|
|||
|
|
- 调整大小
|
|||
|
|
- 配置属性
|
|||
|
|
|
|||
|
|
**常见组件示例:**
|
|||
|
|
- 时钟组件 - 显示当前时间
|
|||
|
|
- 天气组件 - 显示天气信息
|
|||
|
|
- 日历组件 - 显示日期和日程
|
|||
|
|
- 系统监控 - 显示 CPU/内存使用率
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📐 网格系统
|
|||
|
|
|
|||
|
|
阑山桌面使用网格系统管理组件布局。
|
|||
|
|
|
|||
|
|
### 网格概念
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────┐
|
|||
|
|
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
|||
|
|
│ │ 2x2│ │ 2x2│ │ 2x2│ │ 2x2│ │
|
|||
|
|
│ │ 格 │ │ 格 │ │ 格 │ │ 格 │ │
|
|||
|
|
│ └────┘ └────┘ └────┘ └────┘ │
|
|||
|
|
│ ┌────┐ ┌────────┐ ┌────┐ │
|
|||
|
|
│ │ 2x2│ │ 4x2 │ │ 2x2│ │
|
|||
|
|
│ │ 格 │ │ 格 │ │ 格 │ │
|
|||
|
|
│ └────┘ └────────┘ └────┘ │
|
|||
|
|
│ ┌────────┐ ┌────────┐ │
|
|||
|
|
│ │ 4x3 │ │ 4x3 │ │
|
|||
|
|
│ │ 格 │ │ 格 │ │
|
|||
|
|
│ └────────┘ └────────┘ │
|
|||
|
|
└─────────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
每格大小:约 60-80 像素(根据 DPI 自动调整)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 组件尺寸
|
|||
|
|
|
|||
|
|
组件尺寸以**格数**为单位:
|
|||
|
|
|
|||
|
|
| 属性 | 说明 | 示例 |
|
|||
|
|
|-----|------|------|
|
|||
|
|
| `MinWidthCells` | 最小宽度(格数) | 4 = 4格宽 |
|
|||
|
|
| `MinHeightCells` | 最小高度(格数) | 3 = 3格高 |
|
|||
|
|
|
|||
|
|
**常见尺寸参考:**
|
|||
|
|
|
|||
|
|
| 组件类型 | 推荐尺寸 | 实际像素(约) |
|
|||
|
|
|---------|---------|--------------|
|
|||
|
|
| 小图标 | 2x2 | 120x120 |
|
|||
|
|
| 天气卡片 | 4x3 | 240x180 |
|
|||
|
|
| 时钟 | 4x4 | 240x240 |
|
|||
|
|
| 日历 | 6x4 | 360x240 |
|
|||
|
|
| 宽面板 | 8x3 | 480x180 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🏗️ 创建组件
|
|||
|
|
|
|||
|
|
### 步骤 1:创建组件类
|
|||
|
|
|
|||
|
|
组件是继承自 Avalonia 控件的类:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
using Avalonia.Controls;
|
|||
|
|
using LanMountainDesktop.PluginSdk;
|
|||
|
|
|
|||
|
|
namespace MyPlugin;
|
|||
|
|
|
|||
|
|
public class WeatherWidget : Border // 继承自 Border 或其他控件
|
|||
|
|
{
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 组件初始化
|
|||
|
|
InitializeComponent(context);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void InitializeComponent(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 设置背景
|
|||
|
|
Background = new SolidColorBrush(Colors.Transparent);
|
|||
|
|
|
|||
|
|
// 设置圆角(使用宿主主题)
|
|||
|
|
CornerRadius = context.Appearance.ResolveCornerRadius(
|
|||
|
|
PluginCornerRadiusPreset.Component);
|
|||
|
|
|
|||
|
|
// 创建内容
|
|||
|
|
var textBlock = new TextBlock
|
|||
|
|
{
|
|||
|
|
Text = "天气组件",
|
|||
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|||
|
|
VerticalAlignment = VerticalAlignment.Center
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Child = textBlock;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤 2:注册组件
|
|||
|
|
|
|||
|
|
在 `Plugin.Initialize` 中注册:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public override void Initialize(HostBuilderContext context, IServiceCollection services)
|
|||
|
|
{
|
|||
|
|
services.AddPluginDesktopComponent<WeatherWidget>(
|
|||
|
|
new PluginDesktopComponentOptions
|
|||
|
|
{
|
|||
|
|
ComponentId = "MyPlugin.Weather", // 唯一标识
|
|||
|
|
DisplayName = "天气", // 显示名称
|
|||
|
|
IconKey = "Weather", // 图标(Fluent 图标名)
|
|||
|
|
Category = "工具", // 分类
|
|||
|
|
MinWidthCells = 4, // 最小宽度(格)
|
|||
|
|
MinHeightCells = 3, // 最小高度(格)
|
|||
|
|
CornerRadiusPreset = PluginCornerRadiusPreset.Component // 圆角预设
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### PluginDesktopComponentOptions 详解
|
|||
|
|
|
|||
|
|
| 属性 | 必需 | 说明 | 示例 |
|
|||
|
|
|-----|------|------|------|
|
|||
|
|
| `ComponentId` | ✅ | 唯一标识符 | `"MyPlugin.Weather"` |
|
|||
|
|
| `DisplayName` | ✅ | 显示名称 | `"天气"` |
|
|||
|
|
| `IconKey` | ✅ | 图标键名 | `"Weather"`、`"Clock"` |
|
|||
|
|
| `Category` | ✅ | 分类 | `"工具"`、`"信息"` |
|
|||
|
|
| `MinWidthCells` | ✅ | 最小宽度(格) | `4` |
|
|||
|
|
| `MinHeightCells` | ✅ | 最小高度(格) | `3` |
|
|||
|
|
| `CornerRadiusPreset` | ❌ | 圆角预设 | `PluginCornerRadiusPreset.Component` |
|
|||
|
|
| `ResizeMode` | ❌ | 调整大小模式 | `PluginDesktopComponentResizeMode.Free` |
|
|||
|
|
|
|||
|
|
### 常用 Fluent 图标
|
|||
|
|
|
|||
|
|
| 图标键名 | 用途 |
|
|||
|
|
|---------|------|
|
|||
|
|
| `Weather` | 天气相关 |
|
|||
|
|
| `Clock` | 时钟、时间 |
|
|||
|
|
| `Calendar` | 日历、日期 |
|
|||
|
|
| `Settings` | 设置 |
|
|||
|
|
| `Home` | 主页 |
|
|||
|
|
| `Search` | 搜索 |
|
|||
|
|
| `Star` | 收藏 |
|
|||
|
|
| `Heart` | 喜欢 |
|
|||
|
|
| `Info` | 信息 |
|
|||
|
|
| `Warning` | 警告 |
|
|||
|
|
|
|||
|
|
完整图标列表:[Fluent UI System Icons](https://github.com/microsoft/fluentui-system-icons)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 组件外观
|
|||
|
|
|
|||
|
|
### 圆角设置
|
|||
|
|
|
|||
|
|
插件必须使用宿主提供的圆角系统,以保持视觉一致性:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 获取组件标准圆角
|
|||
|
|
var cornerRadius = context.Appearance.ResolveCornerRadius(
|
|||
|
|
PluginCornerRadiusPreset.Component);
|
|||
|
|
|
|||
|
|
CornerRadius = cornerRadius;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可用的圆角预设:**
|
|||
|
|
|
|||
|
|
| 预设 | 用途 |
|
|||
|
|
|-----|------|
|
|||
|
|
| `Micro` | 微小元素 |
|
|||
|
|
| `Xs` | 小元素 |
|
|||
|
|
| `Sm` | 小卡片 |
|
|||
|
|
| `Md` | 普通按钮/卡片 |
|
|||
|
|
| `Lg` | 大面板 |
|
|||
|
|
| `Xl` | 强调容器 |
|
|||
|
|
| `Component` | **桌面组件标准** |
|
|||
|
|
| `Default` | 自适应 |
|
|||
|
|
|
|||
|
|
### 背景与透明
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 透明背景(推荐,让宿主壁纸透出)
|
|||
|
|
Background = new SolidColorBrush(Colors.Transparent);
|
|||
|
|
|
|||
|
|
// 毛玻璃效果
|
|||
|
|
Background = new SolidColorBrush(Color.Parse("#40FFFFFF"));
|
|||
|
|
|
|||
|
|
// 纯色背景
|
|||
|
|
Background = new SolidColorBrush(Color.Parse("#FF2D2D2D"));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 响应主题变化
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 订阅主题变化
|
|||
|
|
context.Appearance.AppearanceChanged += (_, _) =>
|
|||
|
|
{
|
|||
|
|
UpdateAppearance();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
UpdateAppearance();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void UpdateAppearance()
|
|||
|
|
{
|
|||
|
|
// 根据当前主题更新颜色
|
|||
|
|
var isDark = Application.Current?.ActualThemeVariant == ThemeVariant.Dark;
|
|||
|
|
|
|||
|
|
Foreground = new SolidColorBrush(isDark ? Colors.White : Colors.Black);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📏 尺寸与布局
|
|||
|
|
|
|||
|
|
### 获取实际尺寸
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 订阅尺寸变化
|
|||
|
|
SizeChanged += OnSizeChanged;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
|
|||
|
|
{
|
|||
|
|
// 获取当前实际尺寸(像素)
|
|||
|
|
var width = Bounds.Width;
|
|||
|
|
var height = Bounds.Height;
|
|||
|
|
|
|||
|
|
// 根据尺寸调整内容
|
|||
|
|
if (width < 200)
|
|||
|
|
{
|
|||
|
|
// 小尺寸模式
|
|||
|
|
ShowCompactView();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 完整模式
|
|||
|
|
ShowFullView();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 自适应布局
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
private void UpdateLayout()
|
|||
|
|
{
|
|||
|
|
var width = Bounds.Width;
|
|||
|
|
var height = Bounds.Height;
|
|||
|
|
|
|||
|
|
// 根据宽高比调整布局
|
|||
|
|
if (width > height * 2)
|
|||
|
|
{
|
|||
|
|
// 宽屏模式 - 水平排列
|
|||
|
|
_layout.Orientation = Orientation.Horizontal;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 正常模式 - 垂直排列
|
|||
|
|
_layout.Orientation = Orientation.Vertical;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔄 组件生命周期事件
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 组件加载完成(此时已添加到视觉树)
|
|||
|
|
Loaded += OnLoaded;
|
|||
|
|
|
|||
|
|
// 组件卸载(用户删除或关闭宿主)
|
|||
|
|
Unloaded += OnUnloaded;
|
|||
|
|
|
|||
|
|
// 尺寸变化
|
|||
|
|
SizeChanged += OnSizeChanged;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private async void OnLoaded(object? sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
// 加载数据
|
|||
|
|
await LoadDataAsync();
|
|||
|
|
|
|||
|
|
// 启动定时器
|
|||
|
|
_timer = new Timer(OnTimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnUnloaded(object? sender, RoutedEventArgs e)
|
|||
|
|
{
|
|||
|
|
// 清理资源
|
|||
|
|
_timer?.Dispose();
|
|||
|
|
_httpClient?.Dispose();
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💾 组件设置持久化
|
|||
|
|
|
|||
|
|
组件可以保存自己的设置:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class WeatherWidget : Border
|
|||
|
|
{
|
|||
|
|
private readonly IComponentSettingsAccessor _settings;
|
|||
|
|
|
|||
|
|
public WeatherWidget(PluginDesktopComponentContext context)
|
|||
|
|
{
|
|||
|
|
// 获取设置访问器
|
|||
|
|
_settings = context.Settings;
|
|||
|
|
|
|||
|
|
// 读取设置
|
|||
|
|
var city = _settings.GetValue<string>("city", defaultValue: "北京");
|
|||
|
|
var autoRefresh = _settings.GetValue<bool>("auto_refresh", defaultValue: true);
|
|||
|
|
|
|||
|
|
// 保存设置
|
|||
|
|
_settings.SetValue("city", "上海");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🐛 常见问题
|
|||
|
|
|
|||
|
|
### 问题 1:组件不显示在库中
|
|||
|
|
|
|||
|
|
**排查:**
|
|||
|
|
1. 确认已调用 `AddPluginDesktopComponent`
|
|||
|
|
2. 检查 `ComponentId` 是否唯一
|
|||
|
|
3. 确认组件类是 `public`
|
|||
|
|
|
|||
|
|
### 问题 2:组件显示异常
|
|||
|
|
|
|||
|
|
**排查:**
|
|||
|
|
1. 检查构造函数参数是否正确(需要 `PluginDesktopComponentContext`)
|
|||
|
|
2. 确认没有抛出未处理异常
|
|||
|
|
3. 查看日志文件
|
|||
|
|
|
|||
|
|
### 问题 3:圆角不生效
|
|||
|
|
|
|||
|
|
**原因:** 插件无法访问宿主 XAML 资源
|
|||
|
|
|
|||
|
|
**解决:** 使用代码设置圆角(见上文)
|
|||
|
|
|
|||
|
|
### 问题 4:尺寸不正确
|
|||
|
|
|
|||
|
|
**排查:**
|
|||
|
|
1. 检查 `MinWidthCells` 和 `MinHeightCells` 设置
|
|||
|
|
2. 确认内容没有强制尺寸
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📚 参考资源
|
|||
|
|
|
|||
|
|
- [PluginDesktopComponentOptions 源码](../../LanMountainDesktop.PluginSdk/PluginDesktopComponentOptions.cs)
|
|||
|
|
- [04-外观与主题系统](04-外观与主题系统.md)
|
|||
|
|
- [01-开发天气组件](../04-实战案例/01-开发天气组件.md)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 下一步
|
|||
|
|
|
|||
|
|
学习如何添加设置页面:
|
|||
|
|
|
|||
|
|
👉 **[03-设置系统集成](03-设置系统集成.md)** - 让用户配置你的组件
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*最后更新:2026年4月*
|