diff --git a/.gitignore b/.gitignore index 954c28b..448ee79 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ /InkCanvasForClass/bin /InkCanvasForClassX/obj /InkCanvasForClassX/bin +/InkCanvasForClassPPTVsto/obj +/InkCanvasForClassPPTVsto/bin +/PeroInstaller/obj +/PeroInstaller/bin /CvtePaintDemo/obj /CvtePaintDemo/bin /.vs diff --git a/Ink Canvas.sln b/Ink Canvas.sln index feace4c..0c55082 100644 --- a/Ink Canvas.sln +++ b/Ink Canvas.sln @@ -3,16 +3,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33530.505 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClassX", "InkCanvasForClassX\InkCanvasForClassX.csproj", "{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InkCanvasForClassX", "InkCanvasForClassX\InkCanvasForClassX.csproj", "{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InkCanvasForClass", "InkCanvasForClass\InkCanvasForClass.csproj", "{2474F5B0-6FA7-4D70-8A00-167BBB03264D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CvtePaintDemo", "CvtePaintDemo\CvtePaintDemo.csproj", "{26F0E9DD-A9DC-45D1-97B9-337C63863837}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CvtePaintDemo", "CvtePaintDemo\CvtePaintDemo.csproj", "{26F0E9DD-A9DC-45D1-97B9-337C63863837}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demos", "Demos", "{0B6F0669-8945-4AC7-923D-145BF23C38A0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Assets", "Assets", "{D31A4267-C13F-41FE-8516-3B633E3B1990}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClassPPTVsto", "InkCanvasForClassPPTVsto\InkCanvasForClassPPTVsto.csproj", "{E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PeroInstaller", "PeroInstaller\PeroInstaller.csproj", "{AB1CC983-E30D-4597-A858-05DF7DF7664C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -122,6 +126,66 @@ Global {26F0E9DD-A9DC-45D1-97B9-337C63863837}.x86 Debug|x64.Build.0 = Debug|Any CPU {26F0E9DD-A9DC-45D1-97B9-337C63863837}.x86 Debug|x86.ActiveCfg = Debug|Any CPU {26F0E9DD-A9DC-45D1-97B9-337C63863837}.x86 Debug|x86.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|ARM.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|ARM.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|ARM64.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|x64.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|x64.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Debug|x86.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|Any CPU.Build.0 = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|ARM.ActiveCfg = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|ARM.Build.0 = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|ARM64.ActiveCfg = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|ARM64.Build.0 = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|x64.ActiveCfg = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|x64.Build.0 = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|x86.ActiveCfg = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.Release|x86.Build.0 = Release|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|ARM.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|ARM64.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|x64.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|x64.Build.0 = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|x86.ActiveCfg = Debug|Any CPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7}.x86 Debug|x86.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|ARM.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|ARM64.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|x64.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|x64.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|x86.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Debug|x86.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|Any CPU.Build.0 = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|ARM.ActiveCfg = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|ARM.Build.0 = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|ARM64.ActiveCfg = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|ARM64.Build.0 = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|x64.ActiveCfg = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|x64.Build.0 = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|x86.ActiveCfg = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.Release|x86.Build.0 = Release|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|ARM.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|ARM64.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|x64.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|x64.Build.0 = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|x86.ActiveCfg = Debug|Any CPU + {AB1CC983-E30D-4597-A858-05DF7DF7664C}.x86 Debug|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/InkCanvasForClass/MainWindow.xaml b/InkCanvasForClass/MainWindow.xaml index 9a26a8d..5c00d67 100644 --- a/InkCanvasForClass/MainWindow.xaml +++ b/InkCanvasForClass/MainWindow.xaml @@ -1710,17 +1710,6 @@ IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold" Toggled="ToggleSwitchAutoKillICA_Toggled" /> - - - - - @@ -1876,7 +1865,12 @@ - + + + + + diff --git a/InkCanvasForClass/MainWindow_cs/MW_PPT.cs b/InkCanvasForClass/MainWindow_cs/MW_PPT.cs index 8fa804e..2f0a8b0 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_PPT.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_PPT.cs @@ -375,6 +375,14 @@ namespace Ink_Canvas { private void UpdatePPTBtnDisplaySettingsStatus() { + if (!Settings.PowerPointSettings.ShowPPTButton) { + LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; + RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; + LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; + RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; + return; + } + var lsp = Settings.PowerPointSettings.PPTLSButtonPosition; LeftSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, lsp*2); var rsp = Settings.PowerPointSettings.PPTRSButtonPosition; @@ -382,6 +390,7 @@ namespace Ink_Canvas { var dopt = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString(); char[] doptc = dopt.ToCharArray(); + if (doptc[0] == '2') AnimationsHelper.ShowWithFadeIn(LeftBottomPanelForPPTNavigation); else LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed; if (doptc[1] == '2') AnimationsHelper.ShowWithFadeIn(RightBottomPanelForPPTNavigation); diff --git a/InkCanvasForClass/MainWindow_cs/MW_Settings.cs b/InkCanvasForClass/MainWindow_cs/MW_Settings.cs index 0785d27..c146538 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Settings.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Settings.cs @@ -338,6 +338,7 @@ namespace Ink_Canvas { if (!isLoaded) return; Settings.PowerPointSettings.ShowPPTButton = ToggleSwitchShowPPTButton.IsOn; SaveSettingsToFile(); + if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus(); UpdatePPTBtnPreview(); } @@ -1121,19 +1122,19 @@ namespace Ink_Canvas { timerKillProcess.Stop(); } - private void ToggleSwitchAutoKillIDT_Toggled(object sender, RoutedEventArgs e) - { - if (!isLoaded) return; - Settings.Automation.IsAutoKillIDT = ToggleSwitchAutoKillIDT.IsOn; - SaveSettingsToFile(); - if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || - Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas - || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao - || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) - timerKillProcess.Start(); - else - timerKillProcess.Stop(); - } + //private void ToggleSwitchAutoKillIDT_Toggled(object sender, RoutedEventArgs e) + //{ + // if (!isLoaded) return; + // Settings.Automation.IsAutoKillIDT = ToggleSwitchAutoKillIDT.IsOn; + // SaveSettingsToFile(); + // if (Settings.Automation.IsAutoKillEasiNote || Settings.Automation.IsAutoKillPptService || + // Settings.Automation.IsAutoKillHiteAnnotation || Settings.Automation.IsAutoKillInkCanvas + // || Settings.Automation.IsAutoKillICA || Settings.Automation.IsAutoKillIDT || Settings.Automation.IsAutoKillVComYouJiao + // || Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) + // timerKillProcess.Start(); + // else + // timerKillProcess.Stop(); + //} private void ToggleSwitchSaveScreenshotsInDateFolders_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; diff --git a/InkCanvasForClass/MainWindow_cs/MW_SettingsToLoad.cs b/InkCanvasForClass/MainWindow_cs/MW_SettingsToLoad.cs index 42c3ecc..93b54bf 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_SettingsToLoad.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_SettingsToLoad.cs @@ -638,7 +638,7 @@ namespace Ink_Canvas { ToggleSwitchAutoKillICA.IsOn = Settings.Automation.IsAutoKillICA; - ToggleSwitchAutoKillIDT.IsOn = Settings.Automation.IsAutoKillIDT; + //ToggleSwitchAutoKillIDT.IsOn = Settings.Automation.IsAutoKillIDT; ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation.IsOn = Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation; diff --git a/InkCanvasForClass/MainWindow_cs/MW_Timer.cs b/InkCanvasForClass/MainWindow_cs/MW_Timer.cs index aa6f64b..e6eaa8b 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Timer.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Timer.cs @@ -121,16 +121,17 @@ namespace Ink_Canvas { if (processes.Length > 0) arg += " /IM \"Ink Canvas.exe\""; } - if (Settings.Automation.IsAutoKillIDT) { - var processes = Process.GetProcessesByName("智绘教"); - if (processes.Length > 0) arg += " /IM \"智绘教.exe\""; - } + // 移除了IDT的查殺 + //if (Settings.Automation.IsAutoKillIDT) { + // var processes = Process.GetProcessesByName("智绘教"); + // if (processes.Length > 0) arg += " /IM \"智绘教.exe\""; + //} - if (Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) { + //if (Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) { //由于希沃桌面2.0提供的桌面批注是64位应用程序,32位程序无法访问,目前暂不做精准匹配,只匹配进程名称,后面会考虑封装一套基于P/Invoke和WMI的综合进程识别方案。 - var processes = Process.GetProcessesByName("DesktopAnnotation"); - if (processes.Length > 0) arg += " /IM DesktopAnnotation.exe"; - } + // var processes = Process.GetProcessesByName("DesktopAnnotation"); + // if (processes.Length > 0) arg += " /IM DesktopAnnotation.exe"; + //} if (arg != "/F") { var p = new Process(); @@ -162,11 +163,11 @@ namespace Ink_Canvas { }); } - if (arg.Contains("智绘教")) { - Dispatcher.Invoke(() => { - ShowNotification("“智绘教”已自动关闭"); - }); - } + //if (arg.Contains("智绘教")) { + // Dispatcher.Invoke(() => { + // ShowNotification("“智绘教”已自动关闭"); + // }); + //} if (arg.Contains("VcomTeach")) { @@ -175,12 +176,12 @@ namespace Ink_Canvas { }); } - if (arg.Contains("DesktopAnnotation")) - { - Dispatcher.Invoke(() => { - ShowNotification("“DesktopAnnotation”已自动关闭"); - }); - } + //if (arg.Contains("DesktopAnnotation")) + //{ + // Dispatcher.Invoke(() => { + // ShowNotification("“DesktopAnnotation”已自动关闭"); + // }); + //} } } catch {} diff --git a/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto.csproj b/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto.csproj new file mode 100644 index 0000000..b8ebce2 --- /dev/null +++ b/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto.csproj @@ -0,0 +1,216 @@ + + + + + {BAA0C2D2-18E2-41B9-852F-F413020CAA33};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + AnyCPU + {E494CFFE-D2EC-4BAD-82D9-C92FE29616A7} + Library + false + InkCanvasForClassPPTVsto + InkCanvasForClassPPTVsto + 3 + v4.7.2 + VSTO40 + true + HomeSite + + + + False + Microsoft Visual Studio 2010 Tools for Office Runtime %28x86 and x64%29 + true + + + + + PowerPoint + + + + true + full + false + bin\Debug\ + false + $(DefineConstants);DEBUG;TRACE + 4 + + + + pdbonly + true + bin\Release\ + false + $(DefineConstants);TRACE + 4 + + + + + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + True + + + + + False + true + + + False + true + + + False + + + + + + Code + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + + + Code + + + ThisAddIn.cs + + + ThisAddIn.Designer.xml + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + true + + + InkCanvasForClassPPTVsto_TemporaryKey.pfx + + + E0DCEEAE8C0D178489A9D826E0280507E45B0283 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto_TemporaryKey.pfx b/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto_TemporaryKey.pfx new file mode 100644 index 0000000..8833e31 Binary files /dev/null and b/InkCanvasForClassPPTVsto/InkCanvasForClassPPTVsto_TemporaryKey.pfx differ diff --git a/InkCanvasForClassPPTVsto/Properties/AssemblyInfo.cs b/InkCanvasForClassPPTVsto/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..297cda3 --- /dev/null +++ b/InkCanvasForClassPPTVsto/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("InkCanvasForClassPPTVsto")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("InkCanvasForClassPPTVsto")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("cfac1b17-2ab3-422a-9a48-a2d01a63f52d")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + diff --git a/InkCanvasForClassPPTVsto/Properties/Resources.Designer.cs b/InkCanvasForClassPPTVsto/Properties/Resources.Designer.cs new file mode 100644 index 0000000..e06741d --- /dev/null +++ b/InkCanvasForClassPPTVsto/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace InkCanvasForClassPPTVsto.Properties { + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("InkCanvasForClassPPTVsto.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/InkCanvasForClassPPTVsto/Properties/Resources.resx b/InkCanvasForClassPPTVsto/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/InkCanvasForClassPPTVsto/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/InkCanvasForClassPPTVsto/Properties/Settings.Designer.cs b/InkCanvasForClassPPTVsto/Properties/Settings.Designer.cs new file mode 100644 index 0000000..1d49dc3 --- /dev/null +++ b/InkCanvasForClassPPTVsto/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace InkCanvasForClassPPTVsto.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/InkCanvasForClassPPTVsto/Properties/Settings.settings b/InkCanvasForClassPPTVsto/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/InkCanvasForClassPPTVsto/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/InkCanvasForClassPPTVsto/ThisAddIn.Designer.cs b/InkCanvasForClassPPTVsto/ThisAddIn.Designer.cs new file mode 100644 index 0000000..de7c25f --- /dev/null +++ b/InkCanvasForClassPPTVsto/ThisAddIn.Designer.cs @@ -0,0 +1,231 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 414 +namespace InkCanvasForClassPPTVsto { + + + /// + [Microsoft.VisualStudio.Tools.Applications.Runtime.StartupObjectAttribute(0)] + [global::System.Security.Permissions.PermissionSetAttribute(global::System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] + public sealed partial class ThisAddIn : Microsoft.Office.Tools.AddInBase { + + internal Microsoft.Office.Tools.CustomTaskPaneCollection CustomTaskPanes; + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + private global::System.Object missing = global::System.Type.Missing; + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + internal Microsoft.Office.Interop.PowerPoint.Application Application; + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + public ThisAddIn(global::Microsoft.Office.Tools.Factory factory, global::System.IServiceProvider serviceProvider) : + base(factory, serviceProvider, "AddIn", "ThisAddIn") { + Globals.Factory = factory; + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override void Initialize() { + base.Initialize(); + this.Application = this.GetHostItem(typeof(Microsoft.Office.Interop.PowerPoint.Application), "Application"); + Globals.ThisAddIn = this; + global::System.Windows.Forms.Application.EnableVisualStyles(); + this.InitializeCachedData(); + this.InitializeControls(); + this.InitializeComponents(); + this.InitializeData(); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override void FinishInitialization() { + this.InternalStartup(); + this.OnStartup(); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override void InitializeDataBindings() { + this.BeginInitialization(); + this.BindToData(); + this.EndInitialization(); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void InitializeCachedData() { + if ((this.DataHost == null)) { + return; + } + if (this.DataHost.IsCacheInitialized) { + this.DataHost.FillCachedData(this); + } + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void InitializeData() { + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void BindToData() { + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + private void StartCaching(string MemberName) { + this.DataHost.StartCaching(this, MemberName); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + private void StopCaching(string MemberName) { + this.DataHost.StopCaching(this, MemberName); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + private bool IsCached(string MemberName) { + return this.DataHost.IsCached(this, MemberName); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void BeginInitialization() { + this.BeginInit(); + this.CustomTaskPanes.BeginInit(); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void EndInitialization() { + this.CustomTaskPanes.EndInit(); + this.EndInit(); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void InitializeControls() { + this.CustomTaskPanes = Globals.Factory.CreateCustomTaskPaneCollection(null, null, "CustomTaskPanes", "CustomTaskPanes", this); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + private void InitializeComponents() { + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + private bool NeedsFill(string MemberName) { + return this.DataHost.NeedsFill(this, MemberName); + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + protected override void OnShutdown() { + this.CustomTaskPanes.Dispose(); + base.OnShutdown(); + } + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + internal sealed partial class Globals { + + /// + private Globals() { + } + + private static ThisAddIn _ThisAddIn; + + private static global::Microsoft.Office.Tools.Factory _factory; + + private static ThisRibbonCollection _ThisRibbonCollection; + + internal static ThisAddIn ThisAddIn { + get { + return _ThisAddIn; + } + set { + if ((_ThisAddIn == null)) { + _ThisAddIn = value; + } + else { + throw new System.NotSupportedException(); + } + } + } + + internal static global::Microsoft.Office.Tools.Factory Factory { + get { + return _factory; + } + set { + if ((_factory == null)) { + _factory = value; + } + else { + throw new System.NotSupportedException(); + } + } + } + + internal static ThisRibbonCollection Ribbons { + get { + if ((_ThisRibbonCollection == null)) { + _ThisRibbonCollection = new ThisRibbonCollection(_factory.GetRibbonFactory()); + } + return _ThisRibbonCollection; + } + } + } + + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Tools.Office.ProgrammingModel.dll", "17.0.0.0")] + internal sealed partial class ThisRibbonCollection : Microsoft.Office.Tools.Ribbon.RibbonCollectionBase { + + /// + internal ThisRibbonCollection(global::Microsoft.Office.Tools.Ribbon.RibbonFactory factory) : + base(factory) { + } + } +} diff --git a/InkCanvasForClassPPTVsto/ThisAddIn.Designer.xml b/InkCanvasForClassPPTVsto/ThisAddIn.Designer.xml new file mode 100644 index 0000000..a7ebc31 --- /dev/null +++ b/InkCanvasForClassPPTVsto/ThisAddIn.Designer.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/InkCanvasForClassPPTVsto/ThisAddIn.cs b/InkCanvasForClassPPTVsto/ThisAddIn.cs new file mode 100644 index 0000000..02b897b --- /dev/null +++ b/InkCanvasForClassPPTVsto/ThisAddIn.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using PowerPoint = Microsoft.Office.Interop.PowerPoint; +using Office = Microsoft.Office.Core; + +namespace InkCanvasForClassPPTVsto +{ + public partial class ThisAddIn + { + private void ThisAddIn_Startup(object sender, System.EventArgs e) + { + } + + private void ThisAddIn_Shutdown(object sender, System.EventArgs e) + { + } + + #region VSTO 生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InternalStartup() + { + this.Startup += new System.EventHandler(ThisAddIn_Startup); + this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown); + } + + #endregion + } +} diff --git a/InkCanvasForClassX/InkCanvasForClassX.csproj b/InkCanvasForClassX/InkCanvasForClassX.csproj index 38425cb..77ad001 100644 --- a/InkCanvasForClassX/InkCanvasForClassX.csproj +++ b/InkCanvasForClassX/InkCanvasForClassX.csproj @@ -7,6 +7,7 @@ true + diff --git a/InkCanvasForClassX/Libraries/InkProjector.cs b/InkCanvasForClassX/Libraries/InkProjector.cs index cf1ee1c..373ed5b 100644 --- a/InkCanvasForClassX/Libraries/InkProjector.cs +++ b/InkCanvasForClassX/Libraries/InkProjector.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Windows; using System.Windows.Ink; +using System.Windows.Input; using System.Windows.Media; namespace InkCanvasForClassX.Libraries @@ -12,6 +15,7 @@ namespace InkCanvasForClassX.Libraries private VisualCollection _children; private DrawingVisual _layer = new DrawingVisual(); private StrokeCollection _strokes; + private PerfectFreehandJint _perfectFreehandJint = new PerfectFreehandJint(); public InkProjector() { @@ -24,7 +28,7 @@ namespace InkCanvasForClassX.Libraries get => _strokes; set { _strokes = value; - DrawInk(); + DrawPerfectInk(); } } @@ -41,5 +45,50 @@ namespace InkCanvasForClassX.Libraries context.Close(); } + private void DrawPerfectInk() { + DrawingContext context = _layer.RenderOpen(); + context.PushClip(new RectangleGeometry(new Rect(new Size(this.ActualWidth,this.ActualHeight)))); + foreach (var stroke in _strokes) { + var stylusPtsList = new List(); + foreach (var strokeStylusPoint in stroke.StylusPoints) + { + stylusPtsList.Add(new PerfectFreehandJint.StylusPointLite() + { + x = Math.Round(strokeStylusPoint.X, 2), + y = Math.Round(strokeStylusPoint.Y, 2), + pressure = strokeStylusPoint.PressureFactor, + }); + } + context.DrawGeometry(new SolidColorBrush(Colors.Black), (System.Windows.Media.Pen)null, _perfectFreehandJint.GetGeometryStroke(stylusPtsList.ToArray(), new PerfectFreehandJint.StrokeOptions() + { + size = 2, + thinning = 0.5, + smoothing = 0.5, + streamline = 0.2, + simulatePressure = true, + easing = (x) => 1 - (1 - x) * (1 - x), + last = true, + start = new PerfectFreehandJint.StrokeCapOptions() + { + cap = true, + taper = 0, + easing = (x) => 1 - (1 - x) * (1 - x), + }, + end = new PerfectFreehandJint.StrokeCapOptions() + { + cap = true, + taper = 0, + easing = (x) => 1 - (1 - x) * (1 - x), + }, + })); + } + context.Pop(); + context.Close(); + } + + protected override void OnMouseLeave(MouseEventArgs e) { + base.OnMouseLeave(e); + Trace.WriteLine("Mouse Move"); + } } } diff --git a/InkCanvasForClassX/Libraries/PerfectFreehand.cs b/InkCanvasForClassX/Libraries/PerfectFreehand.cs index 41d97ba..7c62479 100644 --- a/InkCanvasForClassX/Libraries/PerfectFreehand.cs +++ b/InkCanvasForClassX/Libraries/PerfectFreehand.cs @@ -14,6 +14,42 @@ namespace InkCanvasForClassX.Libraries /// public class PerfectFreehand { + private static double Average(double a, double b) { + return (a + b) / 2; + } + + public static string ConvertVectorsToSVGPath(Vector[] points, bool closed = true) + { + int len = points.Length; + + if (len < 4) + { + return string.Empty; + } + + Vector a = points[0]; + Vector b = points[1]; + Vector c = points[2]; + + StringBuilder result = new StringBuilder(); + result.AppendFormat("M{0:F2},{1:F2} Q{2:F2},{3:F2} {4:F2},{5:F2} T", + a.X, a.Y, b.X, b.Y, Average(b.X, c.X), Average(b.Y, c.Y)); + + for (int i = 2, max = len - 1; i < max; i++) + { + a = points[i]; + b = points[i + 1]; + result.AppendFormat("{0:F2},{1:F2} ", Average(a.X, b.X), Average(a.Y, b.Y)); + } + + if (closed) + { + result.Append("Z"); + } + + return result.ToString(); + } + /// /// Get an array of points as objects with an adjusted point, pressure, vector, distance, and runningLength. /// @@ -152,6 +188,360 @@ namespace InkCanvasForClassX.Libraries } return size * easing(0.5 - thinning * (0.5 - pressure)); } + + // This is the rate of change for simulated pressure. It could be an option. + private const double RATE_OF_PRESSURE_CHANGE = 0.275; + + private const double PI = Math.PI; + private const double FIXED_PI = PI + 0.0001; + + /// + /// Get an array of points (as `[x, y]`) representing the outline of a stroke. + /// + /// An array of StrokePoints as returned from `getStrokePoints`. + /// An object with options. + /// + public static Vector[] GetStrokeOutlinePointsVectors(StrokePoint[] points, StrokeOptions options) { + var strokeOptions_Size = options.Size ?? 16; + var strokeOptions_Thinning = options.Thinning ?? 0.5; + var strokeOptions_Smoothing = options.Smoothing ?? 0.5; + var strokeOptions_SimulatePressure = options.SimulatePressure ?? true; + Func strokeOptions_Easing = (t) => t; + var strokeOptions_Start = options.Start; + var strokeOptions_End = options.End; + var isComplete = options.Last ?? false; + + var capStart = strokeOptions_Start != null ? strokeOptions_Start.Cap : true; + Func taperStartEase = strokeOptions_Start != null + ? strokeOptions_Start.Easing + : (s) => s * (2 - s); + + var capEnd = strokeOptions_End != null ? strokeOptions_End.Cap : true; + Func taperEndEase = strokeOptions_End != null + ? strokeOptions_End.Easing + : (t) => --t * t * t + 1; + + // We can't do anything with an empty array or a stroke with negative size. + if (points.Length == 0 || strokeOptions_Size <= 0) { + return new Vector[] { }; + } + + // The total length of the line + var totalLength = points[points.Length - 1].RunningLength; + + var taperStart = strokeOptions_Start != null ? strokeOptions_Start.IsTaper == false ? 0 : + strokeOptions_Start.IsTaper ? Math.Max(strokeOptions_Size, totalLength) : + strokeOptions_Start.Taper != null ? (double)strokeOptions_Start.Taper : 0 : Double.NaN; + + var taperEnd = strokeOptions_End != null ? strokeOptions_End.IsTaper == false ? 0 : + strokeOptions_End.IsTaper ? Math.Max(strokeOptions_Size, totalLength) : + strokeOptions_End.Taper != null ? (double)strokeOptions_End.Taper : 0 : Double.NaN; + + // The minimum allowed distance between points (squared) + var minDistance = Math.Pow(strokeOptions_Size * strokeOptions_Smoothing, 2); + + // Our collected left and right points + var leftPts = new List(); + var rightPts = new List(); + + // Previous pressure (start with average of first five pressures, + // in order to prevent fat starts for every line. Drawn lines + // almost always start slow! + var _prevPressure_arrseg = new ArraySegment(points, 0, 10); + var prevPressure = _prevPressure_arrseg.Aggregate(points[0].Pressure, + (acc, curr) => { + var pressure = curr.Pressure; + + if (strokeOptions_SimulatePressure) { + // Speed of change - how fast should the the pressure changing? + var sp = Math.Min(1, curr.Distance / strokeOptions_Size); + // Rate of change - how much of a change is there? + var rp = Math.Min(1, 1 - sp); + pressure = Math.Min(1, acc + (rp - acc) * (sp * RATE_OF_PRESSURE_CHANGE)); + } + + return (acc + pressure) / 2; + }); + + // The current radius + var radius = GetStrokeRadius(strokeOptions_Size, strokeOptions_Thinning, points[points.Length - 1].Pressure, + strokeOptions_Easing); + + // The radius of the first saved point + double firstRadius = Double.NaN; + + // Previous vector + var prevVector = points[0].Vector; + + // Previous left and right points + var pl = points[0].Point; + var pr = pl; + + // Temporary left and right points + var tl = pl; + var tr = pr; + + // Keep track of whether the previous point is a sharp corner + // ... so that we don't detect the same corner twice + var isPrevPointSharpCorner = false; + + /* + Find the outline's left and right points + + Iterating through the points and populate the rightPts and leftPts arrays, + skipping the first and last pointsm, which will get caps later on. + */ + foreach (var _sp in points) { + var pressure = _sp.Pressure; + var point = _sp.Point; + var vector = _sp.Vector; + var distance = _sp.Distance; + var runningLength = _sp.RunningLength; + + var i = Array.IndexOf(points, _sp); + + // Removes noise from the end of the line + if (i < points.Length - 1 && totalLength - runningLength < 3) { + continue; + } + + /* + Calculate the radius + + If not thinning, the current point's radius will be half the size; or + otherwise, the size will be based on the current (real or simulated) + pressure. + */ + if (strokeOptions_Thinning == Double.NaN) { + if (strokeOptions_SimulatePressure) { + // If we're simulating pressure, then do so based on the distance + // between the current point and the previous point, and the size + // of the stroke. Otherwise, use the input pressure. + var sp = Math.Min(1, distance / strokeOptions_Size); + var rp = Math.Min(1, 1 - sp); + pressure = Math.Min(1, prevPressure + (rp - prevPressure) * (sp * RATE_OF_PRESSURE_CHANGE)); + } + + radius = GetStrokeRadius(strokeOptions_Size, strokeOptions_Thinning, pressure, + strokeOptions_Easing); + } else { + radius = strokeOptions_Size / 2; + } + + if (firstRadius == Double.NaN) firstRadius = radius; + + /* + Apply tapering + + If the current length is within the taper distance at either the + start or the end, calculate the taper strengths. Apply the smaller + of the two taper strengths to the radius. + */ + var ts = runningLength < taperStart ? taperStartEase(runningLength / taperStart) : 1; + var te = runningLength < taperEnd ? taperEndEase(runningLength / taperEnd) : 1; + + radius = Math.Max(0.01, radius * Math.Min(ts, te)); + + /* Add points to left and right */ + + /* + Handle sharp corners + + Find the difference (dot product) between the current and next vector. + If the next vector is at more than a right angle to the current vector, + draw a cap at the current point. + */ + + var nextVector = (i < points.Length - 1 ? points[i + 1] : points[i]).Vector; + var nextDpr = i < points.Length - 1 ? Vector.DotVectors(vector, nextVector) : 1.0; + var prevDpr = Vector.DotVectors(vector, prevVector); + + var isPointSharpCorner = prevDpr < 0 && !isPrevPointSharpCorner; + var isNextPointSharpCorner = nextDpr < 0; + + if (isPointSharpCorner || isNextPointSharpCorner) { + // It's a sharp corner. Draw a rounded cap and move on to the next point + // Considering saving these and drawing them later? So that we can avoid + // crossing future points. + + var offset = Vector.MultiplyVector(Vector.PerpendicularRotationVector(prevVector), radius); + + double step = 1D / 13D; + double t = 0D; + for (; t <= 1D; t += step) { + tl = Vector.RotateVectors(Vector.SubtractVectors(point, offset), point, FIXED_PI * t); + leftPts.Add(tl); + + tr = Vector.RotateVectors(Vector.AddVectors(point, offset), point, FIXED_PI * -t); + rightPts.Add(tr); + } + + pl = tl; + pr = tr; + + if (isNextPointSharpCorner) { + isPrevPointSharpCorner = true; + } + continue; + } + + isPrevPointSharpCorner = false; + + // Handle the last point + if (i == points.Length - 1) { + var offset = Vector.MultiplyVector(Vector.PerpendicularRotationVector(vector), radius); + leftPts.Add(Vector.SubtractVectors(point, offset)); + rightPts.Add(Vector.AddVectors(point, offset)); + continue; + } + + /* + Add regular points + + Project points to either side of the current point, using the + calculated size as a distance. If a point's distance to the + previous point on that side greater than the minimum distance + (or if the corner is kinda sharp), add the points to the side's + points array. + */ + Vector _offset = + Vector.MultiplyVector( + Vector.PerpendicularRotationVector(Vector.InterpolateVectors(nextVector, vector, nextDpr)), + radius); + + tl = Vector.SubtractVectors(point, _offset); + + if (i <= 1 || Vector.DistLengthSquaredVectors(pl, tl) > minDistance) { + leftPts.Add(tl); + pl = tl; + } + + tr = Vector.AddVectors(point, _offset); + + if (i <= 1 || Vector.DistLengthSquaredVectors(pr, tr) > minDistance) { + rightPts.Add(tr); + pr = tr; + } + + // Set variables for next iteration + prevPressure = pressure; + prevVector = vector; + } + + /* + Drawing caps + + Now that we have our points on either side of the line, we need to + draw caps at the start and end. Tapered lines don't have caps, but + may have dots for very short lines. + */ + var firstPoint = points[0].Point; + + var lastPoint = points.Length > 1 + ? points[points.Length - 1].Point + : Vector.AddVectors(points[0].Point, new Vector(1, 1)); + + var startCap = new List(); + var endCap = new List(); + + /* + Draw a dot for very short or completed strokes + + If the line is too short to gather left or right points and if the line is + not tapered on either side, draw a dot. If the line is tapered, then only + draw a dot if the line is both very short and complete. If we draw a dot, + we can just return those points. + */ + if (points.Length == 1) { + if (!((strokeOptions_Start != null && (taperStart != 0 && strokeOptions_Start.IsTaper)) || (strokeOptions_End != null && + (taperEnd != 0 && strokeOptions_End.IsTaper))) || isComplete) { + var start = Vector.ProjectVectors(firstPoint, + Vector.UnitVector( + Vector.PerpendicularRotationVector(Vector.SubtractVectors(firstPoint, lastPoint))), !double.IsNaN(firstRadius) ? -firstRadius : -radius); + var dotPts = new List(); + double step = 1D / 13D; + double t = step; + for (; t <= 1D; t += step) { + dotPts.Add(Vector.RotateVectors(start, firstPoint, FIXED_PI * 2 * t)); + } + + return dotPts.ToArray(); + } + } else { + /* + Draw a start cap + + Unless the line has a tapered start, or unless the line has a tapered end + and the line is very short, draw a start cap around the first point. Use + the distance between the second left and right point for the cap's radius. + Finally remove the first left and right points. :psyduck: + */ + + if ((strokeOptions_Start != null && (taperStart != 0 && strokeOptions_Start.IsTaper)) || ((strokeOptions_End != null && + (taperEnd != 0 && strokeOptions_End.IsTaper)) && points.Length == 1)) { + // The start point is tapered, noop + } else if (capStart) { + // Draw the round cap - add thirteen points rotating the right point around the start point to the left point + double step = 1D / 13D; + double t = step; + for (; t <= 1D; t += step) { + var pt = Vector.RotateVectors(rightPts[0], firstPoint, FIXED_PI * t); + startCap.Add(pt); + } + } else { + // Draw the flat cap - add a point to the left and right of the start point + var cornersVector = Vector.SubtractVectors(leftPts[0], rightPts[0]); + var offsetA = Vector.MultiplyVector(cornersVector, 0.5); + var offsetB = Vector.MultiplyVector(cornersVector, 0.51); + + startCap.Add(Vector.SubtractVectors(firstPoint, offsetA)); + startCap.Add(Vector.SubtractVectors(firstPoint, offsetB)); + startCap.Add(Vector.AddVectors(firstPoint, offsetA)); + startCap.Add(Vector.AddVectors(firstPoint, offsetB)); + } + + /* + Draw an end cap + + If the line does not have a tapered end, and unless the line has a tapered + start and the line is very short, draw a cap around the last point. Finally, + remove the last left and right points. Otherwise, add the last point. Note + that This cap is a full-turn-and-a-half: this prevents incorrect caps on + sharp end turns. + */ + var direction = + Vector.PerpendicularRotationVector(Vector.NegateVector(points[points.Length - 1].Vector)); + + if ((strokeOptions_End != null && + (taperEnd != 0 && strokeOptions_End.IsTaper)) || + ((strokeOptions_Start != null && (taperStart != 0 && strokeOptions_Start.IsTaper)) && points.Length == 1)) { + // Tapered end - push the last point to the line + endCap.Add(lastPoint); + } else if (capEnd) { + // Draw the round end cap + var start = Vector.ProjectVectors(lastPoint, direction, radius); + double step = 1D / 29D; + double t = step; + for (; t < 1D; t += step) { + endCap.Add(Libraries.Vector.RotateVectors(start, lastPoint, FIXED_PI * 3 * t)); + } + } else { + // Draw the flat end cap + endCap.Add(Vector.AddVectors(lastPoint, Vector.MultiplyVector(direction, radius))); + endCap.Add(Vector.AddVectors(lastPoint, Vector.MultiplyVector(direction, radius * 0.99))); + endCap.Add(Vector.SubtractVectors(lastPoint, Vector.MultiplyVector(direction, radius))); + endCap.Add(Vector.SubtractVectors(lastPoint, Vector.MultiplyVector(direction, radius * 0.99))); + } + } + + /* + Return the points in the correct winding order: begin on the left side, then + continue around the end cap, then come back along the right side, and finally + complete the start cap. + */ + rightPts.Reverse(); + return leftPts.Concat(endCap).Concat(rightPts).Concat(startCap).ToArray(); + } } namespace Stroke { @@ -204,12 +594,14 @@ namespace InkCanvasForClassX.Libraries /// /// Whether to apply a cap at the start/end of the line. /// - public bool? Cap { get; set; } + public bool Cap { get; set; } /// /// The taper value at the start/end of the line. /// - public double? Taper { get; set; } + public double Taper { get; set; } + + public bool IsTaper { get; set; } /// /// An easing function to apply to the taper. diff --git a/InkCanvasForClassX/Libraries/PerfectFreehandJint.cs b/InkCanvasForClassX/Libraries/PerfectFreehandJint.cs new file mode 100644 index 0000000..07e8f45 --- /dev/null +++ b/InkCanvasForClassX/Libraries/PerfectFreehandJint.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; +using InkCanvasForClassX.Libraries.Stroke; +using Jint; +using Jint.Native; + +namespace InkCanvasForClassX.Libraries +{ + public class PerfectFreehandJint { + public class StylusPointLite + { + public double x; + public double y; + public double pressure; + } + + public class StrokeOptions + { + public double? size { get; set; } + public double? thinning { get; set; } + public double? smoothing { get; set; } + public double? streamline { get; set; } + public Func easing { get; set; } + public bool? simulatePressure { get; set; } + public StrokeCapOptions start { get; set; } + public StrokeCapOptions end { get; set; } + public bool? last { get; set; } + } + + public class StrokeCapOptions + { + public bool? cap { get; set; } + public double? taper { get; set; } + public Func easing { get; set; } + } + + public class StrokePoint + { + public Array point { get; set; } + public double pressure { get; set; } + public double distance { get; set; } + public Array vector { get; set; } + public double runningLength { get; set; } + } + + public readonly Engine JintEngine = new Engine(); + + public PerfectFreehandJint() { + // perfect-freehand + JintEngine.Execute("function neg(t){return[-t[0],-t[1]]}function add(t,n){return[t[0]+n[0],t[1]+n[1]]}function sub(t,n){return[t[0]-n[0],t[1]-n[1]]}function mul(t,n){return[t[0]*n,t[1]*n]}function div(t,n){return[t[0]/n,t[1]/n]}function per(t){return[t[1],-t[0]]}function dpr(t,n){return t[0]*n[0]+t[1]*n[1]}function isEqual(t,n){return t[0]===n[0]&&t[1]===n[1]}function len(t){return Math.hypot(t[0],t[1])}function len2(t){return t[0]*t[0]+t[1]*t[1]}function dist2(t,n){return len2(sub(t,n))}function uni(t){return div(t,len(t))}function dist(t,n){return Math.hypot(t[1]-n[1],t[0]-n[0])}function med(t,n){return mul(add(t,n),.5)}function rotAround(t,n,e){const r=Math.sin(e),u=Math.cos(e),i=t[0]-n[0],s=t[1]-n[1],o=i*r+s*u;return[i*u-s*r+n[0],o+n[1]]}function lrp(t,n,e){return add(t,mul(sub(n,t),e))}function prj(t,n,e){return add(t,mul(n,e))}function getStrokeRadius(t,n,e,r=(t=>t)){return t*r(.5-n*(.5-e))}function getStrokePoints(t,n={}){var e;const{streamline:r=.5,size:u=16,last:i=!1}=n;if(0===t.length)return[];const s=.15+.85*(1-r);let o=Array.isArray(t[0])?t:t.map((({x:t,y:n,pressure:e=.5})=>[t,n,e]));if(2===o.length){const t=o[1];o=o.slice(0,-1);for(let n=1;n<5;n++)o.push(lrp(o[0],t,n/4))}1===o.length&&(o=[...o,[...add(o[0],[1,1]),...o[0].slice(2)]]);const c=[{point:[o[0][0],o[0][1]],pressure:o[0][2]>=0?o[0][2]:.25,vector:[1,1],distance:0,runningLength:0}];let l=!1,p=0,a=c[0];const d=o.length-1;for(let t=1;t=0?o[t][2]:.5,vector:uni(sub(a.point,n)),distance:e,runningLength:p},c.push(a)}return c[0].vector=(null===(e=c[1])||void 0===e?void 0:e.vector)||[0,0],c}const{min:min,PI:PI}=Math,RATE_OF_PRESSURE_CHANGE=.275,FIXED_PI=PI+1e-4;function getStrokeOutlinePoints(t,n={}){const{size:e=16,smoothing:r=.5,thinning:u=.5,simulatePressure:i=!0,easing:s=(t=>t),start:o={},end:c={},last:l=!1}=n,{cap:p=!0,easing:a=(t=>t*(2-t))}=o,{cap:d=!0,easing:h=(t=>--t*t*t+1)}=c;if(0===t.length||e<=0)return[];const f=t[t.length-1].runningLength,g=!1===o.taper?0:!0===o.taper?Math.max(e,f):o.taper,m=!1===c.taper?0:!0===c.taper?Math.max(e,f):c.taper,E=Math.pow(e*r,2),P=[],v=[];let I,_=t.slice(0,10).reduce(((t,n)=>{let r=n.pressure;if(i){const u=min(1,n.distance/e),i=min(1,1-u);r=min(1,t+u*RATE_OF_PRESSURE_CHANGE*(i-t))}return(t+r)/2}),t[0].pressure),A=getStrokeRadius(e,u,t[t.length-1].pressure,s),S=t[0].vector,b=t[0].point,R=b,M=b,F=R,k=!1;for(let n=0;nE)&&(P.push(M),b=M),F=add(o,x),(n<=1||dist2(R,F)>E)&&(v.push(F),R=F),_=r,S=c}const D=t[0].point.slice(0,2),X=t.length>1?t[t.length-1].point.slice(0,2):add(t[0].point,[1,1]),y=[],O=[];if(1===t.length){if(!g&&!m||l){const t=prj(D,uni(per(sub(D,X))),-(I||A)),n=[];for(let e=1/13,r=e;r<=1;r+=e)n.push(rotAround(t,D,2*FIXED_PI*r));return n}}else{if(g||m&&1===t.length);else if(p)for(let t=1/13,n=t;n<=1;n+=t){const t=rotAround(v[0],D,FIXED_PI*n);y.push(t)}else{const t=sub(P[0],v[0]),n=mul(t,.5),e=mul(t,.51);y.push(sub(D,n),sub(D,e),add(D,e),add(D,n))}const n=per(neg(t[t.length-1].vector));if(m||g&&1===t.length)O.push(X);else if(d){const t=prj(X,n,A);for(let n=1/29,e=n;e<1;e+=n)O.push(rotAround(t,X,3*FIXED_PI*e))}else O.push(add(X,mul(n,A)),add(X,mul(n,.99*A)),sub(X,mul(n,.99*A)),sub(X,mul(n,A)))}return P.concat(O,v.reverse(),y)}function getStroke(t,n={}){return getStrokeOutlinePoints(getStrokePoints(t,n),n)}"); + // getSvgPathFromStroke + JintEngine.Execute( + "const average=(e,t)=>(e+t)/2;function getSvgPathFromStroke(e,t=!0){const o=e.length;if(o<4)return\"\";let r=e[0],a=e[1];const i=e[2];let F=`M${r[0].toFixed(2)},${r[1].toFixed(2)} Q${a[0].toFixed(2)},${a[1].toFixed(2)} ${average(a[0],i[0]).toFixed(2)},${average(a[1],i[1]).toFixed(2)} T`;for(let t=2,i=o-1;t - /// 將該向量點乘另一個向量 + /// 提供兩個Vector,返回兩個Vector點乘後的数值 /// - public Vector Dot(Vector vec) + public static double DotVectors(Vector vec1, Vector vec2) { - _x = _x * vec.X; - _y = _y * vec.Y; - return this; - } - - /// - /// 提供兩個Vector,返回兩個Vector點乘後的Vector - /// - public static Vector DotVectors(Vector vec1, Vector vec2) - { - return new Vector(vec1.X * vec2.X, vec1.Y * vec2.Y); + return vec1.X * vec2.X + vec1.Y * vec2.Y; } /// diff --git a/InkCanvasForClassX/MainWindow.xaml b/InkCanvasForClassX/MainWindow.xaml index f60adcd..e02e873 100644 --- a/InkCanvasForClassX/MainWindow.xaml +++ b/InkCanvasForClassX/MainWindow.xaml @@ -10,5 +10,9 @@ + + + + diff --git a/InkCanvasForClassX/MainWindow.xaml.cs b/InkCanvasForClassX/MainWindow.xaml.cs index aadf517..266215d 100644 --- a/InkCanvasForClassX/MainWindow.xaml.cs +++ b/InkCanvasForClassX/MainWindow.xaml.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,11 +8,14 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; +using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using InkCanvasForClassX.Libraries; +using InkCanvasForClassX.Libraries.Stroke; namespace InkCanvasForClassX { @@ -20,12 +24,129 @@ namespace InkCanvasForClassX /// public partial class MainWindow : Window { + + + + public static StylusPointCollection GenerateStylusPoints(int numberOfPoints, int maxX, int maxY) + { + Random random = new Random(); + StylusPointCollection points = new StylusPointCollection(); + + for (int i = 0; i < numberOfPoints; i++) + { + double x = random.NextDouble() * maxX; + double y = random.NextDouble() * maxY; + float pressureFactor = 0.5F; + + StylusPoint point = new StylusPoint(x, y, pressureFactor); + points.Add(point); + } + + return points; + } + + private bool isDragging = false; + private Point startPoint; public MainWindow() { InitializeComponent(); InkC.StrokeCollected += (object sender, InkCanvasStrokeCollectedEventArgs e) => { InkP.Strokes = InkC.Strokes; + var stylusPtsList = new List(); + foreach (var strokeStylusPoint in e.Stroke.StylusPoints) { + stylusPtsList.Add(new PerfectFreehandJint.StylusPointLite() + { + x = Math.Round(strokeStylusPoint.X,2) , + y = Math.Round(strokeStylusPoint.Y,2), + pressure = strokeStylusPoint.PressureFactor, + }); + } + var aaa = new PerfectFreehandJint(); + var ccc = aaa.GetSVGPathStroke(stylusPtsList.ToArray(), new PerfectFreehandJint.StrokeOptions() { + size = 16, + thinning = 0.5, + smoothing = 0.5, + streamline = 0.5, + simulatePressure = true, + easing = (t)=>t, + last = true, + start = new PerfectFreehandJint.StrokeCapOptions() { + cap = true, + taper = 0, + easing = (t)=>t, + }, + end = new PerfectFreehandJint.StrokeCapOptions() + { + cap = true, + taper = 0, + easing = (t) => t, + }, + }); + Trace.WriteLine(ccc); }; + + InkC.MouseRightButtonDown += Inkcanv_MouseRightButtonDown; + InkC.MouseRightButtonUp += Inkcanv_MouseRightButtonUp; + InkC.MouseMove += Inkcanv_MouseMove; + var a = GenerateStylusPoints(10, 1920, 1080); + foreach (var strokePoint in a) + { + Trace.WriteLine($"point x:{strokePoint.X} point y:{strokePoint.Y}"); + } + var c = PerfectFreehand.GetStrokePoints(a, new StrokeOptions() { + Size = 16, + Thinning = 0.5, + Smoothing = 0.5, + SimulatePressure = true, + }); + var s = PerfectFreehand.GetStrokeOutlinePointsVectors(c, new StrokeOptions() { + Size = 16, + Thinning = 0.5, + Smoothing = 0.5, + SimulatePressure = true, + }); + foreach (var strokePoint in c) { + Trace.WriteLine($"point x:{strokePoint.Vector.X.ToString()} point y:{strokePoint.Vector.Y.ToString()}"); + } + Trace.WriteLine(PerfectFreehand.ConvertVectorsToSVGPath(s)); + } + + private void Inkcanv_MouseRightButtonDown(object sender, MouseButtonEventArgs e) + { + isDragging = true; + startPoint = e.GetPosition(InkC); + InkC.CaptureMouse(); + } + + private void Inkcanv_MouseRightButtonUp(object sender, MouseButtonEventArgs e) + { + isDragging = false; + InkC.ReleaseMouseCapture(); + } + + private void Inkcanv_MouseMove(object sender, MouseEventArgs e) + { + if (isDragging && e.RightButton == MouseButtonState.Pressed) + { + Point currentPoint = e.GetPosition(InkC); + System.Windows.Vector delta = currentPoint - startPoint; + + foreach (Stroke stroke in InkC.Strokes) + { + stroke.Transform(new Matrix(1, 0, 0, 1, delta.X, delta.Y), false); + } + InkP.Strokes = InkC.Strokes; + + startPoint = currentPoint; + } + } + + private void ButtonBase1_OnClick(object sender, RoutedEventArgs e) { + InkC.EditingMode = InkCanvasEditingMode.None; + } + + private void ButtonBase2_OnClick(object sender, RoutedEventArgs e) { + InkC.EditingMode = InkCanvasEditingMode.Ink; } } } diff --git a/PeroInstaller/App.xaml b/PeroInstaller/App.xaml new file mode 100644 index 0000000..853bd24 --- /dev/null +++ b/PeroInstaller/App.xaml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/PeroInstaller/App.xaml.cs b/PeroInstaller/App.xaml.cs new file mode 100644 index 0000000..958933f --- /dev/null +++ b/PeroInstaller/App.xaml.cs @@ -0,0 +1,13 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace PeroInstaller +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} \ No newline at end of file diff --git a/PeroInstaller/AssemblyInfo.cs b/PeroInstaller/AssemblyInfo.cs new file mode 100644 index 0000000..b0ec827 --- /dev/null +++ b/PeroInstaller/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/PeroInstaller/InstallerConfig.xaml b/PeroInstaller/InstallerConfig.xaml new file mode 100644 index 0000000..6bb2206 --- /dev/null +++ b/PeroInstaller/InstallerConfig.xaml @@ -0,0 +1,9 @@ + + InkCanvasForClass 安装向导 + InkCanvasForClass + 开源的简单易用小巧强大的屏幕批注软件 + 20240710V1P1 + + \ No newline at end of file diff --git a/PeroInstaller/MainWindow.xaml b/PeroInstaller/MainWindow.xaml new file mode 100644 index 0000000..daec3cb --- /dev/null +++ b/PeroInstaller/MainWindow.xaml @@ -0,0 +1,118 @@ + + + + + + + + + + + + 基于PeroInstaller包装,打包版本: + + + + + + + + + + + + + + + + + + + 安装 + + + + + + + + + + + + + + + + + + + + 卸载 + + + + + + + + + + + + + + + + + + + + 更新 + + + + + + + + + + + + + + + + + + + + 修改 + + + + + + + + + diff --git a/PeroInstaller/MainWindow.xaml.cs b/PeroInstaller/MainWindow.xaml.cs new file mode 100644 index 0000000..e2f78bd --- /dev/null +++ b/PeroInstaller/MainWindow.xaml.cs @@ -0,0 +1,24 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace PeroInstaller +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/PeroInstaller/PeroInstaller - Backup (1).csproj b/PeroInstaller/PeroInstaller - Backup (1).csproj new file mode 100644 index 0000000..32194a3 --- /dev/null +++ b/PeroInstaller/PeroInstaller - Backup (1).csproj @@ -0,0 +1,17 @@ + + + + WinExe + net6.0-windows10.0.19041.0 + enable + enable + true + 7.0 + + + + + + + + diff --git a/PeroInstaller/PeroInstaller - Backup.csproj b/PeroInstaller/PeroInstaller - Backup.csproj new file mode 100644 index 0000000..b25f853 --- /dev/null +++ b/PeroInstaller/PeroInstaller - Backup.csproj @@ -0,0 +1,16 @@ + + + + WinExe + net6.0-windows10.0.18362.0 + enable + enable + true + + + + + + + + diff --git a/PeroInstaller/PeroInstaller.csproj b/PeroInstaller/PeroInstaller.csproj new file mode 100644 index 0000000..7a9958b --- /dev/null +++ b/PeroInstaller/PeroInstaller.csproj @@ -0,0 +1,25 @@ + + + + WinExe + net6.0-windows10.0.18362.0 + enable + enable + true + 7.0 + + + + + + + + + + + + + + + + diff --git a/PeroInstaller/PeroInstaller.csproj.user b/PeroInstaller/PeroInstaller.csproj.user new file mode 100644 index 0000000..27618fc --- /dev/null +++ b/PeroInstaller/PeroInstaller.csproj.user @@ -0,0 +1,19 @@ + + + + <_LastSelectedProfileId>D:\vs\ica\PeroInstaller\Properties\PublishProfiles\FolderProfile.pubxml + + + + Designer + + + + + Designer + + + Designer + + + \ No newline at end of file diff --git a/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml b/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..f4b2696 --- /dev/null +++ b/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,18 @@ + + + + + Release + Any CPU + bin\dist\ + FileSystem + <_TargetId>Folder + net6.0-windows + win-x86 + true + true + true + + \ No newline at end of file diff --git a/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml.user b/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..c09c61c --- /dev/null +++ b/PeroInstaller/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/PeroInstaller/resources/icc.png b/PeroInstaller/resources/icc.png new file mode 100644 index 0000000..99017b9 Binary files /dev/null and b/PeroInstaller/resources/icc.png differ