# 项目搭建、引用策略和启动流程

## 三类项目

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`。
