Initial commit: Better-Seewo EN5 plugin v1.0.1

This commit is contained in:
miao-moe
2026-06-28 01:43:01 +08:00
commit fdd3418890
22 changed files with 1309 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public class ConversionService : IConversionService
{
public async Task<string> ConvertPptxToEnbxAsync(string pptxPath)
{
if (!File.Exists(pptxPath))
throw new FileNotFoundException("PPT 文件未找到", pptxPath);
var outputPath = Path.ChangeExtension(pptxPath, ".enbx");
var converterProcess = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
"Seewo", "EasiNote5", "EasiNote5_5.2.4.9855", "Main",
"EasiNote.OfficeDocumentConverter.exe");
if (File.Exists(converterProcess))
{
var psi = new ProcessStartInfo
{
FileName = converterProcess,
Arguments = $"\"{pptxPath}\" \"{outputPath}\"",
UseShellExecute = false,
CreateNoWindow = true,
};
using var proc = Process.Start(psi);
if (proc != null)
{
await proc.WaitForExitAsync();
}
}
else
{
throw new FileNotFoundException("转换器未找到,请确认希沃白板安装完整", converterProcess);
}
return outputPath;
}
public async Task<string> ConvertEnbxToPptxAsync(string enbxPath)
{
if (!File.Exists(enbxPath))
throw new FileNotFoundException("ENBX 文件未找到", enbxPath);
var outputPath = Path.ChangeExtension(enbxPath, ".pptx");
var exporterProcess = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
"Seewo", "EasiNote5", "EasiNote5_5.2.4.9855", "Main",
"EasiNote.OfficeDocumentConverter.exe");
if (File.Exists(exporterProcess))
{
var psi = new ProcessStartInfo
{
FileName = exporterProcess,
Arguments = $"\"{enbxPath}\" \"{outputPath}\" /export",
UseShellExecute = false,
CreateNoWindow = true,
};
using var proc = Process.Start(psi);
if (proc != null)
{
await proc.WaitForExitAsync();
}
}
else
{
throw new FileNotFoundException("转换器未找到,请确认希沃白板安装完整", exporterProcess);
}
return outputPath;
}
public async Task FixConversionErrorsAsync()
{
await Task.Run(() =>
{
var en5Path = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Seewo", "EasiNote5");
if (Directory.Exists(en5Path))
{
var tempDir = Path.Combine(en5Path, "Temp", "Conversion");
if (Directory.Exists(tempDir))
{
try { Directory.Delete(tempDir, true); } catch { }
}
}
});
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public interface IConversionService
{
Task<string> ConvertPptxToEnbxAsync(string pptxPath);
Task<string> ConvertEnbxToPptxAsync(string enbxPath);
Task FixConversionErrorsAsync();
}
}

View File

@@ -0,0 +1,10 @@
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public interface IInkService
{
Task ExportInkAsync(string filePath);
Task ImportInkAsync(string filePath);
}
}

View File

@@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public interface ITouchFixService
{
Task ApplyFixAsync();
bool IsTouchWorkingCorrectly();
Task<bool> ForceTouchEnableAsync();
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public class InkService : IInkService
{
public async Task ExportInkAsync(string filePath)
{
await Task.Run(() =>
{
dynamic? board = GetENProperty("CurrentBoardApi");
if (board == null) return;
dynamic? slides = board.Slides;
if (slides == null || slides.Count == 0) return;
var inkData = new InkPackage();
foreach (var slide in slides)
{
try
{
var remarker = slide.GetType().GetMethod("GetRemarkProvider")?.Invoke(slide, null);
if (remarker != null)
{
var remarks = remarker.GetType().GetMethod("GetAllRemarks")?.Invoke(remarker, null);
if (remarks != null)
{
inkData.Slides.Add(new SlideInkData
{
SlideId = slide.Id,
Remarks = remarks
});
}
}
}
catch { }
}
var dir = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
var json = System.Text.Json.JsonSerializer.Serialize(inkData);
File.WriteAllText(filePath, json);
});
}
public async Task ImportInkAsync(string filePath)
{
await Task.Run(() =>
{
if (!File.Exists(filePath)) return;
var json = File.ReadAllText(filePath);
var inkData = System.Text.Json.JsonSerializer.Deserialize<InkPackage>(json);
if (inkData == null) return;
dynamic? board = GetENProperty("CurrentBoardApi");
if (board == null) return;
foreach (var slideData in inkData.Slides)
{
try
{
var slide = board.GetType().GetMethod("FindSlideById")?.Invoke(board, new[] { slideData.SlideId });
if (slide == null) continue;
var remarker = slide.GetType().GetMethod("GetRemarkProvider")?.Invoke(slide, null);
if (remarker != null)
{
remarker.GetType().GetMethod("LoadRemarks")?.Invoke(remarker, new[] { slideData.Remarks });
}
}
catch { }
}
});
}
private static dynamic? GetENProperty(string propertyName)
{
try
{
var enType = Type.GetType("Cvte.EasiNote.EN, Cvte.EasiUI", false);
if (enType == null)
{
var asm = typeof(Cvte.EasiNote.UIItem).Assembly;
enType = asm.GetType("Cvte.EasiNote.EN");
}
return enType?.GetProperty(propertyName)?.GetValue(null);
}
catch
{
return null;
}
}
}
public class InkPackage
{
public List<SlideInkData> Slides { get; set; } = new();
}
public class SlideInkData
{
public string SlideId { get; set; } = string.Empty;
public object Remarks { get; set; } = new();
}
}

View File

@@ -0,0 +1,185 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace BetterEN5.Services
{
public static class TouchFixService
{
private static bool _fixApplied = false;
public static async Task ApplyFixAsync()
{
if (_fixApplied) return;
try
{
await Task.Run(() =>
{
ForceIWBMode();
PatchTouchConfig();
SuppressTouchErrors();
_fixApplied = true;
});
}
catch (Exception ex)
{
Debug.WriteLine($"[Better-EN5] TouchFix failed: {ex.Message}");
}
}
public static bool IsTouchWorkingCorrectly()
{
try
{
return TryDetectIWB();
}
catch
{
return false;
}
}
public static async Task<bool> ForceTouchEnableAsync()
{
return await Task.Run(() =>
{
try
{
ForceIWBMode();
return true;
}
catch
{
return false;
}
});
}
private static bool TryDetectIWB()
{
try
{
using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Seewo\EasiNote5");
if (key != null)
{
var val = key.GetValue("ForceIWB");
if (val != null && val.ToString() == "1")
return true;
}
}
catch { }
try
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var configFile = Path.Combine(localAppData, "Seewo", "EasiNote5", "Config", "IWBConfig.json");
if (File.Exists(configFile))
{
var json = File.ReadAllText(configFile);
if (json.Contains("\"ForceIWB\": true") || json.Contains("\"ForceIWB\":true"))
return true;
}
}
catch { }
return false;
}
private static void ForceIWBMode()
{
try
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var configDir = Path.Combine(localAppData, "Seewo", "EasiNote5", "Config");
var configFile = Path.Combine(configDir, "IWBConfig.json");
if (!Directory.Exists(configDir))
Directory.CreateDirectory(configDir);
var config = new
{
ForceIWB = true,
TouchDriverType = "WindowsTouch",
SkipTouchCheck = true,
EnableMultiTouch = true,
LastFixTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
};
var json = System.Text.Json.JsonSerializer.Serialize(config, new System.Text.Json.JsonSerializerOptions
{
WriteIndented = true
});
File.WriteAllText(configFile, json);
Microsoft.Win32.Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\Seewo\EasiNote5", "ForceIWB", 1, Microsoft.Win32.RegistryValueKind.DWord);
Microsoft.Win32.Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\Seewo\EasiNote5", "SkipTouchCheck", 1, Microsoft.Win32.RegistryValueKind.DWord);
Microsoft.Win32.Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\Seewo\EasiNote5", "EnableMultiTouch", 1, Microsoft.Win32.RegistryValueKind.DWord);
}
catch { }
}
private static void PatchTouchConfig()
{
try
{
var configDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Seewo", "EasiNote5", "Config");
var cfgFile = Path.Combine(configDir, "TouchConfig.ini");
if (!Directory.Exists(configDir))
Directory.CreateDirectory(configDir);
var lines = new[]
{
"[Touch]",
"Enable=1",
"Driver=Auto",
"ForceEnable=1",
"SuppressErrors=1",
"SkipDetection=1",
"FallbackToMouse=1",
"",
"[Calibration]",
"Enabled=0",
"",
"[MultiTouch]",
"MaxPoints=10",
"EnableGesture=1",
};
File.WriteAllLines(cfgFile, lines);
}
catch { }
}
private static void SuppressTouchErrors()
{
try
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var logDir = Path.Combine(localAppData, "Seewo", "EasiNote5", "Logs", "Touch");
if (Directory.Exists(logDir))
{
foreach (var logFile in Directory.GetFiles(logDir, "*.log"))
{
try { File.Delete(logFile); } catch { }
}
}
var seewoRegPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Seewo\EasiNote5";
try
{
Microsoft.Win32.Registry.SetValue(seewoRegPath, "SkipTouchCheck", "1");
}
catch { }
}
catch { }
}
}
}