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

87 lines
3.3 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.
# 终端和 Web
## 终端类型
- `LocalTerminal`:桌面原生窗口,使用 `LocalTerminal.Start()`
- `WebTerminal`:浏览器/WebSocket 终端,使用 `WebTerminal.Use(port, ico)`
- `TCPTerminal`TCP 远程终端,使用 `TCPTerminal.Serve(port)`
## 本地窗口
```csharp
LocalTerminal.SetTitle("MyApp");
LocalTerminal.SetIcon(icoBytes, "MyApp");
LocalTerminal.AddMenuItem("Exit", LocalTerminal.Terminate);
LocalTerminal.Start(); // 或 LocalTerminal.Start(hideAfterInit: true)
GUI.PromptPanel(CreateMainPanel(GUI.defaultTerminal));
```
`LocalTerminal.Start()` 应在 `GUI.PromptPanel` 之前调用。`SetIcon(byte[] icoBytes, string name)` 设置托盘和窗口图标。
### 启动后隐藏 libVRender 窗口 / 控制台
`LocalTerminal.Start(bool hideAfterInit = false)``hideAfterInit``true` 时:libVRender **仍会启动**,首帧渲染后自动隐藏主窗口(`glfwHideWindow`),渲染循环继续;托盘双击可恢复。这是**隐藏**,不是终止渲染后端。
控制台隐藏需应用自行处理(例如 Detour/Medulla 用 `ShowWindow(GetConsoleWindow(), SW_HIDE)`),与 `hideAfterInit` 无关。
常见做法是把开关放进工作目录 JSON,由静态构造函数或启动代码读取后传入 `LocalTerminal.Start`
| 应用 | 配置文件 | 字段 |
| --- | --- | --- |
| DetourLite | `detourconsole.json` | `MinimizeToTray``HideConsoleOnStart``CPort` |
| Medulla | `medullaconsole.json` | `MinimizeToTray``HideConsoleOnStart` |
示例(启动 libVRender 后立即隐藏主窗口):
```json
{
"HideConsoleOnStart": false,
"MinimizeToTray": true
}
```
Detour 配置细节见 `detour-configuration` skillMedulla 见 `medulla-startup-config` skill。
## WebTerminal
```csharp
Terminal.RegisterRemotePanel(CreateMainPanel);
Task.Run(() => WebTerminal.Use(port: 8081, ico: icoBytes));
```
`RegisterRemotePanel` 让 Web/TCP 连接可以创建欢迎面板。`ico:` 是浏览器 favicon。
## 图标 icoBytes
`SetIcon``WebTerminal.Use(ico:)` 都接受 **`.ico` 文件字节**(不接受 PNG/JPG)。连同 csproj 的 `<ApplicationIcon>`exe 图标),三处统一用一个 `.ico` 即可。`icoBytes` 可从嵌入资源或磁盘读取:
```csharp
static byte[] LoadIcon() // 嵌入资源:csproj 里 <EmbeddedResource Include="app_icon.ico" />
{
var asm = Assembly.GetExecutingAssembly();
using var s = asm.GetManifestResourceStream(
asm.GetManifestResourceNames().First(p => p.Contains(".ico")));
return new BinaryReader(s).ReadBytes((int)s.Length);
}
// 或:byte[] icoBytes = File.ReadAllBytes("res/app_icon.ico");
```
三处图标(exe / 托盘 / web favicon)的完整设置见 `project-setup-and-packaging.md` 的「图标设置」。
## LeastServer
`WebTerminal.Use()` 内部启动 `LeastServer` 并提供 WebSocket 路由和 webVRender 页面。可增加静态文件和简单 HTTP API:
```csharp
LeastServer.AddServingFiles("/static", "path/to/htdocs");
LeastServer.AddGetHandler("/api/status", () => "OK");
LeastServer.AddPostTextHandler("/api/data", body => ProcessData(body));
```
## 多终端注意事项
- `IssueToDefault()` 发给默认终端。
- `IssueToAllTerminals()` 发给所有终端。
- `panel.Terminal` 可用于把弹窗、Painter 或操作限定到当前终端。
- Painter 需要终端隔离时设置 `painter.terminal = specificTerminal`