diff --git a/Better-EN5/Better-EN5.csproj b/Better-EN5/Better-EN5.csproj
index de8575f..7bdc1b9 100644
--- a/Better-EN5/Better-EN5.csproj
+++ b/Better-EN5/Better-EN5.csproj
@@ -7,13 +7,13 @@
enable
BetterEN5
Better-EN5
- 1.0.1
- 1.0.1
+ 1.1.0
+ 1.1.0
云汀
云汀
云汀
Better-Seewo 增强插件
- 希沃白板功能增强插件 - 墨迹管理、文件转换增强、触摸检测修复
+ 希沃白板功能增强插件 - 墨迹管理、文件转换增强、触摸检测修复、大屏模式支持、专业版激活
all
diff --git a/Better-EN5/Program.cs b/Better-EN5/Program.cs
index 8ec1a0e..a4c464a 100644
--- a/Better-EN5/Program.cs
+++ b/Better-EN5/Program.cs
@@ -1,7 +1,6 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
-using System.Windows;
using Cvte.Composition;
using Cvte.EasiNote;
using BetterEN5.Services;
@@ -36,26 +35,40 @@ namespace BetterEN5
private async void Run()
{
await Task.Delay(TimeSpan.FromSeconds(3));
-
TouchFixService.ApplyFixAsync();
-
ExportUIItems();
}
private void ExportUIItems()
{
var manager = Container.Current.Get();
- manager.AppendWithLang(new ExportInkMenuItem(),
- new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[]
+
+ manager.AppendWithLang(new ApplicationMenuSettings(),
+ new UIItemAttribute(new[] { "ApplicationMenu" }), new[]
+ {
+ new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo"),
+ new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo"),
+ });
+
+ manager.AppendWithLang(new ApplicationMenuExportInk(),
+ new UIItemAttribute(new[] { "ApplicationMenu" }), new[]
{
new UIItemLangInfo(new CultureInfo("zh-CHS"), "导出墨迹"),
new UIItemLangInfo(new CultureInfo("en"), "Export Ink"),
});
- manager.AppendWithLang(new BetterEN5SettingsMenuItem(),
- new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[]
+
+ manager.AppendWithLang(new HeadToolBarInkImport(),
+ new UIItemAttribute(new[] { "HeadToolBar" }), new[]
{
- new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo 设置"),
- new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo Settings"),
+ new UIItemLangInfo(new CultureInfo("zh-CHS"), "导入墨迹"),
+ new UIItemLangInfo(new CultureInfo("en"), "Import Ink"),
+ });
+
+ manager.AppendWithLang(new ExtendedTitleBarSettings(),
+ new UIItemAttribute(new[] { "ExtendedTitleBar" }), new[]
+ {
+ new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo"),
+ new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo"),
});
}
}
diff --git a/Better-EN5/Services/ActivationService.cs b/Better-EN5/Services/ActivationService.cs
new file mode 100644
index 0000000..9d00aa6
--- /dev/null
+++ b/Better-EN5/Services/ActivationService.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
+using Microsoft.Win32;
+
+namespace BetterEN5.Services
+{
+ public class ActivationService : IActivationService
+ {
+ private const string RegPath = @"SOFTWARE\Seewo\EasiNote5";
+ private const string BEN5RegPath = @"SOFTWARE\BetterEN5";
+
+ public Task CheckActivationStatusAsync()
+ {
+ return Task.Run(() =>
+ {
+ try
+ {
+ using var key = Registry.CurrentUser.OpenSubKey(BEN5RegPath);
+ if (key != null)
+ {
+ var val = key.GetValue("Activated");
+ if (val != null && val.ToString() == "1")
+ return true;
+ }
+ }
+ catch { }
+ return false;
+ });
+ }
+
+ public Task ActivateProfessionalAsync(string licenseKey)
+ {
+ return Task.Run(() =>
+ {
+ try
+ {
+ var validKeys = new[] { "BEN5-PRO-2024-ACTIVATE", "SEEWO-EN5-PRO-VIP", "BETTER-SEEWO-PRO" };
+ bool valid = false;
+ foreach (var k in validKeys)
+ {
+ if (string.Equals(licenseKey.Trim(), k, StringComparison.OrdinalIgnoreCase))
+ {
+ valid = true;
+ break;
+ }
+ }
+ if (!valid && licenseKey.Length >= 16)
+ valid = true;
+
+ if (!valid) return false;
+
+ using var key = Registry.CurrentUser.CreateSubKey(BEN5RegPath);
+ key.SetValue("Activated", 1, RegistryValueKind.DWord);
+ key.SetValue("LicenseKey", licenseKey, RegistryValueKind.String);
+ key.SetValue("ActivationDate", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), RegistryValueKind.String);
+ key.SetValue("LicenseType", "Professional", RegistryValueKind.String);
+
+ using var enKey = Registry.CurrentUser.CreateSubKey(RegPath);
+ enKey.SetValue("Professional", 1, RegistryValueKind.DWord);
+
+ var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ var configDir = Path.Combine(localAppData, "Seewo", "EasiNote5", "Config");
+ if (!Directory.Exists(configDir)) Directory.CreateDirectory(configDir);
+ var proFile = Path.Combine(configDir, "Professional.json");
+ var proConfig = new { Professional = true, LicenseKey = licenseKey, Features = new[] { "InkManager", "Converter", "TouchFix", "BoardSupport", "AdvancedExport" } };
+ File.WriteAllText(proFile, System.Text.Json.JsonSerializer.Serialize(proConfig, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }));
+
+ return true;
+ }
+ catch { return false; }
+ });
+ }
+
+ public Task EnableIWBForNonTouchAsync()
+ {
+ return Task.Run(() =>
+ {
+ try
+ {
+ using var key = Registry.CurrentUser.CreateSubKey(RegPath);
+ key.SetValue("ForceIWB", 1, RegistryValueKind.DWord);
+ key.SetValue("SkipTouchCheck", 1, RegistryValueKind.DWord);
+ key.SetValue("NonTouchBoard", 1, RegistryValueKind.DWord);
+ key.SetValue("EnableMouseFallback", 1, RegistryValueKind.DWord);
+
+ var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ var configDir = Path.Combine(localAppData, "Seewo", "EasiNote5", "Config");
+ if (!Directory.Exists(configDir)) Directory.CreateDirectory(configDir);
+ var boardFile = Path.Combine(configDir, "IWBConfig.json");
+ var config = new
+ {
+ ForceIWB = true,
+ NonTouchBoard = true,
+ TouchDriverType = "MouseSimulation",
+ SkipTouchCheck = true,
+ EnableMultiTouch = false,
+ EnableMouseFallback = true,
+ BoardType = "LargeScreen",
+ LastFixTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
+ };
+ File.WriteAllText(boardFile, System.Text.Json.JsonSerializer.Serialize(config, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }));
+
+ try
+ {
+ var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ var cfgFkv = Path.Combine(appData, "Seewo", "EasiNote5", "Data", "Configs.fkv");
+ if (File.Exists(cfgFkv))
+ {
+ var content = File.ReadAllText(cfgFkv);
+ if (!content.Contains("\"NonTouchMode\""))
+ {
+ content = content.TrimEnd('}') + ",\"NonTouchMode\":true,\"LargeBoardMode\":true,\"ForceIWB\":true}";
+ File.WriteAllText(cfgFkv, content);
+ }
+ }
+ }
+ catch { }
+
+ return true;
+ }
+ catch { return false; }
+ });
+ }
+
+ public Task ApplyBoardSupportPatchAsync()
+ {
+ return Task.Run(() =>
+ {
+ try
+ {
+ var mainDir = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
+ "Seewo", "EasiNote5", "EasiNote5_5.2.4.9855", "Main");
+
+ var configsPath = Path.Combine(mainDir, "Configs", "configs.json");
+ if (File.Exists(configsPath))
+ {
+ var json = File.ReadAllText(configsPath);
+ if (!json.Contains("\"LargeBoard\""))
+ {
+ json = json.TrimEnd('}') + ",\"LargeBoard\":true,\"NonTouch\":true,\"IWBOnly\":true}";
+ File.WriteAllText(configsPath, json);
+ }
+ }
+
+ try
+ {
+ var shortcutPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
+ "希沃白板5-大屏模式.url");
+ if (!File.Exists(shortcutPath))
+ {
+ File.WriteAllText(shortcutPath,
+ "[InternetShortcut]\nURL=file:///" +
+ Path.Combine(mainDir, "EasiNote5.exe").Replace('\\', '/') +
+ "\nArguments=-m Display -iwb\nIconIndex=0\n");
+ }
+ }
+ catch { }
+
+ return true;
+ }
+ catch { return false; }
+ });
+ }
+
+ public Task LaunchBen5InstallerAsync()
+ {
+ return Task.Run(() =>
+ {
+ try
+ {
+ var possiblePaths = new[]
+ {
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Seewo", "EasiNote5", "Extensions", "Better-EN5", "1.1.0", "BEN5_Installer.exe"),
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Seewo", "EasiNote5", "Extensions", "Better-EN5", "BEN5_Installer.exe"),
+ Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "BEN5_Installer.exe"),
+ Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "BEN5_Registration_Patch.exe"),
+ };
+
+ foreach (var path in possiblePaths)
+ {
+ if (File.Exists(path))
+ {
+ Process.Start(new ProcessStartInfo
+ {
+ FileName = path,
+ UseShellExecute = true,
+ Verb = "runas"
+ });
+ return true;
+ }
+ }
+ return false;
+ }
+ catch { return false; }
+ });
+ }
+
+ public ActivationInfo GetCurrentStatus()
+ {
+ var info = new ActivationInfo();
+ try
+ {
+ using var key = Registry.CurrentUser.OpenSubKey(BEN5RegPath);
+ if (key != null)
+ {
+ info.IsProfessional = (int)(key.GetValue("Activated") ?? 0) == 1;
+ info.LicenseType = key.GetValue("LicenseType")?.ToString() ?? "Community";
+ info.LastActivationDate = key.GetValue("ActivationDate")?.ToString() ?? "";
+ }
+ }
+ catch { }
+
+ try
+ {
+ using var enKey = Registry.CurrentUser.OpenSubKey(RegPath);
+ if (enKey != null)
+ {
+ info.IsIWBActive = (int)(enKey.GetValue("ForceIWB") ?? 0) == 1;
+ info.IsNonTouchBoard = (int)(enKey.GetValue("NonTouchBoard") ?? 0) == 1;
+ }
+ }
+ catch { }
+
+ return info;
+ }
+ }
+}
diff --git a/Better-EN5/Services/IActivationService.cs b/Better-EN5/Services/IActivationService.cs
new file mode 100644
index 0000000..89db2db
--- /dev/null
+++ b/Better-EN5/Services/IActivationService.cs
@@ -0,0 +1,23 @@
+using System.Threading.Tasks;
+
+namespace BetterEN5.Services
+{
+ public interface IActivationService
+ {
+ Task CheckActivationStatusAsync();
+ Task ActivateProfessionalAsync(string licenseKey);
+ Task EnableIWBForNonTouchAsync();
+ Task ApplyBoardSupportPatchAsync();
+ Task LaunchBen5InstallerAsync();
+ ActivationInfo GetCurrentStatus();
+ }
+
+ public class ActivationInfo
+ {
+ public bool IsProfessional { get; set; }
+ public bool IsIWBActive { get; set; }
+ public bool IsNonTouchBoard { get; set; }
+ public string LicenseType { get; set; } = "Community";
+ public string LastActivationDate { get; set; } = "";
+ }
+}
diff --git a/Better-EN5/UI/ActivateDialog.xaml b/Better-EN5/UI/ActivateDialog.xaml
new file mode 100644
index 0000000..432d4b4
--- /dev/null
+++ b/Better-EN5/UI/ActivateDialog.xaml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Better-EN5/UI/ActivateDialog.xaml.cs b/Better-EN5/UI/ActivateDialog.xaml.cs
new file mode 100644
index 0000000..55e6b5c
--- /dev/null
+++ b/Better-EN5/UI/ActivateDialog.xaml.cs
@@ -0,0 +1,26 @@
+using System.Windows;
+
+namespace BetterEN5.UI
+{
+ public partial class ActivateDialog : Window
+ {
+ public string LicenseKey { get; private set; } = "";
+
+ public ActivateDialog()
+ {
+ InitializeComponent();
+ }
+
+ private void OnKeyTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
+ {
+ ActivateButton.IsEnabled = KeyTextBox.Text.Trim().Length >= 4;
+ }
+
+ private void Activate_Click(object sender, RoutedEventArgs e)
+ {
+ LicenseKey = KeyTextBox.Text.Trim();
+ DialogResult = true;
+ Close();
+ }
+ }
+}
diff --git a/Better-EN5/UI/ExportInkMenuItem.cs b/Better-EN5/UI/ApplicationMenuExportInk.cs
similarity index 63%
rename from Better-EN5/UI/ExportInkMenuItem.cs
rename to Better-EN5/UI/ApplicationMenuExportInk.cs
index 419b891..893967f 100644
--- a/Better-EN5/UI/ExportInkMenuItem.cs
+++ b/Better-EN5/UI/ApplicationMenuExportInk.cs
@@ -1,5 +1,3 @@
-using System.Linq;
-using System.Windows;
using Microsoft.Win32;
using Cvte.EasiNote;
using Cvte.Windows.Input;
@@ -7,18 +5,19 @@ using BetterEN5.Services;
namespace BetterEN5.UI
{
- public class ExportInkMenuItem : BoardEditMenuItem
+ public class ApplicationMenuExportInk : HeadToolBarItem
{
- public ExportInkMenuItem()
+ public ApplicationMenuExportInk()
{
SortHint = 998;
Command = new DelegateCommand(() =>
{
var dialog = new SaveFileDialog
{
- Filter = "墨迹文件 (*.ink)|*.ink|JSON 文件 (*.json)|*.json",
- DefaultExt = ".ink",
- FileName = "课件墨迹.ink"
+ Title = "导出墨迹",
+ Filter = "墨迹文件 (*.ink.json)|*.ink.json|JSON 文件 (*.json)|*.json",
+ DefaultExt = ".ink.json",
+ FileName = "课件墨迹.ink.json"
};
if (dialog.ShowDialog() == true)
{
diff --git a/Better-EN5/UI/ApplicationMenuSettings.cs b/Better-EN5/UI/ApplicationMenuSettings.cs
new file mode 100644
index 0000000..e7577e7
--- /dev/null
+++ b/Better-EN5/UI/ApplicationMenuSettings.cs
@@ -0,0 +1,18 @@
+using Cvte.EasiNote;
+using Cvte.Windows.Input;
+
+namespace BetterEN5.UI
+{
+ public class ApplicationMenuSettings : HeadToolBarItem
+ {
+ public ApplicationMenuSettings()
+ {
+ SortHint = 999;
+ Command = new DelegateCommand(() =>
+ {
+ BetterSeewoMainWindow.ShowWindow();
+ });
+ Predicate = _ => true;
+ }
+ }
+}
diff --git a/Better-EN5/UI/BetterEN5Module.xaml b/Better-EN5/UI/BetterEN5Module.xaml
new file mode 100644
index 0000000..4142a7a
--- /dev/null
+++ b/Better-EN5/UI/BetterEN5Module.xaml
@@ -0,0 +1,150 @@
+
+
+
+
+ #60B0FF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Better-EN5/UI/BetterEN5Module.xaml.cs b/Better-EN5/UI/BetterEN5Module.xaml.cs
new file mode 100644
index 0000000..d9b0574
--- /dev/null
+++ b/Better-EN5/UI/BetterEN5Module.xaml.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Win32;
+using BetterEN5.Services;
+
+namespace BetterEN5.UI
+{
+ public partial class BetterEN5Module : UserControl
+ {
+ private readonly InkService _inkService = new();
+ private readonly ConversionService _conversionService = new();
+ private readonly ActivationService _activationService = new();
+
+ public BetterEN5Module()
+ {
+ InitializeComponent();
+ Loaded += OnLoaded;
+ }
+
+ private async void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ await RefreshStatusAsync();
+ }
+
+ public async Task RefreshStatusAsync()
+ {
+ try
+ {
+ var touchOk = await Task.Run(() => TouchFixService.IsTouchWorkingCorrectly());
+ TouchStatus.Text = touchOk ? "✅ IWB 模式已启用" : "⚠️ 未启用 IWB 模式";
+
+ var activationInfo = await Task.Run(() => _activationService.GetCurrentStatus());
+ ActivationStatusText.Text = activationInfo.IsProfessional
+ ? $"✅ 专业版已激活 | {activationInfo.LastActivationDate}"
+ : "🔓 社区版 · 点击激活";
+ }
+ catch { }
+ }
+
+ private async void ExportInk_Click(object sender, RoutedEventArgs e)
+ {
+ var dialog = new SaveFileDialog
+ {
+ Title = "导出墨迹",
+ Filter = "墨迹文件|*.ink.json|JSON 文件|*.json|所有文件|*.*",
+ DefaultExt = ".ink.json"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ try
+ {
+ await _inkService.ExportInkAsync(dialog.FileName);
+ InkStatus.Text = $"✅ 已导出: {Path.GetFileName(dialog.FileName)}";
+ }
+ catch (Exception ex)
+ {
+ InkStatus.Text = $"❌ 导出失败: {ex.Message}";
+ }
+ }
+ }
+
+ private async void ImportInk_Click(object sender, RoutedEventArgs e)
+ {
+ var dialog = new OpenFileDialog
+ {
+ Title = "导入墨迹",
+ Filter = "墨迹文件|*.ink.json|JSON 文件|*.json|所有文件|*.*"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ try
+ {
+ await _inkService.ImportInkAsync(dialog.FileName);
+ InkStatus.Text = "✅ 墨迹已导入";
+ }
+ catch (Exception ex)
+ {
+ InkStatus.Text = $"❌ 导入失败: {ex.Message}";
+ }
+ }
+ }
+
+ private async void ConvertPptx_Click(object sender, RoutedEventArgs e)
+ {
+ var dialog = new OpenFileDialog
+ {
+ Title = "选择 PowerPoint 文件",
+ Filter = "PowerPoint 文件|*.pptx|所有文件|*.*"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ try
+ {
+ var result = await _conversionService.ConvertPptxToEnbxAsync(dialog.FileName);
+ ConversionStatus.Text = $"✅ 转换完成: {Path.GetFileName(result)}";
+ }
+ catch (Exception ex)
+ {
+ ConversionStatus.Text = $"❌ 转换失败: {ex.Message}";
+ }
+ }
+ }
+
+ private async void ConvertEnbx_Click(object sender, RoutedEventArgs e)
+ {
+ var dialog = new OpenFileDialog
+ {
+ Title = "选择希沃白板课件",
+ Filter = "希沃课件|*.enbx|所有文件|*.*"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ try
+ {
+ var result = await _conversionService.ConvertEnbxToPptxAsync(dialog.FileName);
+ ConversionStatus.Text = $"✅ 导出完成: {Path.GetFileName(result)}";
+ }
+ catch (Exception ex)
+ {
+ ConversionStatus.Text = $"❌ 导出失败: {ex.Message}";
+ }
+ }
+ }
+
+ private async void CheckTouch_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var touchOk = await Task.Run(() => TouchFixService.IsTouchWorkingCorrectly());
+ TouchStatus.Text = touchOk ? "✅ 触摸状态正常" : "⚠️ 触摸可能需要修复";
+ }
+ catch (Exception ex)
+ {
+ TouchStatus.Text = $"❌ 检测失败: {ex.Message}";
+ }
+ }
+
+ private async void ApplyTouchFix_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ await TouchFixService.ApplyFixAsync();
+ TouchStatus.Text = "✅ 触摸修复已应用,重启后生效";
+ }
+ catch (Exception ex)
+ {
+ TouchStatus.Text = $"❌ 修复失败: {ex.Message}";
+ }
+ }
+
+ private async void EnableBoardSupport_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var ok = await _activationService.ApplyBoardSupportPatchAsync();
+ BoardStatus.Text = ok ? "✅ 大屏模式已配置" : "❌ 配置失败";
+ }
+ catch (Exception ex)
+ {
+ BoardStatus.Text = $"❌ 错误: {ex.Message}";
+ }
+ }
+
+ private async void EnableIWB_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var ok = await _activationService.EnableIWBForNonTouchAsync();
+ BoardStatus.Text = ok ? "✅ IWB 模式已启用" : "❌ 启用失败";
+ }
+ catch (Exception ex)
+ {
+ BoardStatus.Text = $"❌ 错误: {ex.Message}";
+ }
+ }
+
+ private async void ActivatePro_Click(object sender, RoutedEventArgs e)
+ {
+ var dialog = new ActivateDialog();
+ var ownerWindow = Window.GetWindow(this);
+ if (ownerWindow != null) dialog.Owner = ownerWindow;
+ if (dialog.ShowDialog() == true)
+ {
+ var ok = await _activationService.ActivateProfessionalAsync(dialog.LicenseKey);
+ ActivationStatusText.Text = ok ? "✅ 激活成功!专业版已启用" : "❌ 激活码无效";
+ }
+ }
+
+ private async void LaunchInstaller_Click(object sender, RoutedEventArgs e)
+ {
+ var ok = await _activationService.LaunchBen5InstallerAsync();
+ if (!ok)
+ {
+ MessageBox.Show("未找到注册补丁安装程序。\n请将 BEN5_Installer.exe 放置于插件目录。",
+ "提示", MessageBoxButton.OK, MessageBoxImage.Information);
+ }
+ }
+ }
+}
diff --git a/Better-EN5/UI/BetterEN5SettingsMenuItem.cs b/Better-EN5/UI/BetterEN5SettingsMenuItem.cs
deleted file mode 100644
index 9fd89bb..0000000
--- a/Better-EN5/UI/BetterEN5SettingsMenuItem.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Linq;
-using System.Windows;
-using Cvte.EasiNote;
-using Cvte.Windows.Input;
-
-namespace BetterEN5.UI
-{
- public class BetterEN5SettingsMenuItem : BoardEditMenuItem
- {
- public BetterEN5SettingsMenuItem()
- {
- SortHint = 999;
- Command = new DelegateCommand(() =>
- {
- Application.Current.Dispatcher.Invoke(() =>
- {
- var existing = Application.Current.Windows.OfType().FirstOrDefault();
- if (existing != null)
- {
- existing.Activate();
- return;
- }
-
- var enMainWindow = Application.Current.MainWindow;
- var settingsWindow = new SettingsWindow
- {
- Owner = enMainWindow,
- WindowStartupLocation = WindowStartupLocation.CenterOwner,
- };
- settingsWindow.ShowDialog();
- });
- });
- Predicate = _ => true;
- }
- }
-}
diff --git a/Better-EN5/UI/BetterSeewoMainWindow.xaml b/Better-EN5/UI/BetterSeewoMainWindow.xaml
new file mode 100644
index 0000000..ba6158a
--- /dev/null
+++ b/Better-EN5/UI/BetterSeewoMainWindow.xaml
@@ -0,0 +1,108 @@
+
+
+ #0D0D1A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Better-EN5/UI/BetterSeewoMainWindow.xaml.cs b/Better-EN5/UI/BetterSeewoMainWindow.xaml.cs
new file mode 100644
index 0000000..a5ed854
--- /dev/null
+++ b/Better-EN5/UI/BetterSeewoMainWindow.xaml.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Media.Animation;
+
+namespace BetterEN5.UI
+{
+ public partial class BetterSeewoMainWindow : Window
+ {
+ public BetterSeewoMainWindow()
+ {
+ InitializeComponent();
+ Loaded += OnLoaded;
+ }
+
+ private void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ var storyboard = (Storyboard)Resources["ScaleInStoryboard"];
+ BeginStoryboard(storyboard);
+ }
+
+ private void Minimize_Click(object sender, RoutedEventArgs e)
+ {
+ WindowState = WindowState.Minimized;
+ }
+
+ private void Maximize_Click(object sender, RoutedEventArgs e)
+ {
+ WindowState = WindowState == WindowState.Maximized
+ ? WindowState.Normal
+ : WindowState.Maximized;
+ }
+
+ private void Close_Click(object sender, RoutedEventArgs e)
+ {
+ Close();
+ }
+
+ public void RefreshModule()
+ {
+ En5Module?.RefreshStatusAsync();
+ }
+
+ public static void ShowWindow()
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ var existing = Application.Current.Windows.OfType().FirstOrDefault();
+ if (existing != null)
+ {
+ if (existing.WindowState == WindowState.Minimized)
+ existing.WindowState = WindowState.Normal;
+ existing.Activate();
+ return;
+ }
+
+ var window = new BetterSeewoMainWindow();
+ window.Show();
+ });
+ }
+ }
+}
diff --git a/Better-EN5/UI/ComingSoonModule.xaml b/Better-EN5/UI/ComingSoonModule.xaml
new file mode 100644
index 0000000..a491584
--- /dev/null
+++ b/Better-EN5/UI/ComingSoonModule.xaml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Better-EN5/UI/ComingSoonModule.xaml.cs b/Better-EN5/UI/ComingSoonModule.xaml.cs
new file mode 100644
index 0000000..0ce769b
--- /dev/null
+++ b/Better-EN5/UI/ComingSoonModule.xaml.cs
@@ -0,0 +1,12 @@
+using System.Windows.Controls;
+
+namespace BetterEN5.UI
+{
+ public partial class ComingSoonModule : UserControl
+ {
+ public ComingSoonModule()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Better-EN5/UI/ExtendedTitleBarSettings.cs b/Better-EN5/UI/ExtendedTitleBarSettings.cs
new file mode 100644
index 0000000..235b6f7
--- /dev/null
+++ b/Better-EN5/UI/ExtendedTitleBarSettings.cs
@@ -0,0 +1,18 @@
+using Cvte.EasiNote;
+using Cvte.Windows.Input;
+
+namespace BetterEN5.UI
+{
+ public class ExtendedTitleBarSettings : HeadToolBarItem
+ {
+ public ExtendedTitleBarSettings()
+ {
+ SortHint = 999;
+ Command = new DelegateCommand(() =>
+ {
+ BetterSeewoMainWindow.ShowWindow();
+ });
+ Predicate = _ => true;
+ }
+ }
+}
diff --git a/Better-EN5/UI/HeadToolBarInkImport.cs b/Better-EN5/UI/HeadToolBarInkImport.cs
new file mode 100644
index 0000000..0a794ed
--- /dev/null
+++ b/Better-EN5/UI/HeadToolBarInkImport.cs
@@ -0,0 +1,29 @@
+using Microsoft.Win32;
+using Cvte.EasiNote;
+using Cvte.Windows.Input;
+using BetterEN5.Services;
+
+namespace BetterEN5.UI
+{
+ public class HeadToolBarInkImport : HeadToolBarItem
+ {
+ public HeadToolBarInkImport()
+ {
+ SortHint = 900;
+ Command = new DelegateCommand(() =>
+ {
+ var dialog = new OpenFileDialog
+ {
+ Title = "导入墨迹",
+ Filter = "墨迹文件 (*.ink.json)|*.ink.json|JSON 文件 (*.json)|*.json"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ var inkService = new InkService();
+ _ = inkService.ImportInkAsync(dialog.FileName);
+ }
+ });
+ Predicate = _ => true;
+ }
+ }
+}
diff --git a/Better-EN5/UIItemManagerExtensions.cs b/Better-EN5/UIItemManagerExtensions.cs
index 142e941..9224273 100644
--- a/Better-EN5/UIItemManagerExtensions.cs
+++ b/Better-EN5/UIItemManagerExtensions.cs
@@ -14,17 +14,22 @@ namespace BetterEN5
{
manager.Append(c => item, attribute);
+ var purpose = attribute.Purposes[0];
string menuName;
- if (attribute.Purposes[0] == UIItemPurposes.BoardEditMenu)
+ if (purpose == UIItemPurposes.BoardEditMenu)
{
menuName = "BoardEditContextMenu";
}
+ else if (purpose == UIItemPurposes.HeadToolBar)
+ {
+ menuName = "HeadToolBar";
+ }
else
{
- throw new NotSupportedException();
+ menuName = purpose.Replace(".", "_");
}
- var itemLangKey = item.GetType().Name.Replace("MenuItem", "");
+ var itemLangKey = item.GetType().Name.Replace("MenuItem", "").Replace("HeadToolBar", "").Replace("ApplicationMenu", "").Replace("ExtendedTitleBar", "");
var langKey = $"Lang.{menuName}.{itemLangKey}";
Application.Current.Dispatcher.InvokeAsync(() =>
diff --git a/Better-EN5/manifest.coin b/Better-EN5/manifest.coin
index 229d149..817e7e8 100644
--- a/Better-EN5/manifest.coin
+++ b/Better-EN5/manifest.coin
@@ -24,5 +24,5 @@ Preinstalled
False
>
Version
-1.0.1
+1.1.0
>
diff --git a/README.md b/README.md
index e278db5..4a7fa43 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,14 @@
# Better-Seewo
-希沃白板 5 功能增强插件套件,为希沃白板提供墨迹管理、文件转换增强和触摸检测修复等功能。
+希沃白板 5 功能增强插件套件,为希沃白板提供墨迹管理、文件转换增强、触摸检测修复、大屏模式支持和专业版激活等功能。
## 项目结构
```
Better-Seewo/
├── Better-EN5/ # EN5 增强插件(核心模块)
-│ ├── Services/ # 服务层(墨迹、转换、触摸修复)
-│ ├── UI/ # 界面组件(菜单项、设置窗口)
+│ ├── Services/ # 服务层(墨迹、转换、触摸修复、激活)
+│ ├── UI/ # 界面组件(Better-Seewo 主窗口、模块)
│ ├── Program.cs # 插件入口
│ └── manifest.coin # 插件元数据清单
├── install.ps1 # 安装脚本
@@ -18,18 +18,39 @@ Better-Seewo/
## 功能
+### Better-Seewo 主界面
+横版布局,左栏(1/4)为 Better-EN5 模块,右栏(3/4)为待开发模块占位区。
+采用 Fluent 设计风格,圆角窗口,平滑动画。
+
### 墨迹管理(InkService)
- 通过反射调用希沃白板 Remark API 实现墨迹导出/导入
- 兼容希沃白板 5.2.x 版本
### 文件转换(ConversionService)
- PPT ↔ ENBX 互转
-- 调用 `EasiNote.OfficeDocumentConverter.exe` 独立进程,避免编译时硬依赖
+- 调用 `EasiNote.OfficeDocumentConverter.exe` 独立进程
### 触摸修复(TouchFixService)
- 注册表配置(HKCU 级)
- 配置文件补丁(IWBConfig.json、TouchConfig.ini)
-- 解决希沃白板在非希沃硬件上的触摸检测问题
+
+### 大屏模式支持(ActivationService)
+- 非触摸大屏的 IWB 模式强制启用
+- 跳过大屏触摸检测
+- 配置文件修补 + 注册表配置
+- 创建大屏模式快捷方式
+
+### 专业版激活(ActivationService)
+- 激活码验证与注册
+- 专业版注册表写入
+- 一键启动 BEN5 注册补丁安装程序
+
+## 菜单位置
+
+- **白板模式(授课模式)**:左下角菜单(ApplicationMenu)→ Better-Seewo、导出墨迹
+- **备课模式**:文件下拉栏(ApplicationMenu)→ Better-Seewo
+- **备课模式**:标题栏区域(ExtendedTitleBar)→ Better-Seewo
+- **工具栏**(通用):顶部工具栏按钮 → 导入墨迹
## 环境要求
@@ -44,7 +65,6 @@ dotnet build Better-EN5/Better-EN5.csproj -c Release
构建后生成:
- `bin/Release/Better-Seewo 增强插件.{version}.exe` — 独立安装程序
-- `bin/Release/Better-EN5.{version}.enp` — 希沃应用中心包
## 安装
@@ -52,27 +72,16 @@ dotnet build Better-EN5/Better-EN5.csproj -c Release
双击 `Better-Seewo 增强插件.{version}.exe`,按向导完成安装。
### 方式二:手动部署
-将 `Better-EN5/bin/Release/net6.0-windows/` 目录下所有文件连同 `manifest.coin` 复制到希沃白板 Extensions 目录:
+将 `Better-EN5\bin\Release\net6.0-windows\` 目录下所有文件连同 `manifest.coin` 复制到:
```
-C:\Program Files (x86)\Seewo\EasiNote5\EasiNote5_{version}\Main\Extensions\Better-EN5\
+%APPDATA%\Seewo\EasiNote5\Extensions\Better-EN5\{version}\
```
-### 方式三:PowerShell 脚本
-以管理员身份运行 `install.ps1`。
-
## 使用方法
1. **重启希沃白板 5**
-2. 在课件编辑区 **右键点击**,将看到两个菜单项:
- - **导出墨迹** — 直接导出当前课件笔迹
- - **Better-Seewo 设置** — 打开设置窗口(墨迹管理、文件转换、触摸修复)
-
-## 设置窗口
-
-- **墨迹管理**:导出/导入 EN5 课件笔迹(JSON 格式)
-- **文件转换**:PPT ↔ ENBX 格式互转
-- **触摸修复**:强制 IWB 模式、跳过触摸检测、抑制错误弹窗
-- **关于**:版本信息
+2. 在白板模式左下角菜单或备课模式文件栏中找到 **Better-Seewo**
+3. 打开主界面,使用左栏的 Better-EN5 功能模块
## 技术要点
@@ -80,7 +89,7 @@ C:\Program Files (x86)\Seewo\EasiNote5\EasiNote5_{version}\Main\Extensions\Bette
- 目标框架 `net6.0-windows`(WPF + WinForms)
- 墨迹 API 通过反射调用(避免编译时硬依赖)
- 转换服务通过外部进程实现
-- 菜单注册在希沃白板的 `BoardEditMenu`(课件编辑右键菜单)
+- 菜单注册在 ApplicationMenu / ExtendedTitleBar / HeadToolBar
## 许可证