add:插件系统
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Controls;
|
||||
using InkCanvasForClass.PluginSdk;
|
||||
|
||||
namespace InkCanvasForClass.PluginHost
|
||||
{
|
||||
/// <summary>
|
||||
/// 收集插件登记的菜单 / 工具栏 / 设置页,供宿主窗口在启动后统一挂载。
|
||||
/// </summary>
|
||||
public sealed class CollectingPluginRegistry : IPluginRegistry
|
||||
{
|
||||
private string _currentPluginId = "";
|
||||
|
||||
public string CurrentPluginId => _currentPluginId;
|
||||
|
||||
public ObservableCollection<MenuItemRegistration> MenuItems { get; } =
|
||||
new ObservableCollection<MenuItemRegistration>();
|
||||
|
||||
public ObservableCollection<ToolbarButtonRegistration> ToolbarButtons { get; } =
|
||||
new ObservableCollection<ToolbarButtonRegistration>();
|
||||
|
||||
public ObservableCollection<SettingsPageRegistration> SettingsPages { get; } =
|
||||
new ObservableCollection<SettingsPageRegistration>();
|
||||
|
||||
public void SetCurrentPluginId(string pluginId)
|
||||
{
|
||||
_currentPluginId = pluginId ?? "";
|
||||
}
|
||||
|
||||
public void RegisterMenuItem(string groupKey, MenuItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
MenuItems.Add(new MenuItemRegistration(_currentPluginId, groupKey ?? "", item));
|
||||
}
|
||||
|
||||
public void RegisterToolbarButton(Button button)
|
||||
{
|
||||
if (button == null) return;
|
||||
ToolbarButtons.Add(new ToolbarButtonRegistration(_currentPluginId, button));
|
||||
}
|
||||
|
||||
public void RegisterSettingsPage(string pageId, string displayName, Func<UserControl> createView)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pageId) || createView == null) return;
|
||||
SettingsPages.Add(new SettingsPageRegistration(
|
||||
_currentPluginId,
|
||||
pageId,
|
||||
displayName ?? pageId,
|
||||
createView));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
MenuItems.Clear();
|
||||
ToolbarButtons.Clear();
|
||||
SettingsPages.Clear();
|
||||
_currentPluginId = "";
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MenuItemRegistration
|
||||
{
|
||||
public MenuItemRegistration(string pluginId, string groupKey, MenuItem item)
|
||||
{
|
||||
PluginId = pluginId ?? "";
|
||||
GroupKey = groupKey ?? "";
|
||||
Item = item ?? throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
public string PluginId { get; }
|
||||
public string GroupKey { get; }
|
||||
public MenuItem Item { get; }
|
||||
}
|
||||
|
||||
public sealed class ToolbarButtonRegistration
|
||||
{
|
||||
public ToolbarButtonRegistration(string pluginId, Button button)
|
||||
{
|
||||
PluginId = pluginId ?? "";
|
||||
Button = button ?? throw new ArgumentNullException(nameof(button));
|
||||
}
|
||||
|
||||
public string PluginId { get; }
|
||||
public Button Button { get; }
|
||||
}
|
||||
|
||||
public sealed class SettingsPageRegistration
|
||||
{
|
||||
public SettingsPageRegistration(string pluginId, string pageId, string displayName, Func<UserControl> createView)
|
||||
{
|
||||
PluginId = pluginId ?? "";
|
||||
PageId = pageId ?? "";
|
||||
DisplayName = displayName ?? "";
|
||||
CreateView = createView ?? throw new ArgumentNullException(nameof(createView));
|
||||
}
|
||||
|
||||
public string PluginId { get; }
|
||||
public string PageId { get; }
|
||||
public string DisplayName { get; }
|
||||
public Func<UserControl> CreateView { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<RootNamespace>InkCanvasForClass.PluginHost</RootNamespace>
|
||||
<AssemblyName>InkCanvas.PluginHost</AssemblyName>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SDK\InkCanvas.PluginSdk.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace InkCanvasForClass.PluginSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// Ink Canvas 插件接口
|
||||
/// </summary>
|
||||
public interface IInkCanvasPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// 插件唯一标识符
|
||||
/// </summary>
|
||||
string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件名称
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件描述
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件版本
|
||||
/// </summary>
|
||||
Version Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件作者
|
||||
/// </summary>
|
||||
string Author { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件主页URL
|
||||
/// </summary>
|
||||
string Homepage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件图标
|
||||
/// </summary>
|
||||
ImageSource Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件初始化
|
||||
/// </summary>
|
||||
/// <param name="context">插件上下文</param>
|
||||
void Initialize(IPluginContext context);
|
||||
|
||||
/// <summary>
|
||||
/// 插件启动
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// 插件停止
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/// <summary>
|
||||
/// 插件清理
|
||||
/// </summary>
|
||||
void Cleanup();
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件设置界面
|
||||
/// </summary>
|
||||
/// <returns>设置界面控件</returns>
|
||||
UserControl GetSettingsView();
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件菜单项
|
||||
/// </summary>
|
||||
/// <returns>菜单项列表</returns>
|
||||
IEnumerable<MenuItem> GetMenuItems();
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件工具栏按钮
|
||||
/// </summary>
|
||||
/// <returns>工具栏按钮列表</returns>
|
||||
IEnumerable<Button> GetToolbarButtons();
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件状态栏信息
|
||||
/// </summary>
|
||||
/// <returns>状态栏信息</returns>
|
||||
string GetStatusBarInfo();
|
||||
|
||||
/// <summary>
|
||||
/// 插件是否已启用
|
||||
/// </summary>
|
||||
bool IsEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件启用状态变更事件
|
||||
/// </summary>
|
||||
event EventHandler<bool> EnabledChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Ink;
|
||||
|
||||
namespace InkCanvasForClass.PluginSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// 插件上下文接口,提供对主应用程序功能的访问
|
||||
/// </summary>
|
||||
public interface IPluginContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 主窗口实例
|
||||
/// </summary>
|
||||
Window MainWindow { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前画布
|
||||
/// </summary>
|
||||
System.Windows.Controls.InkCanvas CurrentCanvas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有画布页面
|
||||
/// </summary>
|
||||
IList<System.Windows.Controls.Canvas> AllCanvasPages { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前页面索引
|
||||
/// </summary>
|
||||
int CurrentPageIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 总页面数
|
||||
/// </summary>
|
||||
int TotalPageCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 浮动工具栏
|
||||
/// </summary>
|
||||
FrameworkElement FloatingToolBar { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 左侧面板
|
||||
/// </summary>
|
||||
FrameworkElement LeftPanel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 右侧面板
|
||||
/// </summary>
|
||||
FrameworkElement RightPanel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 顶部面板
|
||||
/// </summary>
|
||||
FrameworkElement TopPanel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 底部面板
|
||||
/// </summary>
|
||||
FrameworkElement BottomPanel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前绘制模式
|
||||
/// </summary>
|
||||
int CurrentDrawingMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前墨迹宽度
|
||||
/// </summary>
|
||||
double CurrentInkWidth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前墨迹颜色
|
||||
/// </summary>
|
||||
Color CurrentInkColor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前高亮笔宽度
|
||||
/// </summary>
|
||||
double CurrentHighlighterWidth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前橡皮擦大小
|
||||
/// </summary>
|
||||
int CurrentEraserSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前橡皮擦类型
|
||||
/// </summary>
|
||||
int CurrentEraserType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前橡皮擦形状
|
||||
/// </summary>
|
||||
int CurrentEraserShape { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前墨迹透明度
|
||||
/// </summary>
|
||||
double CurrentInkAlpha { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前墨迹样式
|
||||
/// </summary>
|
||||
int CurrentInkStyle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前背景颜色
|
||||
/// </summary>
|
||||
string CurrentBackgroundColor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为深色主题
|
||||
/// </summary>
|
||||
bool IsDarkTheme { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为白板模式
|
||||
/// </summary>
|
||||
bool IsWhiteboardMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为PPT模式
|
||||
/// </summary>
|
||||
bool IsPPTMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为全屏模式
|
||||
/// </summary>
|
||||
bool IsFullScreenMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为画布模式
|
||||
/// </summary>
|
||||
bool IsCanvasMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为选择模式
|
||||
/// </summary>
|
||||
bool IsSelectionMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为橡皮擦模式
|
||||
/// </summary>
|
||||
bool IsEraserMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为形状绘制模式
|
||||
/// </summary>
|
||||
bool IsShapeDrawingMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为高亮笔模式
|
||||
/// </summary>
|
||||
bool IsHighlighterMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以撤销
|
||||
/// </summary>
|
||||
bool CanUndo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以重做
|
||||
/// </summary>
|
||||
bool CanRedo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取设置值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">设置类型</typeparam>
|
||||
/// <param name="key">设置键</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>设置值</returns>
|
||||
T GetSetting<T>(string key, T defaultValue = default(T));
|
||||
|
||||
/// <summary>
|
||||
/// 设置设置值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">设置类型</typeparam>
|
||||
/// <param name="key">设置键</param>
|
||||
/// <param name="value">设置值</param>
|
||||
void SetSetting<T>(string key, T value);
|
||||
|
||||
/// <summary>
|
||||
/// 保存设置
|
||||
/// </summary>
|
||||
void SaveSettings();
|
||||
|
||||
/// <summary>
|
||||
/// 加载设置
|
||||
/// </summary>
|
||||
void LoadSettings();
|
||||
|
||||
/// <summary>
|
||||
/// 重置设置
|
||||
/// </summary>
|
||||
void ResetSettings();
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有插件
|
||||
/// </summary>
|
||||
/// <returns>插件列表</returns>
|
||||
IList<IInkCanvasPlugin> GetAllPlugins();
|
||||
|
||||
/// <summary>
|
||||
/// 根据名称获取插件
|
||||
/// </summary>
|
||||
/// <param name="pluginName">插件名称</param>
|
||||
/// <returns>插件实例</returns>
|
||||
IInkCanvasPlugin GetPlugin(string pluginName);
|
||||
|
||||
/// <summary>
|
||||
/// 启用插件
|
||||
/// </summary>
|
||||
/// <param name="pluginName">插件名称</param>
|
||||
void EnablePlugin(string pluginName);
|
||||
|
||||
/// <summary>
|
||||
/// 禁用插件
|
||||
/// </summary>
|
||||
/// <param name="pluginName">插件名称</param>
|
||||
void DisablePlugin(string pluginName);
|
||||
|
||||
/// <summary>
|
||||
/// 卸载插件
|
||||
/// </summary>
|
||||
/// <param name="pluginName">插件名称</param>
|
||||
void UnloadPlugin(string pluginName);
|
||||
|
||||
/// <summary>
|
||||
/// 显示设置窗口
|
||||
/// </summary>
|
||||
void ShowSettingsWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏设置窗口
|
||||
/// </summary>
|
||||
void HideSettingsWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 显示插件设置窗口
|
||||
/// </summary>
|
||||
void ShowPluginSettingsWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏插件设置窗口
|
||||
/// </summary>
|
||||
void HidePluginSettingsWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 显示帮助窗口
|
||||
/// </summary>
|
||||
void ShowHelpWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏帮助窗口
|
||||
/// </summary>
|
||||
void HideHelpWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 显示关于窗口
|
||||
/// </summary>
|
||||
void ShowAboutWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏关于窗口
|
||||
/// </summary>
|
||||
void HideAboutWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 显示通知
|
||||
/// </summary>
|
||||
/// <param name="message">消息内容</param>
|
||||
/// <param name="type">通知类型</param>
|
||||
void ShowNotification(string message, NotificationType type = NotificationType.Info);
|
||||
|
||||
/// <summary>
|
||||
/// 显示确认对话框
|
||||
/// </summary>
|
||||
/// <param name="message">消息内容</param>
|
||||
/// <param name="title">标题</param>
|
||||
/// <returns>用户选择结果</returns>
|
||||
bool ShowConfirmDialog(string message, string title = "确认");
|
||||
|
||||
/// <summary>
|
||||
/// 显示输入对话框
|
||||
/// </summary>
|
||||
/// <param name="message">提示消息</param>
|
||||
/// <param name="title">标题</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>用户输入内容</returns>
|
||||
string ShowInputDialog(string message, string title = "输入", string defaultValue = "");
|
||||
|
||||
/// <summary>
|
||||
/// 设置全屏模式
|
||||
/// </summary>
|
||||
/// <param name="isFullScreen">是否全屏</param>
|
||||
void SetFullScreen(bool isFullScreen);
|
||||
|
||||
/// <summary>
|
||||
/// 设置置顶模式
|
||||
/// </summary>
|
||||
/// <param name="isTopMost">是否置顶</param>
|
||||
void SetTopMost(bool isTopMost);
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口可见性
|
||||
/// </summary>
|
||||
/// <param name="isVisible">是否可见</param>
|
||||
void SetWindowVisibility(bool isVisible);
|
||||
|
||||
/// <summary>
|
||||
/// 最小化窗口
|
||||
/// </summary>
|
||||
void MinimizeWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 最大化窗口
|
||||
/// </summary>
|
||||
void MaximizeWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 还原窗口
|
||||
/// </summary>
|
||||
void RestoreWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 关闭窗口
|
||||
/// </summary>
|
||||
void CloseWindow();
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口位置
|
||||
/// </summary>
|
||||
/// <param name="x">X坐标</param>
|
||||
/// <param name="y">Y坐标</param>
|
||||
void SetWindowPosition(double x, double y);
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗口大小
|
||||
/// </summary>
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
void SetWindowSize(double width, double height);
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口位置
|
||||
/// </summary>
|
||||
/// <returns>窗口位置</returns>
|
||||
(double x, double y) GetWindowPosition();
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口大小
|
||||
/// </summary>
|
||||
/// <returns>窗口大小</returns>
|
||||
(double width, double height) GetWindowSize();
|
||||
|
||||
/// <summary>
|
||||
/// 清除当前画布
|
||||
/// </summary>
|
||||
void ClearCanvas();
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有画布
|
||||
/// </summary>
|
||||
void ClearAllCanvases();
|
||||
|
||||
/// <summary>
|
||||
/// 添加新页面
|
||||
/// </summary>
|
||||
void AddNewPage();
|
||||
|
||||
/// <summary>
|
||||
/// 删除当前页面
|
||||
/// </summary>
|
||||
void DeleteCurrentPage();
|
||||
|
||||
/// <summary>
|
||||
/// 切换到指定页面
|
||||
/// </summary>
|
||||
/// <param name="pageIndex">页面索引</param>
|
||||
void SwitchToPage(int pageIndex);
|
||||
|
||||
/// <summary>
|
||||
/// 下一页
|
||||
/// </summary>
|
||||
void NextPage();
|
||||
|
||||
/// <summary>
|
||||
/// 上一页
|
||||
/// </summary>
|
||||
void PreviousPage();
|
||||
|
||||
/// <summary>
|
||||
/// 设置绘制模式
|
||||
/// </summary>
|
||||
/// <param name="mode">绘制模式</param>
|
||||
void SetDrawingMode(int mode);
|
||||
|
||||
/// <summary>
|
||||
/// 设置墨迹宽度
|
||||
/// </summary>
|
||||
/// <param name="width">宽度</param>
|
||||
void SetInkWidth(double width);
|
||||
|
||||
/// <summary>
|
||||
/// 设置墨迹颜色
|
||||
/// </summary>
|
||||
/// <param name="color">颜色</param>
|
||||
void SetInkColor(Color color);
|
||||
|
||||
/// <summary>
|
||||
/// 设置高亮笔宽度
|
||||
/// </summary>
|
||||
/// <param name="width">宽度</param>
|
||||
void SetHighlighterWidth(double width);
|
||||
|
||||
/// <summary>
|
||||
/// 设置橡皮擦大小
|
||||
/// </summary>
|
||||
/// <param name="size">大小</param>
|
||||
void SetEraserSize(int size);
|
||||
|
||||
/// <summary>
|
||||
/// 设置橡皮擦类型
|
||||
/// </summary>
|
||||
/// <param name="type">类型</param>
|
||||
void SetEraserType(int type);
|
||||
|
||||
/// <summary>
|
||||
/// 设置橡皮擦形状
|
||||
/// </summary>
|
||||
/// <param name="shape">形状</param>
|
||||
void SetEraserShape(int shape);
|
||||
|
||||
/// <summary>
|
||||
/// 设置墨迹透明度
|
||||
/// </summary>
|
||||
/// <param name="alpha">透明度</param>
|
||||
void SetInkAlpha(double alpha);
|
||||
|
||||
/// <summary>
|
||||
/// 设置墨迹样式
|
||||
/// </summary>
|
||||
/// <param name="style">样式</param>
|
||||
void SetInkStyle(int style);
|
||||
|
||||
/// <summary>
|
||||
/// 设置背景颜色
|
||||
/// </summary>
|
||||
/// <param name="color">颜色</param>
|
||||
void SetBackgroundColor(string color);
|
||||
|
||||
/// <summary>
|
||||
/// 保存画布
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
void SaveCanvas(string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// 加载画布
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
void LoadCanvas(string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// 导出为图片
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
/// <param name="format">格式</param>
|
||||
void ExportAsImage(string filePath, string format);
|
||||
|
||||
/// <summary>
|
||||
/// 导出为PDF
|
||||
/// </summary>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
void ExportAsPDF(string filePath);
|
||||
|
||||
/// <summary>
|
||||
/// 撤销操作
|
||||
/// </summary>
|
||||
void Undo();
|
||||
|
||||
/// <summary>
|
||||
/// 重做操作
|
||||
/// </summary>
|
||||
void Redo();
|
||||
|
||||
/// <summary>
|
||||
/// 全选
|
||||
/// </summary>
|
||||
void SelectAll();
|
||||
|
||||
/// <summary>
|
||||
/// 取消选择
|
||||
/// </summary>
|
||||
void DeselectAll();
|
||||
|
||||
/// <summary>
|
||||
/// 删除选中项
|
||||
/// </summary>
|
||||
void DeleteSelected();
|
||||
|
||||
/// <summary>
|
||||
/// 复制选中项
|
||||
/// </summary>
|
||||
void CopySelected();
|
||||
|
||||
/// <summary>
|
||||
/// 剪切选中项
|
||||
/// </summary>
|
||||
void CutSelected();
|
||||
|
||||
/// <summary>
|
||||
/// 粘贴
|
||||
/// </summary>
|
||||
void Paste();
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件处理器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="handler">事件处理器</param>
|
||||
void RegisterEventHandler(string eventName, EventHandler handler);
|
||||
|
||||
/// <summary>
|
||||
/// 注销事件处理器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="handler">事件处理器</param>
|
||||
void UnregisterEventHandler(string eventName, EventHandler handler);
|
||||
|
||||
/// <summary>
|
||||
/// 触发事件
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="sender">事件发送者</param>
|
||||
/// <param name="args">事件参数</param>
|
||||
void TriggerEvent(string eventName, object sender, EventArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// 重启应用程序
|
||||
/// </summary>
|
||||
void RestartApplication();
|
||||
|
||||
/// <summary>
|
||||
/// 退出应用程序
|
||||
/// </summary>
|
||||
void ExitApplication();
|
||||
|
||||
/// <summary>
|
||||
/// 检查更新
|
||||
/// </summary>
|
||||
void CheckForUpdates();
|
||||
|
||||
/// <summary>
|
||||
/// 打开帮助文档
|
||||
/// </summary>
|
||||
void OpenHelpDocument();
|
||||
|
||||
/// <summary>
|
||||
/// 打开关于页面
|
||||
/// </summary>
|
||||
void OpenAboutPage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace InkCanvasForClass.PluginSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// 方案 B:不依赖 Microsoft.Extensions.DependencyInjection 的轻量扩展注册表。
|
||||
/// 宿主在适当时机将登记项挂到菜单 / 工具栏 / 设置 UI。
|
||||
/// </summary>
|
||||
public interface IPluginRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前正在执行注册的插件目录 Id(由宿主在加载每个插件前设置)。
|
||||
/// </summary>
|
||||
string CurrentPluginId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 注册主菜单或上下文菜单中的项;<paramref name="groupKey"/> 由宿主解释(如 "Main.Plugins")。
|
||||
/// </summary>
|
||||
void RegisterMenuItem(string groupKey, MenuItem item);
|
||||
|
||||
/// <summary>
|
||||
/// 注册工具栏按钮。
|
||||
/// </summary>
|
||||
void RegisterToolbarButton(Button button);
|
||||
|
||||
/// <summary>
|
||||
/// 注册设置页;<paramref name="createView"/> 在打开设置时惰性创建。
|
||||
/// </summary>
|
||||
void RegisterSettingsPage(string pageId, string displayName, Func<UserControl> createView);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<RootNamespace>InkCanvasForClass.PluginSdk</RootNamespace>
|
||||
<UseWPF>true</UseWPF>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>InkCanvas.PluginSdk</PackageId>
|
||||
<PackageVersion>1.0.0</PackageVersion>
|
||||
<Authors>Ink Canvas Team</Authors>
|
||||
<Company>Ink Canvas</Company>
|
||||
<Product>Ink Canvas Plugin SDK</Product>
|
||||
<Description>SDK for developing Ink Canvas plugins - 墨迹画布插件开发SDK</Description>
|
||||
<PackageProjectUrl>https://github.com/your-org/ink-canvas</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/your-org/ink-canvas</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageTags>ink;canvas;plugin;sdk;wpf;drawing</PackageTags>
|
||||
<Copyright>Copyright © 2025</Copyright>
|
||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0.0</FileVersion>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace InkCanvasForClass.PluginSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// Ink Canvas 插件基类
|
||||
/// 提供插件的基本实现
|
||||
/// </summary>
|
||||
public abstract class InkCanvasPluginBase : IInkCanvasPlugin
|
||||
{
|
||||
private bool _isEnabled;
|
||||
private IPluginContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 插件唯一标识符
|
||||
/// </summary>
|
||||
public abstract string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件名称
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件描述
|
||||
/// </summary>
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件版本
|
||||
/// </summary>
|
||||
public abstract Version Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件作者
|
||||
/// </summary>
|
||||
public abstract string Author { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插件主页URL
|
||||
/// </summary>
|
||||
public virtual string Homepage => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 插件图标
|
||||
/// </summary>
|
||||
public virtual ImageSource Icon => null;
|
||||
|
||||
/// <summary>
|
||||
/// 插件是否已启用
|
||||
/// </summary>
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled != value)
|
||||
{
|
||||
_isEnabled = value;
|
||||
OnEnabledChanged(value);
|
||||
EnabledChanged?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件启用状态变更事件
|
||||
/// </summary>
|
||||
public event EventHandler<bool> EnabledChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 插件上下文
|
||||
/// </summary>
|
||||
protected IPluginContext Context => _context;
|
||||
|
||||
/// <summary>
|
||||
/// 插件初始化
|
||||
/// </summary>
|
||||
/// <param name="context">插件上下文</param>
|
||||
public virtual void Initialize(IPluginContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 方案 B:在 <see cref="Initialize"/> 之后由宿主调用,用于向 <see cref="IPluginRegistry"/> 登记菜单、工具栏、设置页等。
|
||||
/// </summary>
|
||||
/// <param name="registry">宿主提供的注册表</param>
|
||||
public virtual void RegisterExtensions(IPluginRegistry registry)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件启动
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
{
|
||||
// 默认实现为空
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件停止
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
{
|
||||
// 默认实现为空
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件清理
|
||||
/// </summary>
|
||||
public virtual void Cleanup()
|
||||
{
|
||||
// 默认实现为空
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件设置界面
|
||||
/// </summary>
|
||||
/// <returns>设置界面控件</returns>
|
||||
public virtual UserControl GetSettingsView()
|
||||
{
|
||||
return new UserControl();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件菜单项
|
||||
/// </summary>
|
||||
/// <returns>菜单项列表</returns>
|
||||
public virtual IEnumerable<MenuItem> GetMenuItems()
|
||||
{
|
||||
return new List<MenuItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件工具栏按钮
|
||||
/// </summary>
|
||||
/// <returns>工具栏按钮列表</returns>
|
||||
public virtual IEnumerable<Button> GetToolbarButtons()
|
||||
{
|
||||
return new List<Button>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取插件状态栏信息
|
||||
/// </summary>
|
||||
/// <returns>状态栏信息</returns>
|
||||
public virtual string GetStatusBarInfo()
|
||||
{
|
||||
return $"{Name} v{Version} - {(IsEnabled ? "已启用" : "已禁用")}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用状态变更时的处理
|
||||
/// </summary>
|
||||
/// <param name="isEnabled">是否启用</param>
|
||||
protected virtual void OnEnabledChanged(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示通知
|
||||
/// </summary>
|
||||
/// <param name="message">消息内容</param>
|
||||
/// <param name="type">通知类型</param>
|
||||
protected void ShowNotification(string message, NotificationType type = NotificationType.Info)
|
||||
{
|
||||
_context?.ShowNotification(message, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示确认对话框
|
||||
/// </summary>
|
||||
/// <param name="message">消息内容</param>
|
||||
/// <param name="title">标题</param>
|
||||
/// <returns>用户选择结果</returns>
|
||||
protected bool ShowConfirmDialog(string message, string title = "确认")
|
||||
{
|
||||
return _context?.ShowConfirmDialog(message, title) ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示输入对话框
|
||||
/// </summary>
|
||||
/// <param name="message">提示消息</param>
|
||||
/// <param name="title">标题</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>用户输入内容</returns>
|
||||
protected string ShowInputDialog(string message, string title = "输入", string defaultValue = "")
|
||||
{
|
||||
return _context?.ShowInputDialog(message, title, defaultValue) ?? defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设置值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">设置类型</typeparam>
|
||||
/// <param name="key">设置键</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>设置值</returns>
|
||||
protected T GetSetting<T>(string key, T defaultValue = default)
|
||||
{
|
||||
if (_context == null) return defaultValue;
|
||||
return _context.GetSetting(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置设置值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">设置类型</typeparam>
|
||||
/// <param name="key">设置键</param>
|
||||
/// <param name="value">设置值</param>
|
||||
protected void SetSetting<T>(string key, T value)
|
||||
{
|
||||
_context?.SetSetting(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存设置
|
||||
/// </summary>
|
||||
protected void SaveSettings()
|
||||
{
|
||||
_context?.SaveSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件处理器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="handler">事件处理器</param>
|
||||
protected void RegisterEventHandler(string eventName, EventHandler handler)
|
||||
{
|
||||
_context?.RegisterEventHandler(eventName, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销事件处理器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="handler">事件处理器</param>
|
||||
protected void UnregisterEventHandler(string eventName, EventHandler handler)
|
||||
{
|
||||
_context?.UnregisterEventHandler(eventName, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发事件
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="sender">事件发送者</param>
|
||||
/// <param name="args">事件参数</param>
|
||||
protected void TriggerEvent(string eventName, object sender, EventArgs args)
|
||||
{
|
||||
_context?.TriggerEvent(eventName, sender, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace InkCanvasForClass.PluginSdk
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知类型枚举
|
||||
/// </summary>
|
||||
public enum NotificationType
|
||||
{
|
||||
/// <summary>
|
||||
/// 信息
|
||||
/// </summary>
|
||||
Info,
|
||||
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// 警告
|
||||
/// </summary>
|
||||
Warning,
|
||||
|
||||
/// <summary>
|
||||
/// 错误
|
||||
/// </summary>
|
||||
Error
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
# Ink Canvas Plugin SDK
|
||||
|
||||
Ink Canvas 插件开发SDK,用于开发墨迹画布应用的插件。
|
||||
|
||||
**命名空间**:`InkCanvasForClass.PluginSdk`(避免与 WPF 控件 `System.Windows.Controls.InkCanvas` 在引用 `InkCanvas.*` 时产生歧义)。
|
||||
|
||||
## 方案 B:轻量注册表(无 Microsoft.Extensions.DependencyInjection)
|
||||
|
||||
宿主在加载每个插件、调用 `Initialize` 之后,会调用 `InkCanvasPluginBase.RegisterExtensions(IPluginRegistry registry)`。插件可在此登记菜单项、工具栏按钮、设置页工厂;宿主窗口稍后统一挂载。注册表实现类型为 `InkCanvasForClass.PluginHost.CollectingPluginRegistry`,由主程序内 `PluginManager.Instance.ExtensionRegistry` 暴露。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
dotnet add package InkCanvas.PluginSdk
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 创建插件项目
|
||||
|
||||
创建一个新的类库项目,并添加对 `InkCanvas.PluginSdk` 的引用。
|
||||
|
||||
### 2. 实现插件接口
|
||||
|
||||
```csharp
|
||||
using InkCanvas.PluginSdk;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace MyPlugin
|
||||
{
|
||||
public class MyPlugin : InkCanvasPluginBase
|
||||
{
|
||||
public override string Id => "com.example.myplugin";
|
||||
public override string Name => "我的插件";
|
||||
public override string Description => "这是一个示例插件";
|
||||
public override Version Version => new Version(1, 0, 0);
|
||||
public override string Author => "插件作者";
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
// 插件启动时的逻辑
|
||||
ShowNotification("插件已启动!", NotificationType.Success);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
// 插件停止时的逻辑
|
||||
ShowNotification("插件已停止!", NotificationType.Info);
|
||||
}
|
||||
|
||||
public override UserControl GetSettingsView()
|
||||
{
|
||||
// 返回插件设置界面
|
||||
return new MyPluginSettingsView();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 插件功能
|
||||
|
||||
#### 访问主应用程序功能
|
||||
|
||||
通过 `Context` 属性可以访问主应用程序的各种功能:
|
||||
|
||||
```csharp
|
||||
// 获取当前画布
|
||||
var canvas = Context.CurrentCanvas;
|
||||
|
||||
// 设置墨迹颜色
|
||||
Context.SetInkColor(Colors.Red);
|
||||
|
||||
// 清除画布
|
||||
Context.ClearCanvas();
|
||||
|
||||
// 显示通知
|
||||
Context.ShowNotification("操作完成!", NotificationType.Success);
|
||||
```
|
||||
|
||||
#### 创建菜单项
|
||||
|
||||
```csharp
|
||||
public override IEnumerable<MenuItem> GetMenuItems()
|
||||
{
|
||||
var menuItem = new MenuItem
|
||||
{
|
||||
Header = "我的功能",
|
||||
Icon = new Image { Source = MyIcon }
|
||||
};
|
||||
menuItem.Click += (s, e) => {
|
||||
// 处理菜单点击
|
||||
ShowNotification("菜单被点击了!");
|
||||
};
|
||||
|
||||
return new[] { menuItem };
|
||||
}
|
||||
```
|
||||
|
||||
#### 创建工具栏按钮
|
||||
|
||||
```csharp
|
||||
public override IEnumerable<Button> GetToolbarButtons()
|
||||
{
|
||||
var button = new Button
|
||||
{
|
||||
Content = "我的工具",
|
||||
ToolTip = "这是一个工具按钮"
|
||||
};
|
||||
button.Click += (s, e) => {
|
||||
// 处理按钮点击
|
||||
Context.SetInkColor(Colors.Blue);
|
||||
};
|
||||
|
||||
return new[] { button };
|
||||
}
|
||||
```
|
||||
|
||||
#### 事件处理
|
||||
|
||||
```csharp
|
||||
public override void Start()
|
||||
{
|
||||
// 注册事件处理器
|
||||
RegisterEventHandler("CanvasChanged", OnCanvasChanged);
|
||||
RegisterEventHandler("DrawingModeChanged", OnDrawingModeChanged);
|
||||
}
|
||||
|
||||
private void OnCanvasChanged(object sender, EventArgs e)
|
||||
{
|
||||
ShowNotification("画布已更改");
|
||||
}
|
||||
|
||||
private void OnDrawingModeChanged(object sender, EventArgs e)
|
||||
{
|
||||
ShowNotification($"绘制模式已更改为: {Context.CurrentDrawingMode}");
|
||||
}
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### IInkCanvasPlugin 接口
|
||||
|
||||
插件必须实现的主要接口。
|
||||
|
||||
### IPluginContext 接口
|
||||
|
||||
提供对主应用程序功能的访问。
|
||||
|
||||
### InkCanvasPluginBase 基类
|
||||
|
||||
提供插件的基本实现,建议继承此类。
|
||||
|
||||
## 示例插件
|
||||
|
||||
查看 `Examples` 文件夹中的示例插件,了解如何实现各种功能。
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using InkCanvasForClass.PluginSdk;
|
||||
|
||||
namespace InkCanvasForClass.SamplePlugins
|
||||
{
|
||||
/// <summary>
|
||||
/// 示例插件:在当前 <see cref="InkCanvas"/> 右上角叠加显示实时时钟(不拦截笔触命中)。
|
||||
/// </summary>
|
||||
public sealed class ClockOverlayPlugin : InkCanvasPluginBase
|
||||
{
|
||||
public override string Id => "inkcanvas.sample.clock-overlay";
|
||||
|
||||
public override string Name => "画布时钟示例";
|
||||
|
||||
public override string Description => "在画布右上角显示当前时间(HH:mm:ss)";
|
||||
|
||||
public override Version Version => new Version(1, 0, 0);
|
||||
|
||||
public override string Author => "ICC CE Sample";
|
||||
|
||||
private Border _host;
|
||||
private TextBlock _timeText;
|
||||
private DispatcherTimer _timer;
|
||||
private System.Windows.Controls.InkCanvas _canvas;
|
||||
private SizeChangedEventHandler _sizeHandler;
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
var mw = Context?.MainWindow;
|
||||
var canvas = Context?.CurrentCanvas as System.Windows.Controls.InkCanvas;
|
||||
if (mw == null || canvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mw.Dispatcher.Invoke(() =>
|
||||
{
|
||||
_canvas = canvas;
|
||||
_host = new Border
|
||||
{
|
||||
Background = new SolidColorBrush(Color.FromArgb(170, 32, 32, 36)),
|
||||
CornerRadius = new CornerRadius(8),
|
||||
Padding = new Thickness(12, 8, 12, 8),
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
_timeText = new TextBlock
|
||||
{
|
||||
FontSize = 24,
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = Brushes.White,
|
||||
FontFamily = new FontFamily("Segoe UI, Microsoft YaHei UI")
|
||||
};
|
||||
_host.Child = _timeText;
|
||||
Panel.SetZIndex(_host, 10050);
|
||||
|
||||
_canvas.Children.Add(_host);
|
||||
_sizeHandler = (s, e) => Reposition();
|
||||
_canvas.SizeChanged += _sizeHandler;
|
||||
Reposition();
|
||||
|
||||
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
||||
_timer.Tick += (_, __) => Tick();
|
||||
_timer.Start();
|
||||
Tick();
|
||||
});
|
||||
}
|
||||
|
||||
private void Tick()
|
||||
{
|
||||
if (_timeText != null)
|
||||
{
|
||||
_timeText.Text = DateTime.Now.ToString("HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
private void Reposition()
|
||||
{
|
||||
if (_canvas == null || _host == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_host.UpdateLayout();
|
||||
var left = Math.Max(8, _canvas.ActualWidth - _host.ActualWidth - 20);
|
||||
InkCanvas.SetLeft(_host, left);
|
||||
InkCanvas.SetTop(_host, 20);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
var mw = Context?.MainWindow;
|
||||
if (mw != null && (_canvas != null || _host != null))
|
||||
{
|
||||
mw.Dispatcher.Invoke(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Stop();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
if (_canvas != null && _sizeHandler != null)
|
||||
{
|
||||
_canvas.SizeChanged -= _sizeHandler;
|
||||
_sizeHandler = null;
|
||||
}
|
||||
|
||||
if (_canvas != null && _host != null && _canvas.Children.Contains(_host))
|
||||
{
|
||||
_canvas.Children.Remove(_host);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 避免卸载时异常影响宿主
|
||||
}
|
||||
finally
|
||||
{
|
||||
_host = null;
|
||||
_timeText = null;
|
||||
_canvas = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
base.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<RootNamespace>InkCanvasForClass.SamplePlugins</RootNamespace>
|
||||
<AssemblyName>SampleClockPlugin</AssemblyName>
|
||||
<UseWPF>true</UseWPF>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\SDK\InkCanvas.PluginSdk.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user