Files
zhaowei.huangandCursor 158d770c54 docs: 添加 cyclegui-app-development 项目技能
将 CycleGUI 开发技能(含 Duplicated id 防碰撞规范)纳入 .cursor/skills,并调整 gitignore 仅放行 skills 目录可提交。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 22:38:18 +08:00

152 lines
4.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目搭建、引用策略和启动流程
## 三类项目
1. **CycleGUI 同解决方案内示例**:例如 `LearnCycleGUI`,可 `ProjectReference``CycleGUI\CycleGUI.csproj`
2. **宿主/调度程序**:例如 `SimpleLite`,引用真实 `CycleGUI.dll`,用 `Costura.Fody` 把托管程序集包进宿主 Assembly。
3. **插件或二次开发项目**:默认引用 `RefCycleGUI.dll`,不要引用真实 `CycleGUI.dll`。真实实现由宿主提供,以保护和隔离 CycleGUI 代码资产。
## 插件/二开项目模板
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="CycleGUI">
<HintPath>$(CGUILibDir)RefCycleGUI.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
</Project>
```
`Private=false` 用于避免把 Ref 程序集复制成插件自己的运行时依赖。宿主进程负责提供真实 CycleGUI。
## 宿主程序模板
```xml
<ItemGroup>
<PackageReference Include="Costura.Fody" Version="5.7.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<Reference Include="CycleGUI">
<HintPath>$(CGUILibDir)CycleGUI.dll</HintPath>
</Reference>
</ItemGroup>
```
`FodyWeavers.xml`
```xml
<Weavers>
<Costura />
</Weavers>
```
native 依赖如 `libVRender.dll` 按宿主自己的资源、输出目录或加载策略处理,不要把插件二开项目设计成显式部署真实 `CycleGUI.dll`
## 同解决方案示例模板
```xml
<ItemGroup>
<ProjectReference Include="..\..\CycleGUI\CycleGUI.csproj" />
</ItemGroup>
```
只在跟 CycleGUI 源码一起开发和验证的示例中使用该模式。
## 常用 using
```csharp
using CycleGUI;
using CycleGUI.API;
using CycleGUI.Terminals;
using System.Drawing;
using System.Numerics;
```
## 本地启动
```csharp
Terminal.RegisterRemotePanel(CreateMainPanel);
LocalTerminal.SetTitle("MyApp");
LocalTerminal.SetIcon(icoBytes, "MyApp");
LocalTerminal.AddMenuItem("Exit", LocalTerminal.Terminate);
LocalTerminal.Start();
GUI.PromptPanel(CreateMainPanel(GUI.defaultTerminal));
```
`Terminal.RegisterRemotePanel` 让 TCP/Web 终端连接后也能拿到欢迎面板。`GUI.PromptPanel` 显示本地默认终端上的主面板。
## Web 启动
```csharp
Task.Run(() => WebTerminal.Use(port: 8081, ico: icoBytes));
```
可配合 `LeastServer` 发布静态文件和简单 HTTP API。Web 细节见 `terminals-and-web.md`
## 图标设置(exe / 托盘 / Web favicon
三处图标**统一用 `.ico` 格式**Windows 图标;建议内含 16/32/48 多尺寸,需要高清可再加 256)。常见做法是一个 `.ico` 同时用于三处。
1. **exe 可执行程序图标**csproj 里 `<ApplicationIcon>`,编译期写入 PE 资源,资源管理器/任务栏看到的就是它。
```xml
<PropertyGroup>
<ApplicationIcon>res\app_icon.ico</ApplicationIcon>
</PropertyGroup>
```
2. **LocalTerminal 托盘 / 窗口图标**`LocalTerminal.SetIcon(byte[] icoBytes, string name)`,传 `.ico` 文件字节,须在 `LocalTerminal.Start()` 之前调用。
3. **WebTerminal 浏览器 favicon**`WebTerminal.Use(int port, byte[] ico = null)`,把同一份 `.ico` 字节作为 `ico:` 传入。
`icoBytes` 的两种来源:
```csharp
// A) 把 .ico 作为嵌入资源(csproj: <EmbeddedResource Include="app_icon.ico" />),运行时读出
static byte[] LoadIcon()
{
var asm = Assembly.GetExecutingAssembly();
using var s = asm.GetManifestResourceStream(
asm.GetManifestResourceNames().First(p => p.Contains(".ico")));
return new BinaryReader(s).ReadBytes((int)s.Length);
}
// B) 直接从磁盘文件读
byte[] icoBytes = File.ReadAllBytes("res/app_icon.ico");
```
嵌入式(A)适合单文件分发,图标随程序集走、不依赖外部文件;磁盘式(B)适合图标可替换的场景。
完整三处一起设置:
```xml
<!-- .csproj -->
<PropertyGroup>
<ApplicationIcon>res\app_icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="res\app_icon.ico" />
</ItemGroup>
```
```csharp
var icoBytes = LoadIcon();
LocalTerminal.SetTitle("MyApp");
LocalTerminal.SetIcon(icoBytes, "MyApp"); // 托盘 + 窗口
LocalTerminal.Start();
WebTerminal.Use(port: 8081, ico: icoBytes); // Web favicon
```
> `SetIcon` / `WebTerminal.Use` 只接受 `.ico` 字节,不要传 PNG/JPG 字节。要从 PNG 生成,请先离线转成多尺寸 `.ico`。