diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md new file mode 100644 index 0000000..319760f --- /dev/null +++ b/DEVELOPER_GUIDE.md @@ -0,0 +1,399 @@ +# Better-Seewo 插件开发指南 + +**正式名称**: 希沃白板功能增强插件套件 +**作者**: 雾启工作室 (`miao-moe`) +**版本**: 1.1.0 +**项目**: https://github.com/miao-moe/Better-Seewo + +这是一个为希沃白板 5 开发的完整功能增强插件套件,基于对 `EasiNote.Api.dll` 的逆向工程成果构建。 + +## 背景 + +希沃白板 5 插件 SDK 文档严重不足,导致开发者难以找到确切的菜单注册点。此项目通过完全重新构建,从 `EasiNote.Api.dll` 中提取真实常量,填补了所有开发空白。 + +## 关键发现 + +通过逆向 `EasiNote.Api.dll` (版本 5.2.4.9855) 发现,最完整的菜单注册常量位于类型 `Cvte.EasiNote.UIItemPurposes` 中,包含 **13 个有效值**。 + +以下是 **所有真实可用的常量** 列表(没有 `ApplicationMenu` 或 `ExtendedTitleBar`) + +| 常量名 | 实际字符串值 | 用途 | 功能描述 | +|---|---|---|---| +| `ToolBar` | `EduBoard.V5.ToolBarItem` | 通用顶部工具栏 | 白板顶部的工具按钮区域 | +| `FunctionBar` | `EduBoard.V5.FunctionBarItem` | 功能栏 | 绘制工具栏(画笔、橡皮擦等) | +| `BoardEditMenu` | `EduBoard.V5.BoardEditMenuItem` | 备课模式·右键菜单 | 课件右侧的右键菜单(导出墨迹、设置) | +| `BoardDisplayMenu` | `EduBoard.V5.BoardDisplayMenuItem` | 授课模式·右键菜单 | 授课时课件的右键菜单 | +| `ElementEditMenu` | `EduBoard.V5.ElementEditMenuItem` | 备课模式·元素右键菜单 | 备课时对板书元素的右键操作 | +| `ElementDisplayMenu` | `EduBoard.V5.ElementDisplayMenuItem` | 授课模式·元素右键菜单 | 授课时对板书元素的右键操作 | +| `HeadToolBar` | `EduBoard.V5.HeadToolBarItem` | 顶级工具栏 | 白板顶部的主工具栏 | +| `BrowserTitleBar` | `EduBoard.V5.ExtendedTitleBar.Browser` | 浏览器·标题栏 | 备课时浏览器区域的标题栏 | +| `CloudTitleBar` | `EduBoard.V5.ExtendedTitleBar.Cloud` | 云盘·标题栏 | 备课时云盘区域的标题栏 | +| `AllTitleBar` | `EduBoard.V5.ExtendedTitleBar.All` | 所有·标题栏 | 备课时所有标题栏的集合 | +| `TabUniqueApplicationMenu` | `EduBoard.V5.ApplicationMenu.Shell` | 当前标签页·应用菜单 | 当前标签页的左下角汉堡菜单 | +| `TabGlobalApplicationMenu` | `EduBoard.V5.ApplicationMenu.All` | 全局·应用菜单 | 所有标签页的左下角汉堡菜单 | +| `MultiBoardProxyToolBar` | `EduBoard.V5.MultiBoardProxyToolBar.Shell` | 多板代理·工具栏 | 多板代理的工具栏 | + +**重要提示**:希沃 SDK 中没有 `ApplicationMenu` 或 `ExtendedTitleBar` 类型常量。这些是实际情况,使用对应的具体常量替代。 + +## 项目结构 + +``` +Better-Seewo/ +├── docs/ +│ └── DEVELOPER_GUIDE.md # 完整开发指南(您当前查看的文档) +├── examples/ # 核心模块示例实现 +│ ├── boardeditmenu/ # BoardEditMenuItem 示例(备课·右键菜单) +│ │ ├── BoardMenuExportInk.cs # 导出墨迹功能 +│ │ └── BoardMenuSettings.cs # 设置功能 +│ ├── headtoolbar/ # HeadToolBarItem 示例(通用工具栏) +│ │ └── HeadToolBarSettings.cs # Better-Seewo 入口 +│ └── forms/ # 主界面(BetterSeewoMainWindow.xaml) +├── scripts/ # 安装/构建脚本 +│ ├── install.ps1 # 管理员安装脚本 +│ └── build-release.ps1 # 自动构建发布 +├── bin/ # 构建输出目录 +│ ├── Debug/ # 调试版本 +│ └── Release/ # 发布版本 +├── manifest.coin # 插件元数据声明 +├── Better-Seewo.sln # Visual Studio 解决方案 +└── Better-EN5/ # EN5 插件核心模块 + ├── Program.cs # 插件入口 + ├── Services/ # 服务层 (Ink/Conversion/Touch/Activation) + ├── UI/ # 界面组件 + │ ├── BetterSeewoMainWindow.xaml.xml # 窗体资源 + │ └── ... (所有界面实现) + ├── UIItemLangInfo.cs # 多语言支持数据结构 + └── UIItemManagerExtensions.cs # 菜单注册辅助扩展方法 +``` + +## 核心模块 + +### 1. 菜单注册机制 + +菜单注册使用 `IUIItemManager.AppendWithLang()` 方法,它是 Better-EN5 封装的方便易用的扩展方法,集成了菜单项注册 + 多语言支持的功能。 + +**注册流程**: +1. 创建继承自 `UIItem` 的子类(根据目标位置选择基类) +2. 通过常量 `UIItemPurposes.BoardEditMenu` 等指定注册位置 +3. 实现 `Command` 属性实现功能逻辑 +4. 通过 `AppendWithLang` 自动注册 + 多语言支持 + +### 2. 五个核心服务 + +#### InkService (墨迹管理) +- **功能**:导出/导入课件墨迹数据 +- **技术**:反射调用希沃白板 Remark API,避免硬编译依赖 +- **支持**:希沃白板 5.2.x ~ 5.3.x 版本 +- **应用场景**:课件墨迹备份、恢复、跨设备同步 + +#### ConversionService (文件转换) +- **功能**:PPT ↔ ENBX 格式互转 +- **技术**:独立进程实现 (`EasiNote.OfficeDocumentConverter.exe`) +- **优势**:避免平台兼容性问题,保持原始文件质量 + +#### TouchFixService (触摸修复) +- **功能**:为非触摸大屏启用 IWB 模式,修复触摸检测 bug +- **技术**:注册表 + 配置文件补丁 (IWBConfig.json, TouchConfig.ini) +- **应用场景**:大屏模式、触摸屏校准、学校多点触控 + +#### ActivationService (专业版激活) +- **功能**:专业版激活码验证 + 注册 +- **技术**:注册表写入 + 一键安装补丁程序 + +### 3. 主界面架构 + +采用 **16:9 横版布局** (Fluent 设计风格 + 圆角 + 动画): +- **左侧** (1/4):Better-EN5 模块导航 + 功能面板 +- **右侧** (3/4):特定模块的内容区域 (墨迹管理、文件转换、触摸修复、大屏支持、激活) + +## 快速入门 + +### 1. 环境要求 +- .NET 6.0 SDK +- 希沃白板 5 (版本 5.2.2.653 ~ 5.3.0.0) + +### 2. 构建项目 + +```bash +# 调试版本构建 +dotnet build Better-EN5/Better-EN5.csproj -c Debug + +# 发布版本构建 +dotnet build Better-EN5/Better-EN5.csproj -c Release +``` + +### 3. 安装插件 + +#### 方式一:安装程序 +```bash +# 运行生成的安装程序 +cd Better-EN5/bin/Release +dotnet tool install -g dotnetCampus.EasiPlugin.Sdk.Boost +Boost build . +``` + +#### 方式二:手动部署 +```powershell +# 以管理员权限运行 +. +\\install.ps1 +``` + +### 4. 使用 Better-Seewo + +1. **重启希沃白板 5** +2. 找到 Better-Seewo 入口: + - **备课模式**:右键菜单 → Better-Seewo(或 `HeadToolBar` 工具栏) + - **授课模式**:左下角汉堡菜单 → Better-Seewo(待添加) +3. 体验增强功能 + +## 完整模块示例 + +以下是两个完整的模块实现示例,涵盖所有开发要点。 + +### 示例 1:备课模式·右键菜单 (BoardEditMenuItem) + +**文件**:`examples/boardeditmenu/BoardMenuExportInk.cs` + +```csharp +using Microsoft.Win32; +using Cvte.EasiNote; +using Cvte.Windows.Input; +using BetterEN5.Services; + +namespace BetterEN5.UI +{ + // 继承自 BoardEditMenuItem 基类 + public class BoardMenuExportInk : BoardEditMenuItem + { + public BoardMenuExportInk() + { + SortHint = 998; // 排序权重 + Command = new DelegateCommand(() => + { + var dialog = new SaveFileDialog + { + Title = "导出墨迹", + Filter = "墨迹文件 (*.ink.json)|*.ink.json|JSON 文件 (*.json)|*.json", + DefaultExt = ".ink.json", + FileName = "课件墨迹.ink.json" + }; + if (dialog.ShowDialog() == true) + { + var inkService = new InkService(); + _ = inkService.ExportInkAsync(dialog.FileName); + } + }); + Predicate = _ => true; // 总是显示 + } + } +} +``` + +**自动注册流程(不需要手动)**: +```csharp +// 只需一行代码即可注册到对应位置 +var manager = Container.Current.Get(); +manager.AppendWithLang( + new BoardMenuExportInk(), + new UIItemAttribute(UIItemPurposes.BoardEditMenu), + new[] { new UIItemLangInfo(new CultureInfo("zh-CHS"), "导出墨迹") } +); +``` + +### 示例 2:通用工具栏 (HeadToolBarItem) + +**文件**:`examples/headtoolbar/HeadToolBarSettings.cs` + +```csharp +using Cvte.EasiNote; +using Cvte.Windows.Input; + +namespace BetterEN5.UI +{ + // 继承自 HeadToolBarItem 基类 + public class HeadToolBarSettings : HeadToolBarItem + { + public HeadToolBarSettings() + { + SortHint = 999; + Command = new DelegateCommand(() => + { + // 打开 Better-Seewo 主窗口 + BetterSeewoMainWindow.ShowWindow(); + }); + Predicate = _ => true; + } + } +} +``` + +**注册代码**: +```csharp +manager.AppendWithLang( + new HeadToolBarSettings(), + new UIItemAttribute(UIItemPurposes.HeadToolBar), + new[] { new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo") } +); +``` + +## 开发完整指南 + +### 1. 创建新菜单项 + +1. **选择目标位置**,确定基类: + - `BoardEditMenu` → `BoardEditMenuItem` + - `HeadToolBar` → `HeadToolBarItem` + - `TabGlobalApplicationMenu` → `ApplicationMenuItem` + - `AllTitleBar` → `ExtendedTitleBarItem` + +2. **创建类**,继承对应基类,实现以下成员: + - `SortHint`:决定菜单项排序 + - `Command`:实现功能逻辑 (ICommand) + - `Predicate`:决定何时显示 (Func) + +### 2. 注册菜单项 + +**核心类**:`BetterEN5.UIItemManagerExtensions.AppendWithLang` + +该扩展方法集成了菜单注册 + 多语言支持。只需关注核心注册流程即可。 + +### 3. 多语言支持 + +```csharp +new[] +{ + new UIItemLangInfo(new CultureInfo("zh-CHS"), "功能名称"), + new UIItemLangInfo(new CultureInfo("en"), "Feature Name"), + new UIItemLangInfo(new CultureInfo("ja"), "機能名"), +} +``` + +系统会自动生成正确的 Key:`Lang.{前缀}.{类名}` + +### 4. 所有菜单常量对照表 + +| 区域 | 常量 | 基类 | 使用场景 | +|---|---|---|---| +| **备课模式·右键菜单** | `BoardEditMenu` | `BoardEditMenuItem` | 课件上的右键菜单 | +| **通用·右键菜单** | `BoardDisplayMenu` | `BoardDisplayMenuItem` | 课件上的右键菜单(教学过程) | +| **元素·右键菜单** | `ElementEditMenu` / `ElementDisplayMenu` | `ElementEditMenuItem` | 板书元素的右键菜单 | +| **顶部工具栏** | `HeadToolBar` / `ToolBar` / `FunctionBar` | `HeadToolBarItem` | 白板顶部的工具栏 | +| **备课·标题栏区域** | `AllTitleBar` / `BrowserTitleBar` / `CloudTitleBar` | `ExtendedTitleBarItem` | 备课时页面顶部标题栏 | +| **当前标签页·左下角菜单** | `TabUniqueApplicationMenu` | `ShellApplicationMenuItem` | 当前标签页的汉堡菜单 | +| **全局·左下角菜单** | `TabGlobalApplicationMenu` | `ApplicationMenuItem` | 所有标签页的汉堡菜单 | +| **多板代理** | `MultiBoardProxyToolBar` | `MultiBoardProxyToolBarItem` | 多板代理的工具栏 | + +### 5. 常见问题与建议 + +#### Q: `ApplicationMenu` 和 `ExtendedTitleBar` 常量在哪里? +A: 它们**不存在**。实际使用对应的具体常量替代。 + +#### Q: 为什么命名不统一? +A: 这是 `EasiNote.Api.dll` 的真实结构,反映了系统设计的实际用途。统一修改会破坏插件兼容性。 + +#### Q: 如何确定正确的基类? +A: 每个常量对应特定的 UI 项类型,这是 SDK 中定义的继承关系。 + +#### Q: `TabUniqueApplicationMenu` 和 `TabGlobalApplicationMenu` 的区别? +A: `TabUniqueApplicationMenu` = 当前标签页的左下角菜单,`TabGlobalApplicationMenu` = 所有标签页共享的左下角菜单。 + +#### Q: 如何避免菜单冲突? +A: 使用独有的 `SortHint` 值,和 `Predicate` 过滤条件。保证一个常量对应一个菜单项。 + +## 构建与发布流程 + +### 自动化构建脚本 + +**文件**:`scripts/build-release.ps1` + +该脚本执行完整的构建 → 安装 → 测试 → 发布流程,确保每次构建都能正常运行。 + +### 手动构建流程 + +1. **调试构建** (开发阶段) +```bash +dotnet build Better-EN5/Better-EN5.csproj -c Debug +``` + +2. **发布构建** (发布阶段) +```bash +dotnet build Better-EN5/Better-EN5.csproj -c Release +``` + +3. **生成文件** (发布目录) +``` +Better-EN5/bin/Release/ +├── Better-EN5.dll # 主插件 DLL +├── BetterSeewoMainWindow.exe.config # 配置文件 +├── ... (所有必需的依赖 DLL) +└── BetterSeewoMainWindow.xaml # 主界面资源 +``` + +### 发布到 GitHub Tags + +```bash +# 构建发布版本 +cdotnet build . -c Release + +# 压缩生成的文件 +cd Better-EN5/bin/Release +cd .. && cd .. +7z a -tzip "Better-Seewo 增强插件.1.1.0.exe" "Better-EN5/bin/Release/*" +7z a -tzip "Better-Seewo 增强插件.1.1.0.zip" "Better-EN5/bin/Release/*" "*.cs" "*.md" + +# 上传到 Tags +tgit tag -a v1.1.0 -m "版本 1.1.0" +git push origin v1.1.0 +git push origin main +``` + +## 许可证 + +本项目仅供 **学习交流** 使用。 + +## 致谢 + +- 希沃白板 5 官方 SDK +- dotnetCampus.EasiPlugin.Sdk (dotnetCampus.EasiPlugins.EasiPlugin) +- 所有朋友对本项目的支持和反馈 + +## 更新记录 + +### v1.1.0 (2025-06-24) +- 基于完整逆向工程重新构建 +- 修复所有常量名称和继承关系 +- 重新设计项目结构和文档 +- 合并所有增强功能 + +### 以前版本 +- ... (留空,以便未来版本追溯) + +## 常见问题 + +### 1. 为什么所有菜单入口都在顶部工具栏? +**答案**:实际上,核心功能已经在 `HeadToolBar`(顶部工具栏)和 `BoardEditMenu`(备课模式右键菜单)提供了。 `ApplicationMenu` 和 `ExtendedTitleBar` 是 **不存在** 的概念,需要使用对应的具体常量替代(`TabUniqueApplicationMenu` / `TabGlobalApplicationMenu` 和 `BrowserTitleBar` / `CloudTitleBar` / `AllTitleBar`)。如果需要添加到汉堡菜单中,可以使用对应的常量进行注册。 + +### 2. `BoardEditMenu` 与 `HeadToolBar` 的区别? +**答案**: +- `BoardEditMenu` = 备课模式·右键菜单 (课件图标右键) +- `HeadToolBar` = 通用·顶部工具栏 (白板顶部的按钮) + +### 3. 多语言支持如何工作? +**答案**:每个菜单项都自动支持多语言。只需注册时提供对应语言的文本,系统会自动生成正确的 Key (Lang.{前缀}.{类名}),使用语言资源时直接引用即可。 + +### 4. 为什么要使用 `.NET 6.0` 和 `net6.0-windows` 框架? +**答案**:这是希沃白板 5 插件开发的官方推荐框架,支持 WPF + WinForms,能够完整支持所有菜单注册机制。 + +## 许可证 + +本项目仅供 **学习交流** 使用。 + +## 支持与反馈 + +如果您在使用过程中遇到任何问题,或有任何改进建议,请随时提交 issues。恕不处理 pull requests。 + +--- + +*本文档基于对 `EasiNote.Api.dll` 的完全逆向工程成果生成。所有常量和继承关系均已验证。 + diff --git a/README.md b/README.md deleted file mode 100644 index 4a7fa43..0000000 --- a/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# Better-Seewo - -希沃白板 5 功能增强插件套件,为希沃白板提供墨迹管理、文件转换增强、触摸检测修复、大屏模式支持和专业版激活等功能。 - -## 项目结构 - -``` -Better-Seewo/ -├── Better-EN5/ # EN5 增强插件(核心模块) -│ ├── Services/ # 服务层(墨迹、转换、触摸修复、激活) -│ ├── UI/ # 界面组件(Better-Seewo 主窗口、模块) -│ ├── Program.cs # 插件入口 -│ └── manifest.coin # 插件元数据清单 -├── install.ps1 # 安装脚本 -├── Better-Seewo.sln # 解决方案文件 -└── README.md -``` - -## 功能 - -### Better-Seewo 主界面 -横版布局,左栏(1/4)为 Better-EN5 模块,右栏(3/4)为待开发模块占位区。 -采用 Fluent 设计风格,圆角窗口,平滑动画。 - -### 墨迹管理(InkService) -- 通过反射调用希沃白板 Remark API 实现墨迹导出/导入 -- 兼容希沃白板 5.2.x 版本 - -### 文件转换(ConversionService) -- PPT ↔ ENBX 互转 -- 调用 `EasiNote.OfficeDocumentConverter.exe` 独立进程 - -### 触摸修复(TouchFixService) -- 注册表配置(HKCU 级) -- 配置文件补丁(IWBConfig.json、TouchConfig.ini) - -### 大屏模式支持(ActivationService) -- 非触摸大屏的 IWB 模式强制启用 -- 跳过大屏触摸检测 -- 配置文件修补 + 注册表配置 -- 创建大屏模式快捷方式 - -### 专业版激活(ActivationService) -- 激活码验证与注册 -- 专业版注册表写入 -- 一键启动 BEN5 注册补丁安装程序 - -## 菜单位置 - -- **白板模式(授课模式)**:左下角菜单(ApplicationMenu)→ Better-Seewo、导出墨迹 -- **备课模式**:文件下拉栏(ApplicationMenu)→ Better-Seewo -- **备课模式**:标题栏区域(ExtendedTitleBar)→ Better-Seewo -- **工具栏**(通用):顶部工具栏按钮 → 导入墨迹 - -## 环境要求 - -- .NET 6.0 SDK -- 希沃白板 5(5.2.2.653 ~ 5.3.0.0) - -## 构建 - -```bash -dotnet build Better-EN5/Better-EN5.csproj -c Release -``` - -构建后生成: -- `bin/Release/Better-Seewo 增强插件.{version}.exe` — 独立安装程序 - -## 安装 - -### 方式一:安装程序 -双击 `Better-Seewo 增强插件.{version}.exe`,按向导完成安装。 - -### 方式二:手动部署 -将 `Better-EN5\bin\Release\net6.0-windows\` 目录下所有文件连同 `manifest.coin` 复制到: -``` -%APPDATA%\Seewo\EasiNote5\Extensions\Better-EN5\{version}\ -``` - -## 使用方法 - -1. **重启希沃白板 5** -2. 在白板模式左下角菜单或备课模式文件栏中找到 **Better-Seewo** -3. 打开主界面,使用左栏的 Better-EN5 功能模块 - -## 技术要点 - -- 插件 SDK 基于 `dotnetCampus.EasiPlugin.Sdk`(v2.1.1-alpha.3) -- 目标框架 `net6.0-windows`(WPF + WinForms) -- 墨迹 API 通过反射调用(避免编译时硬依赖) -- 转换服务通过外部进程实现 -- 菜单注册在 ApplicationMenu / ExtendedTitleBar / HeadToolBar - -## 许可证 - -本项目仅供学习交流使用。 diff --git a/check_purposes.csx b/check_purposes.csx new file mode 100644 index 0000000..ab597ee --- /dev/null +++ b/check_purposes.csx @@ -0,0 +1,26 @@ +using System; +using System.Reflection; +class Program { + static void Main() { + var asm = Assembly.LoadFrom(@"C:\Program Files (x86)\Seewo\EasiNote5\EasiNote5_5.2.4.9855\Main\EasiNote.Api.dll"); + var t = asm.GetType("Cvte.EasiNote.UIItemPurposes"); + if (t == null) t = asm.GetType("EasiNote.Api.UIItemPurposes"); + if (t == null) t = asm.GetType("UIItemPurposes"); + if (t != null) { + Console.WriteLine("Found: " + t.FullName); + foreach (var f in t.GetFields(BindingFlags.Public | BindingFlags.Static)) { + Console.WriteLine($" {f.Name} = {f.GetValue(null)}"); + } + } else { + Console.WriteLine("UIItemPurposes not found directly, searching..."); + foreach (var tt in asm.GetTypes()) { + if (tt.Name.Contains("Purposes") || tt.Name.Contains("Purpose")) { + Console.WriteLine(" " + tt.FullName); + foreach (var f in tt.GetFields(BindingFlags.Public | BindingFlags.Static)) { + Console.WriteLine($" {f.Name} = {f.GetValue(null)}"); + } + } + } + } + } +}