Initial commit: Better-Seewo EN5 plugin v1.0.1
This commit is contained in:
22
Better-EN5/Better-EN5.csproj
Normal file
22
Better-EN5/Better-EN5.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>BetterEN5</RootNamespace>
|
||||
<AssemblyName>Better-EN5</AssemblyName>
|
||||
<Version>1.0.1</Version>
|
||||
<FileVersion>1.0.1</FileVersion>
|
||||
<Authors>云汀</Authors>
|
||||
<Author>云汀</Author>
|
||||
<Company>云汀</Company>
|
||||
<Product>Better-Seewo 增强插件</Product>
|
||||
<Description>希沃白板功能增强插件 - 墨迹管理、文件转换增强、触摸检测修复</Description>
|
||||
<UseEasiNote>all</UseEasiNote>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="dotnetCampus.EasiPlugin.Sdk" Version="2.1.1-alpha.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
11
Better-EN5/EventId.cs
Normal file
11
Better-EN5/EventId.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace BetterEN5
|
||||
{
|
||||
static class EventId
|
||||
{
|
||||
public const string OpenSettingsEvent = "BetterEN5_OpenSettings";
|
||||
public const string InkExportEvent = "BetterEN5_InkExport";
|
||||
public const string InkImportEvent = "BetterEN5_InkImport";
|
||||
public const string ConversionEvent = "BetterEN5_Conversion";
|
||||
public const string TouchFixAppliedEvent = "BetterEN5_TouchFixApplied";
|
||||
}
|
||||
}
|
||||
62
Better-EN5/Program.cs
Normal file
62
Better-EN5/Program.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Cvte.Composition;
|
||||
using Cvte.EasiNote;
|
||||
using BetterEN5.Services;
|
||||
using BetterEN5.UI;
|
||||
|
||||
namespace BetterEN5
|
||||
{
|
||||
class Program : dotnetCampus.EasiPlugins.EasiPlugin
|
||||
{
|
||||
protected override Task OnRunningAsync()
|
||||
{
|
||||
if (!EN.CommandOptions.IsCloud)
|
||||
{
|
||||
if (EN.App.IsReady)
|
||||
{
|
||||
Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
EN.App.Ready += App_Ready;
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void App_Ready(object? sender, EventArgs e)
|
||||
{
|
||||
EN.App.Ready -= App_Ready;
|
||||
Run();
|
||||
}
|
||||
|
||||
private async void Run()
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
|
||||
TouchFixService.ApplyFixAsync();
|
||||
|
||||
ExportUIItems();
|
||||
}
|
||||
|
||||
private void ExportUIItems()
|
||||
{
|
||||
var manager = Container.Current.Get<IUIItemManager>();
|
||||
manager.AppendWithLang(new ExportInkMenuItem(),
|
||||
new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[]
|
||||
{
|
||||
new UIItemLangInfo(new CultureInfo("zh-CHS"), "导出墨迹"),
|
||||
new UIItemLangInfo(new CultureInfo("en"), "Export Ink"),
|
||||
});
|
||||
manager.AppendWithLang(new BetterEN5SettingsMenuItem(),
|
||||
new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[]
|
||||
{
|
||||
new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo 设置"),
|
||||
new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo Settings"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Better-EN5/Services/ConversionService.cs
Normal file
99
Better-EN5/Services/ConversionService.cs
Normal 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 { }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Better-EN5/Services/IConversionService.cs
Normal file
11
Better-EN5/Services/IConversionService.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
10
Better-EN5/Services/IInkService.cs
Normal file
10
Better-EN5/Services/IInkService.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterEN5.Services
|
||||
{
|
||||
public interface IInkService
|
||||
{
|
||||
Task ExportInkAsync(string filePath);
|
||||
Task ImportInkAsync(string filePath);
|
||||
}
|
||||
}
|
||||
11
Better-EN5/Services/ITouchFixService.cs
Normal file
11
Better-EN5/Services/ITouchFixService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterEN5.Services
|
||||
{
|
||||
public interface ITouchFixService
|
||||
{
|
||||
Task ApplyFixAsync();
|
||||
bool IsTouchWorkingCorrectly();
|
||||
Task<bool> ForceTouchEnableAsync();
|
||||
}
|
||||
}
|
||||
111
Better-EN5/Services/InkService.cs
Normal file
111
Better-EN5/Services/InkService.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
185
Better-EN5/Services/TouchFixService.cs
Normal file
185
Better-EN5/Services/TouchFixService.cs
Normal 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 { }
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Better-EN5/UI/BetterEN5SettingsMenuItem.cs
Normal file
36
Better-EN5/UI/BetterEN5SettingsMenuItem.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
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<SettingsWindow>().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;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Better-EN5/UI/ExportInkMenuItem.cs
Normal file
32
Better-EN5/UI/ExportInkMenuItem.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Microsoft.Win32;
|
||||
using Cvte.EasiNote;
|
||||
using Cvte.Windows.Input;
|
||||
using BetterEN5.Services;
|
||||
|
||||
namespace BetterEN5.UI
|
||||
{
|
||||
public class ExportInkMenuItem : BoardEditMenuItem
|
||||
{
|
||||
public ExportInkMenuItem()
|
||||
{
|
||||
SortHint = 998;
|
||||
Command = new DelegateCommand(() =>
|
||||
{
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
Filter = "墨迹文件 (*.ink)|*.ink|JSON 文件 (*.json)|*.json",
|
||||
DefaultExt = ".ink",
|
||||
FileName = "课件墨迹.ink"
|
||||
};
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
var inkService = new InkService();
|
||||
_ = inkService.ExportInkAsync(dialog.FileName);
|
||||
}
|
||||
});
|
||||
Predicate = _ => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
168
Better-EN5/UI/SettingsWindow.xaml
Normal file
168
Better-EN5/UI/SettingsWindow.xaml
Normal file
@@ -0,0 +1,168 @@
|
||||
<Window x:Class="BetterEN5.UI.SettingsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Better-Seewo 设置"
|
||||
Height="520" Width="680"
|
||||
ResizeMode="CanResize"
|
||||
WindowStyle="SingleBorderWindow"
|
||||
FontSize="14">
|
||||
<Window.Resources>
|
||||
<Style x:Key="TabHeaderStyle" TargetType="TabItem">
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
<Setter Property="Padding" Value="16,8"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style x:Key="ActionButton" TargetType="Button">
|
||||
<Setter Property="Padding" Value="16,8"/>
|
||||
<Setter Property="Margin" Value="8"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
</Style>
|
||||
<Style x:Key="GroupBoxStyle" TargetType="GroupBox">
|
||||
<Setter Property="Margin" Value="8"/>
|
||||
<Setter Property="Padding" Value="12"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Margin="12">
|
||||
<TabControl>
|
||||
<TabItem Header="墨迹管理" Style="{StaticResource TabHeaderStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="8">
|
||||
<GroupBox Header="墨迹导出" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,12">
|
||||
将当前课件中的所有墨迹(笔迹、标注)导出为 JSON 文件,方便备份和迁移。
|
||||
</TextBlock>
|
||||
<UniformGrid Columns="2" HorizontalAlignment="Left">
|
||||
<Button Content="导出墨迹..." Style="{StaticResource ActionButton}"
|
||||
Click="ExportInk_Click"/>
|
||||
<Button Content="导入墨迹..." Style="{StaticResource ActionButton}"
|
||||
Click="ImportInk_Click"/>
|
||||
</UniformGrid>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="墨迹设置" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Name="AutoSaveInkCheckBox" Margin="4" Content="关闭课件时自动备份墨迹"/>
|
||||
<CheckBox x:Name="IncludeShapeInkCheckBox" Margin="4" Content="导出包含形状上的笔迹"/>
|
||||
<Button Content="保存设置" Style="{StaticResource ActionButton}"
|
||||
HorizontalAlignment="Left" Click="SaveInkSettings_Click"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="状态" Style="{StaticResource GroupBoxStyle}">
|
||||
<TextBlock x:Name="InkStatusText" Text="就绪" Foreground="Gray"/>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="文件转换" Style="{StaticResource TabHeaderStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="8">
|
||||
<GroupBox Header="PPT 转 ENBX" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,12">
|
||||
将 PowerPoint 文件(.pptx)转换为希沃白板课件格式(.enbx),
|
||||
保留更多原始格式和排版。
|
||||
</TextBlock>
|
||||
<Button Content="选择并转换 PPT..." Style="{StaticResource ActionButton}"
|
||||
HorizontalAlignment="Left" Click="ConvertPptx_Click"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="ENBX 转 PPT" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,12">
|
||||
将希沃白板课件(.enbx)导出为 PowerPoint 格式(.pptx)。
|
||||
</TextBlock>
|
||||
<Button Content="选择并转换 ENBX..." Style="{StaticResource ActionButton}"
|
||||
HorizontalAlignment="Left" Click="ConvertEnbx_Click"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="转换修复" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0,0,0,12">
|
||||
清除转换缓存和临时文件,修复可能的转换失败问题。
|
||||
</TextBlock>
|
||||
<UniformGrid Columns="2" HorizontalAlignment="Left">
|
||||
<Button Content="清理转换缓存" Style="{StaticResource ActionButton}"
|
||||
Click="ClearConversionCache_Click"/>
|
||||
<Button Content="强制重新注册转换器" Style="{StaticResource ActionButton}"
|
||||
Click="ReRegisterConverter_Click"/>
|
||||
</UniformGrid>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="状态" Style="{StaticResource GroupBoxStyle}">
|
||||
<TextBlock x:Name="ConversionStatusText" Text="就绪" Foreground="Gray"/>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="触摸修复" Style="{StaticResource TabHeaderStyle}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="8">
|
||||
<GroupBox Header="触摸检测状态" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="TouchStatusText" TextWrapping="Wrap" Margin="0,0,0,12">
|
||||
正在检测触摸状态...
|
||||
</TextBlock>
|
||||
<UniformGrid Columns="2" HorizontalAlignment="Left">
|
||||
<Button Content="检测触摸状态" Style="{StaticResource ActionButton}"
|
||||
Click="CheckTouch_Click"/>
|
||||
<Button Content="应用修复" Style="{StaticResource ActionButton}"
|
||||
Click="ApplyTouchFix_Click"/>
|
||||
</UniformGrid>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="修复选项" Style="{StaticResource GroupBoxStyle}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Name="ForceIWBModeCheckBox" Margin="4" Content="强制启用 IWB 模式(白板模式)" IsChecked="True"/>
|
||||
<CheckBox x:Name="SkipTouchCheckCheckBox" Margin="4" Content="跳过启动时的触摸检测" IsChecked="True"/>
|
||||
<CheckBox x:Name="SuppressTouchErrorsCheckBox" Margin="4" Content="抑制触摸相关错误提示" IsChecked="True"/>
|
||||
<CheckBox x:Name="EnableFallbackModeCheckBox" Margin="4" Content="启用鼠标回退模式(触摸失效时自动切换)" IsChecked="True"/>
|
||||
<Button Content="保存触摸设置" Style="{StaticResource ActionButton}"
|
||||
HorizontalAlignment="Left" Click="SaveTouchSettings_Click"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="说明" Style="{StaticResource GroupBoxStyle}">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
• 部分学校电脑的触摸硬件本身没有故障,但希沃白板的触摸检测逻辑存在兼容性问题。
|
||||
• 本功能通过配置注册表和配置文件,强制启用触摸支持,跳过有问题的检测步骤。
|
||||
• 如果修复后触摸仍不工作,请尝试重启希沃白板。
|
||||
• 如遇到更严重的触摸问题,可使用"还原"功能恢复默认设置。
|
||||
</TextBlock>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="关于" Style="{StaticResource TabHeaderStyle}">
|
||||
<StackPanel Margin="24" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<TextBlock Text="Better-Seewo" FontSize="24" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,8"/>
|
||||
<TextBlock Text="希沃白板功能增强插件" FontSize="16"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,4"/>
|
||||
<TextBlock x:Name="VersionText" Text="版本 1.0.0"
|
||||
HorizontalAlignment="Center" Foreground="Gray" Margin="0,0,0,24"/>
|
||||
<Separator Margin="0,0,0,16"/>
|
||||
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center">
|
||||
Better-EN5 模块提供以下增强功能:
|
||||
• 墨迹(笔迹/标注)的独立导出和导入
|
||||
• 增强的 PPT 与 ENBX 文件转换
|
||||
• 触摸检测逻辑修复与错误抑制
|
||||
项目地址:https://github.com/anomalyco/opencode
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
||||
283
Better-EN5/UI/SettingsWindow.xaml.cs
Normal file
283
Better-EN5/UI/SettingsWindow.xaml.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Microsoft.Win32;
|
||||
using Cvte.EasiNote;
|
||||
using BetterEN5.Services;
|
||||
|
||||
namespace BetterEN5.UI
|
||||
{
|
||||
public partial class SettingsWindow : Window
|
||||
{
|
||||
private readonly InkService _inkService = new();
|
||||
private readonly ConversionService _conversionService = new();
|
||||
|
||||
public SettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LoadSettings();
|
||||
await RefreshTouchStatusAsync();
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var settingsFile = Path.Combine(localAppData, "Seewo", "EasiNote5", "BetterEN5", "settings.json");
|
||||
if (File.Exists(settingsFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(settingsFile);
|
||||
var settings = System.Text.Json.JsonSerializer.Deserialize<SettingsData>(json);
|
||||
if (settings != null)
|
||||
{
|
||||
AutoSaveInkCheckBox.IsChecked = settings.AutoSaveInk;
|
||||
IncludeShapeInkCheckBox.IsChecked = settings.IncludeShapeInk;
|
||||
ForceIWBModeCheckBox.IsChecked = settings.ForceIWB;
|
||||
SkipTouchCheckCheckBox.IsChecked = settings.SkipTouchCheck;
|
||||
SuppressTouchErrorsCheckBox.IsChecked = settings.SuppressTouchErrors;
|
||||
EnableFallbackModeCheckBox.IsChecked = settings.EnableFallbackMode;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveSettings()
|
||||
{
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var dir = Path.Combine(localAppData, "Seewo", "EasiNote5", "BetterEN5");
|
||||
var settingsFile = Path.Combine(dir, "settings.json");
|
||||
|
||||
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
|
||||
|
||||
var settings = new SettingsData
|
||||
{
|
||||
AutoSaveInk = AutoSaveInkCheckBox.IsChecked ?? false,
|
||||
IncludeShapeInk = IncludeShapeInkCheckBox.IsChecked ?? false,
|
||||
ForceIWB = ForceIWBModeCheckBox.IsChecked ?? true,
|
||||
SkipTouchCheck = SkipTouchCheckCheckBox.IsChecked ?? true,
|
||||
SuppressTouchErrors = SuppressTouchErrorsCheckBox.IsChecked ?? true,
|
||||
EnableFallbackMode = EnableFallbackModeCheckBox.IsChecked ?? true,
|
||||
};
|
||||
|
||||
var json = System.Text.Json.JsonSerializer.Serialize(settings, new System.Text.Json.JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
File.WriteAllText(settingsFile, json);
|
||||
}
|
||||
|
||||
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);
|
||||
InkStatusText.Text = $"墨迹已导出至: {dialog.FileName}";
|
||||
InkStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InkStatusText.Text = $"导出失败: {ex.Message}";
|
||||
InkStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void ImportInk_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new OpenFileDialog
|
||||
{
|
||||
Title = "导入墨迹",
|
||||
Filter = "墨迹文件|*.ink.json|JSON 文件|*.json|所有文件|*.*",
|
||||
DefaultExt = ".ink.json"
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _inkService.ImportInkAsync(dialog.FileName);
|
||||
InkStatusText.Text = "墨迹已导入";
|
||||
InkStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InkStatusText.Text = $"导入失败: {ex.Message}";
|
||||
InkStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveInkSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
InkStatusText.Text = "墨迹设置已保存";
|
||||
InkStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
|
||||
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);
|
||||
ConversionStatusText.Text = $"转换完成: {result}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ConversionStatusText.Text = $"转换失败: {ex.Message}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ConversionStatusText.Text = $"导出完成: {result}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ConversionStatusText.Text = $"导出失败: {ex.Message}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void ClearConversionCache_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _conversionService.FixConversionErrorsAsync();
|
||||
ConversionStatusText.Text = "转换缓存已清理";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ConversionStatusText.Text = $"清理失败: {ex.Message}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private async void ReRegisterConverter_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var converterPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
|
||||
"Seewo", "EasiNote5", "EasiNote5_5.2.4.9855", "Main",
|
||||
"EasiNote.OfficeDocumentConverter.exe");
|
||||
|
||||
if (File.Exists(converterPath))
|
||||
{
|
||||
Process.Start(converterPath, "/register");
|
||||
await Task.Delay(1000);
|
||||
ConversionStatusText.Text = "转换器已重新注册";
|
||||
}
|
||||
else
|
||||
{
|
||||
ConversionStatusText.Text = "未找到转换器";
|
||||
}
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ConversionStatusText.Text = $"注册失败: {ex.Message}";
|
||||
ConversionStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private async void CheckTouch_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await RefreshTouchStatusAsync();
|
||||
}
|
||||
|
||||
private async void ApplyTouchFix_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await TouchFixService.ApplyFixAsync();
|
||||
TouchStatusText.Text = "触摸修复已应用,请重启希沃白板生效";
|
||||
TouchStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
SaveSettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TouchStatusText.Text = $"修复失败: {ex.Message}";
|
||||
TouchStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveTouchSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
TouchStatusText.Text = "触摸设置已保存";
|
||||
TouchStatusText.Foreground = System.Windows.Media.Brushes.Green;
|
||||
}
|
||||
|
||||
private async Task RefreshTouchStatusAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var isIwb = await Task.Run(() => TouchFixService.IsTouchWorkingCorrectly());
|
||||
TouchStatusText.Text = isIwb
|
||||
? "触摸状态: 正常 (IWB 模式已启用)"
|
||||
: "触摸状态: 非 IWB 模式 (可能存在问题)";
|
||||
TouchStatusText.Foreground = isIwb
|
||||
? System.Windows.Media.Brushes.Green
|
||||
: System.Windows.Media.Brushes.Orange;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TouchStatusText.Text = $"无法检测触摸状态: {ex.Message}";
|
||||
TouchStatusText.Foreground = System.Windows.Media.Brushes.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsData
|
||||
{
|
||||
public bool AutoSaveInk { get; set; }
|
||||
public bool IncludeShapeInk { get; set; }
|
||||
public bool ForceIWB { get; set; } = true;
|
||||
public bool SkipTouchCheck { get; set; } = true;
|
||||
public bool SuppressTouchErrors { get; set; } = true;
|
||||
public bool EnableFallbackMode { get; set; } = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Better-EN5/UIItemLangInfo.cs
Normal file
8
Better-EN5/UIItemLangInfo.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace BetterEN5
|
||||
{
|
||||
readonly record struct UIItemLangInfo(CultureInfo CultureInfo, string LangText)
|
||||
{
|
||||
}
|
||||
}
|
||||
45
Better-EN5/UIItemManagerExtensions.cs
Normal file
45
Better-EN5/UIItemManagerExtensions.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Cvte.EasiNote;
|
||||
using Cvte.Windows.Localization;
|
||||
|
||||
namespace BetterEN5
|
||||
{
|
||||
static class UIItemManagerExtensions
|
||||
{
|
||||
public static void AppendWithLang(this IUIItemManager manager, UIItem item,
|
||||
UIItemAttribute attribute, IList<UIItemLangInfo> langInfoList)
|
||||
{
|
||||
manager.Append(c => item, attribute);
|
||||
|
||||
string menuName;
|
||||
if (attribute.Purposes[0] == UIItemPurposes.BoardEditMenu)
|
||||
{
|
||||
menuName = "BoardEditContextMenu";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
var itemLangKey = item.GetType().Name.Replace("MenuItem", "");
|
||||
var langKey = $"Lang.{menuName}.{itemLangKey}";
|
||||
|
||||
Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
foreach (var langInfo in langInfoList)
|
||||
{
|
||||
Lang.Sources.Add(new DictionaryLanguageSource
|
||||
{
|
||||
[langInfo.CultureInfo] = new Dictionary<string, string>()
|
||||
{
|
||||
{ langKey, langInfo.LangText },
|
||||
},
|
||||
});
|
||||
}
|
||||
}, DispatcherPriority.Send);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Better-EN5/manifest.coin
Normal file
28
Better-EN5/manifest.coin
Normal file
@@ -0,0 +1,28 @@
|
||||
>
|
||||
Description
|
||||
希沃白板功能增强插件 - 提供墨迹管理、文件转换增强和触摸检测修复功能
|
||||
>
|
||||
Id
|
||||
BetterEN5
|
||||
>
|
||||
MaxClientVersion
|
||||
5.3.0.0
|
||||
>
|
||||
MinClientVersion
|
||||
5.2.2.653
|
||||
>
|
||||
Name
|
||||
Better-EN5 增强模块
|
||||
>
|
||||
NetEntryPoint
|
||||
Better-EN5.dll
|
||||
>
|
||||
NetFrameworkEntryPoint
|
||||
Better-EN5.dll
|
||||
>
|
||||
Preinstalled
|
||||
False
|
||||
>
|
||||
Version
|
||||
1.0.1
|
||||
>
|
||||
Reference in New Issue
Block a user