diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..27d4f745
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,22 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+## Description
+
+
+## Reproduction
+
+
+## Expected behavior
+
+
+## Screenshots
+
+
+## Additional context
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..f909f8a7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,10 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+## Description
diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml
new file mode 100644
index 00000000..2b180086
--- /dev/null
+++ b/.github/workflows/dotnet-desktop.yml
@@ -0,0 +1,35 @@
+name: .NET Build
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+
+ build:
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v4.2.2
+
+ - name: Setup MSbuild
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Setup NuGet
+ uses: NuGet/setup-nuget@v2.0.1
+
+ - name: Restore NuGet Packages
+ run: nuget restore "Ink Canvas.sln"
+
+ - name: Build the Solution
+ run: |
+ msbuild -t:restore /p:GitFlow="Github Action"
+ msbuild /p:platform="Any CPU" /p:configuration="Release" /p:GitFlow="Github Action" "Ink Canvas/InkCanvasForClass.csproj"
+
+ - name: Upload to artifact
+ uses: actions/upload-artifact@v4.5.0
+ with:
+ name: InkCanvasForClass
+ path: "Ink Canvas/bin/Any CPU/Release/net472/"
diff --git a/.idea/.idea.Ink Canvas/.idea/.gitignore b/.idea/.idea.Ink Canvas/.idea/.gitignore
new file mode 100644
index 00000000..b4ff7879
--- /dev/null
+++ b/.idea/.idea.Ink Canvas/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/projectSettingsUpdater.xml
+/modules.xml
+/contentModel.xml
+/.idea.Ink Canvas.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.Ink Canvas/.idea/.name b/.idea/.idea.Ink Canvas/.idea/.name
new file mode 100644
index 00000000..ecd6c92c
--- /dev/null
+++ b/.idea/.idea.Ink Canvas/.idea/.name
@@ -0,0 +1 @@
+Ink Canvas
\ No newline at end of file
diff --git a/.idea/.idea.Ink Canvas/.idea/encodings.xml b/.idea/.idea.Ink Canvas/.idea/encodings.xml
new file mode 100644
index 00000000..df87cf95
--- /dev/null
+++ b/.idea/.idea.Ink Canvas/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Ink Canvas/.idea/indexLayout.xml b/.idea/.idea.Ink Canvas/.idea/indexLayout.xml
new file mode 100644
index 00000000..7b08163c
--- /dev/null
+++ b/.idea/.idea.Ink Canvas/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Ink Canvas/.idea/vcs.xml b/.idea/.idea.Ink Canvas/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/.idea.Ink Canvas/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/CodeChunks.db b/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/CodeChunks.db
new file mode 100644
index 00000000..69e478f1
Binary files /dev/null and b/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/CodeChunks.db differ
diff --git a/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/SemanticSymbols.db b/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/SemanticSymbols.db
new file mode 100644
index 00000000..97f1c647
Binary files /dev/null and b/.vs/Ink Canvas/CopilotIndices/17.14.698.11175/SemanticSymbols.db differ
diff --git a/.vs/Ink Canvas/DesignTimeBuild/.dtbcache.v2 b/.vs/Ink Canvas/DesignTimeBuild/.dtbcache.v2
new file mode 100644
index 00000000..6307a8a4
Binary files /dev/null and b/.vs/Ink Canvas/DesignTimeBuild/.dtbcache.v2 differ
diff --git a/.vs/Ink Canvas/FileContentIndex/92cf1a99-e1a2-4b47-9d7c-1313c10009c7.vsidx b/.vs/Ink Canvas/FileContentIndex/92cf1a99-e1a2-4b47-9d7c-1313c10009c7.vsidx
new file mode 100644
index 00000000..d507340b
Binary files /dev/null and b/.vs/Ink Canvas/FileContentIndex/92cf1a99-e1a2-4b47-9d7c-1313c10009c7.vsidx differ
diff --git a/.vs/Ink Canvas/FileContentIndex/bac8aa04-4cf8-4a92-bd23-531d2bcdccc9.vsidx b/.vs/Ink Canvas/FileContentIndex/bac8aa04-4cf8-4a92-bd23-531d2bcdccc9.vsidx
new file mode 100644
index 00000000..f2098f47
Binary files /dev/null and b/.vs/Ink Canvas/FileContentIndex/bac8aa04-4cf8-4a92-bd23-531d2bcdccc9.vsidx differ
diff --git a/.vs/Ink Canvas/FileContentIndex/dd2f2f2e-6cac-4256-b9af-f63d37652881.vsidx b/.vs/Ink Canvas/FileContentIndex/dd2f2f2e-6cac-4256-b9af-f63d37652881.vsidx
new file mode 100644
index 00000000..70aef67a
Binary files /dev/null and b/.vs/Ink Canvas/FileContentIndex/dd2f2f2e-6cac-4256-b9af-f63d37652881.vsidx differ
diff --git a/.vs/Ink Canvas/v17/.futdcache.v2 b/.vs/Ink Canvas/v17/.futdcache.v2
new file mode 100644
index 00000000..aa9b49b2
Binary files /dev/null and b/.vs/Ink Canvas/v17/.futdcache.v2 differ
diff --git a/.vs/Ink Canvas/v17/.suo b/.vs/Ink Canvas/v17/.suo
new file mode 100644
index 00000000..68e42b28
Binary files /dev/null and b/.vs/Ink Canvas/v17/.suo differ
diff --git a/.vs/Ink Canvas/v17/DocumentLayout.backup.json b/.vs/Ink Canvas/v17/DocumentLayout.backup.json
new file mode 100644
index 00000000..6b64d5ef
--- /dev/null
+++ b/.vs/Ink Canvas/v17/DocumentLayout.backup.json
@@ -0,0 +1,153 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\administrator\\desktop\\icc ce\\icc-0610.2.3\\ink canvas\\mainwindow_cs\\mw_ppt.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|solutionrelative:ink canvas\\mainwindow_cs\\mw_ppt.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Ink Canvas.sln.DotSettings.user||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\administrator\\desktop\\icc ce\\icc-0610.2.3\\ink canvas\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
+ "RelativeMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|solutionrelative:ink canvas\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:privacy.txt||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Manual.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:LICENSE||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 2,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "MainWindow.xaml",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow.xaml",
+ "RelativeDocumentMoniker": "Ink Canvas\\MainWindow.xaml",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow.xaml",
+ "RelativeToolTip": "Ink Canvas\\MainWindow.xaml",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
+ "WhenOpened": "2025-05-24T13:22:56.715Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 7,
+ "Title": "Microsoft.Common.CurrentVersion.targets",
+ "DocumentMoniker": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "RelativeDocumentMoniker": "..\\..\\..\\..\\..\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "ToolTip": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "RelativeToolTip": "..\\..\\..\\..\\..\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "ViewState": "AgIAAGsJAAAAAAAAAAAQwIEJAAAEAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003801|",
+ "WhenOpened": "2025-05-24T13:06:01.053Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "MW_PPT.cs",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "RelativeToolTip": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "ViewState": "AgIAAFgAAAAAAAAAAAAUwHQAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-05-24T13:04:47.205Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "README.md",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
+ "RelativeDocumentMoniker": "README.md",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
+ "RelativeToolTip": "README.md",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
+ "WhenOpened": "2025-05-24T13:04:01.407Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "privacy.txt",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt",
+ "RelativeDocumentMoniker": "privacy.txt",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt",
+ "RelativeToolTip": "privacy.txt",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
+ "WhenOpened": "2025-05-24T13:04:01.337Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "Manual.md",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md",
+ "RelativeDocumentMoniker": "Manual.md",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md",
+ "RelativeToolTip": "Manual.md",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
+ "WhenOpened": "2025-05-24T13:04:00.986Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "LICENSE",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE",
+ "RelativeDocumentMoniker": "LICENSE",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE",
+ "RelativeToolTip": "LICENSE",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-05-24T13:04:00.902Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "Ink Canvas.sln.DotSettings.user",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user",
+ "RelativeDocumentMoniker": "Ink Canvas.sln.DotSettings.user",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user",
+ "RelativeToolTip": "Ink Canvas.sln.DotSettings.user",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003464|",
+ "WhenOpened": "2025-05-24T13:04:00.792Z",
+ "EditorCaption": ""
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/Ink Canvas/v17/DocumentLayout.json b/.vs/Ink Canvas/v17/DocumentLayout.json
new file mode 100644
index 00000000..6b64d5ef
--- /dev/null
+++ b/.vs/Ink Canvas/v17/DocumentLayout.json
@@ -0,0 +1,153 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\administrator\\desktop\\icc ce\\icc-0610.2.3\\ink canvas\\mainwindow_cs\\mw_ppt.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|solutionrelative:ink canvas\\mainwindow_cs\\mw_ppt.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Ink Canvas.sln.DotSettings.user||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\administrator\\desktop\\icc ce\\icc-0610.2.3\\ink canvas\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
+ "RelativeMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|solutionrelative:ink canvas\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:privacy.txt||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Manual.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:LICENSE||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 2,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "MainWindow.xaml",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow.xaml",
+ "RelativeDocumentMoniker": "Ink Canvas\\MainWindow.xaml",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow.xaml",
+ "RelativeToolTip": "Ink Canvas\\MainWindow.xaml",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
+ "WhenOpened": "2025-05-24T13:22:56.715Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 7,
+ "Title": "Microsoft.Common.CurrentVersion.targets",
+ "DocumentMoniker": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "RelativeDocumentMoniker": "..\\..\\..\\..\\..\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "ToolTip": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "RelativeToolTip": "..\\..\\..\\..\\..\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\Microsoft.Common.CurrentVersion.targets",
+ "ViewState": "AgIAAGsJAAAAAAAAAAAQwIEJAAAEAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003801|",
+ "WhenOpened": "2025-05-24T13:06:01.053Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "MW_PPT.cs",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "RelativeToolTip": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
+ "ViewState": "AgIAAFgAAAAAAAAAAAAUwHQAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-05-24T13:04:47.205Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "README.md",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
+ "RelativeDocumentMoniker": "README.md",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
+ "RelativeToolTip": "README.md",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
+ "WhenOpened": "2025-05-24T13:04:01.407Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "privacy.txt",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt",
+ "RelativeDocumentMoniker": "privacy.txt",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\privacy.txt",
+ "RelativeToolTip": "privacy.txt",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
+ "WhenOpened": "2025-05-24T13:04:01.337Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "Manual.md",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md",
+ "RelativeDocumentMoniker": "Manual.md",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Manual.md",
+ "RelativeToolTip": "Manual.md",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
+ "WhenOpened": "2025-05-24T13:04:00.986Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "LICENSE",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE",
+ "RelativeDocumentMoniker": "LICENSE",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\LICENSE",
+ "RelativeToolTip": "LICENSE",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-05-24T13:04:00.902Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "Ink Canvas.sln.DotSettings.user",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user",
+ "RelativeDocumentMoniker": "Ink Canvas.sln.DotSettings.user",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\Ink Canvas.sln.DotSettings.user",
+ "RelativeToolTip": "Ink Canvas.sln.DotSettings.user",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003464|",
+ "WhenOpened": "2025-05-24T13:04:00.792Z",
+ "EditorCaption": ""
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/ProjectEvaluation/ink canvas.metadata.v9.bin b/.vs/ProjectEvaluation/ink canvas.metadata.v9.bin
new file mode 100644
index 00000000..e8f31112
Binary files /dev/null and b/.vs/ProjectEvaluation/ink canvas.metadata.v9.bin differ
diff --git a/.vs/ProjectEvaluation/ink canvas.projects.v9.bin b/.vs/ProjectEvaluation/ink canvas.projects.v9.bin
new file mode 100644
index 00000000..f28260b8
Binary files /dev/null and b/.vs/ProjectEvaluation/ink canvas.projects.v9.bin differ
diff --git a/.vs/ProjectEvaluation/ink canvas.strings.v9.bin b/.vs/ProjectEvaluation/ink canvas.strings.v9.bin
new file mode 100644
index 00000000..d0f91645
Binary files /dev/null and b/.vs/ProjectEvaluation/ink canvas.strings.v9.bin differ
diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json
new file mode 100644
index 00000000..6b611411
--- /dev/null
+++ b/.vs/VSWorkspaceState.json
@@ -0,0 +1,6 @@
+{
+ "ExpandedNodes": [
+ ""
+ ],
+ "PreviewInSolutionExplorer": false
+}
\ No newline at end of file
diff --git a/.vs/icc-0610.2.2/FileContentIndex/777fbe68-06ce-4859-8b8d-d763f120f2c0.vsidx b/.vs/icc-0610.2.2/FileContentIndex/777fbe68-06ce-4859-8b8d-d763f120f2c0.vsidx
new file mode 100644
index 00000000..69e6ba72
Binary files /dev/null and b/.vs/icc-0610.2.2/FileContentIndex/777fbe68-06ce-4859-8b8d-d763f120f2c0.vsidx differ
diff --git a/.vs/icc-0610.2.2/FileContentIndex/95c8e0b1-8689-4e23-84a6-a09fc53d1455.vsidx b/.vs/icc-0610.2.2/FileContentIndex/95c8e0b1-8689-4e23-84a6-a09fc53d1455.vsidx
new file mode 100644
index 00000000..072d526b
Binary files /dev/null and b/.vs/icc-0610.2.2/FileContentIndex/95c8e0b1-8689-4e23-84a6-a09fc53d1455.vsidx differ
diff --git a/.vs/icc-0610.2.2/v17/.wsuo b/.vs/icc-0610.2.2/v17/.wsuo
new file mode 100644
index 00000000..187600a8
Binary files /dev/null and b/.vs/icc-0610.2.2/v17/.wsuo differ
diff --git a/.vs/icc-0610.2.2/v17/DocumentLayout.backup.json b/.vs/icc-0610.2.2/v17/DocumentLayout.backup.json
new file mode 100644
index 00000000..27e2d25f
--- /dev/null
+++ b/.vs/icc-0610.2.2/v17/DocumentLayout.backup.json
@@ -0,0 +1,290 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "System.ValueTuple.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\System.ValueTuple.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\System.ValueTuple.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:48.138Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "Settings.json",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Settings.json",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Settings.json",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
+ "WhenOpened": "2025-05-24T13:02:44.878Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "OSVersionExt.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\OSVersionExt.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\OSVersionExt.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.837Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "Office.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Office.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Office.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.774Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "NHotkey.Wpf.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.718Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "NHotkey.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\NHotkey.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\NHotkey.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.662Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "Newtonsoft.Json.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.589Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 7,
+ "Title": "Microsoft.Office.Interop.PowerPoint.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.932Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 8,
+ "Title": "MdXaml.Plugins.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.838Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 9,
+ "Title": "MdXaml.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\MdXaml.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\MdXaml.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.776Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 10,
+ "Title": "iNKORE.UI.WPF.Modern.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.573Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 11,
+ "Title": "iNKORE.UI.WPF.Modern.Controls.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.432Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 12,
+ "Title": "iNKORE.UI.WPF.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:42.807Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 13,
+ "Title": "InkCanvasForClass.exe.config",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000601|",
+ "WhenOpened": "2025-05-24T13:02:27.288Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 14,
+ "Title": "ICSharpCode.AvalonEdit.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.847Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 15,
+ "Title": "IAWinFX.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IAWinFX.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IAWinFX.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.816Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 16,
+ "Title": "IALoader.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IALoader.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IALoader.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.784Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 17,
+ "Title": "IACore.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IACore.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IACore.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.753Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 18,
+ "Title": "Hardcodet.NotifyIcon.Wpf.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.113Z"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/icc-0610.2.2/v17/DocumentLayout.json b/.vs/icc-0610.2.2/v17/DocumentLayout.json
new file mode 100644
index 00000000..10391208
--- /dev/null
+++ b/.vs/icc-0610.2.2/v17/DocumentLayout.json
@@ -0,0 +1,338 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "icc.png - PNG [256x256, 32 \u4F4D, PNG]",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\icc.png",
+ "RelativeDocumentMoniker": "icc.png",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\icc.png - PNG [256x256, 32 \u4F4D, PNG]",
+ "RelativeToolTip": "icc.png - PNG [256x256, 32 \u4F4D, PNG]",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001533|",
+ "WhenOpened": "2025-05-24T13:03:45.63Z",
+ "EditorCaption": " - PNG [256x256, 32 \u4F4D, PNG]"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "AutomaticUpdateVersionControl.txt",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\AutomaticUpdateVersionControl.txt",
+ "RelativeDocumentMoniker": "AutomaticUpdateVersionControl.txt",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\AutomaticUpdateVersionControl.txt",
+ "RelativeToolTip": "AutomaticUpdateVersionControl.txt",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
+ "WhenOpened": "2025-05-24T13:03:45.517Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": ".gitignore",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\.gitignore",
+ "RelativeDocumentMoniker": ".gitignore",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.2\\.gitignore",
+ "RelativeToolTip": ".gitignore",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-05-24T13:03:43.13Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "System.ValueTuple.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\System.ValueTuple.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\System.ValueTuple.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\System.ValueTuple.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:48.138Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "Settings.json",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Settings.json",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Settings.json",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Settings.json",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
+ "WhenOpened": "2025-05-24T13:02:44.878Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "OSVersionExt.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\OSVersionExt.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\OSVersionExt.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\OSVersionExt.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.837Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "Office.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Office.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Office.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Office.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.774Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 7,
+ "Title": "NHotkey.Wpf.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\NHotkey.Wpf.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.718Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 8,
+ "Title": "NHotkey.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\NHotkey.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\NHotkey.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\NHotkey.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.662Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 9,
+ "Title": "Newtonsoft.Json.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Newtonsoft.Json.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:44.589Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 10,
+ "Title": "Microsoft.Office.Interop.PowerPoint.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Microsoft.Office.Interop.PowerPoint.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.932Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 11,
+ "Title": "MdXaml.Plugins.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\MdXaml.Plugins.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.838Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 12,
+ "Title": "MdXaml.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\MdXaml.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\MdXaml.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\MdXaml.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.776Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 13,
+ "Title": "iNKORE.UI.WPF.Modern.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.573Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 14,
+ "Title": "iNKORE.UI.WPF.Modern.Controls.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.Modern.Controls.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:43.432Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 15,
+ "Title": "iNKORE.UI.WPF.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\iNKORE.UI.WPF.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:42.807Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 16,
+ "Title": "InkCanvasForClass.exe.config",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\InkCanvasForClass.exe.config",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000601|",
+ "WhenOpened": "2025-05-24T13:02:27.288Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 17,
+ "Title": "ICSharpCode.AvalonEdit.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\ICSharpCode.AvalonEdit.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.847Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 18,
+ "Title": "IAWinFX.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IAWinFX.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IAWinFX.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IAWinFX.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.816Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 19,
+ "Title": "IALoader.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IALoader.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IALoader.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IALoader.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.784Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 20,
+ "Title": "IACore.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\IACore.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\IACore.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\IACore.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.753Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 21,
+ "Title": "Hardcodet.NotifyIcon.Wpf.dll",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "RelativeDocumentMoniker": "..\\..\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "RelativeToolTip": "..\\..\\InkCanvasForClass\\Hardcodet.NotifyIcon.Wpf.dll",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001697|",
+ "WhenOpened": "2025-05-24T13:02:22.113Z"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/icc-0610.2.2/v17/workspaceFileList.bin b/.vs/icc-0610.2.2/v17/workspaceFileList.bin
new file mode 100644
index 00000000..8d13c3ee
Binary files /dev/null and b/.vs/icc-0610.2.2/v17/workspaceFileList.bin differ
diff --git a/.vs/icc-0610.2.3/FileContentIndex/29319a2c-7faa-4ee5-8d24-17c238ca803e.vsidx b/.vs/icc-0610.2.3/FileContentIndex/29319a2c-7faa-4ee5-8d24-17c238ca803e.vsidx
new file mode 100644
index 00000000..b74c61fd
Binary files /dev/null and b/.vs/icc-0610.2.3/FileContentIndex/29319a2c-7faa-4ee5-8d24-17c238ca803e.vsidx differ
diff --git a/.vs/icc-0610.2.3/FileContentIndex/34c6dd5d-6075-49b2-ab2c-4e8d079d036e.vsidx b/.vs/icc-0610.2.3/FileContentIndex/34c6dd5d-6075-49b2-ab2c-4e8d079d036e.vsidx
new file mode 100644
index 00000000..5a4c68f0
Binary files /dev/null and b/.vs/icc-0610.2.3/FileContentIndex/34c6dd5d-6075-49b2-ab2c-4e8d079d036e.vsidx differ
diff --git a/.vs/icc-0610.2.3/FileContentIndex/7a5efc25-7ca5-4a7f-a0e0-0e8bf3996d0a.vsidx b/.vs/icc-0610.2.3/FileContentIndex/7a5efc25-7ca5-4a7f-a0e0-0e8bf3996d0a.vsidx
new file mode 100644
index 00000000..b23372c0
Binary files /dev/null and b/.vs/icc-0610.2.3/FileContentIndex/7a5efc25-7ca5-4a7f-a0e0-0e8bf3996d0a.vsidx differ
diff --git a/.vs/icc-0610.2.3/FileContentIndex/9947b71c-9e8d-4a20-80aa-4e44b1609bf2.vsidx b/.vs/icc-0610.2.3/FileContentIndex/9947b71c-9e8d-4a20-80aa-4e44b1609bf2.vsidx
new file mode 100644
index 00000000..da5eb89f
Binary files /dev/null and b/.vs/icc-0610.2.3/FileContentIndex/9947b71c-9e8d-4a20-80aa-4e44b1609bf2.vsidx differ
diff --git a/.vs/icc-0610.2.3/FileContentIndex/e1d7dcd2-b73f-4c9a-b51c-9ba3cb8d4cbb.vsidx b/.vs/icc-0610.2.3/FileContentIndex/e1d7dcd2-b73f-4c9a-b51c-9ba3cb8d4cbb.vsidx
new file mode 100644
index 00000000..8e02f030
Binary files /dev/null and b/.vs/icc-0610.2.3/FileContentIndex/e1d7dcd2-b73f-4c9a-b51c-9ba3cb8d4cbb.vsidx differ
diff --git a/.vs/icc-0610.2.3/v17/.wsuo b/.vs/icc-0610.2.3/v17/.wsuo
new file mode 100644
index 00000000..a7e1b305
Binary files /dev/null and b/.vs/icc-0610.2.3/v17/.wsuo differ
diff --git a/.vs/icc-0610.2.3/v17/DocumentLayout.backup.json b/.vs/icc-0610.2.3/v17/DocumentLayout.backup.json
new file mode 100644
index 00000000..48317cfd
--- /dev/null
+++ b/.vs/icc-0610.2.3/v17/DocumentLayout.backup.json
@@ -0,0 +1,67 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "icc.png",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png",
+ "RelativeDocumentMoniker": "icc.png",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png",
+ "RelativeToolTip": "icc.png",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001533|",
+ "WhenOpened": "2025-05-24T13:12:49.619Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "AutomaticUpdateVersionControl.txt",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt",
+ "RelativeDocumentMoniker": "AutomaticUpdateVersionControl.txt",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt",
+ "RelativeToolTip": "AutomaticUpdateVersionControl.txt",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
+ "WhenOpened": "2025-05-24T13:12:49.575Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": ".gitignore",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore",
+ "RelativeDocumentMoniker": ".gitignore",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore",
+ "RelativeToolTip": ".gitignore",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-05-24T13:12:49.025Z"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/icc-0610.2.3/v17/DocumentLayout.json b/.vs/icc-0610.2.3/v17/DocumentLayout.json
new file mode 100644
index 00000000..b53370fc
--- /dev/null
+++ b/.vs/icc-0610.2.3/v17/DocumentLayout.json
@@ -0,0 +1,72 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:icc.png||{177559E0-D141-11D0-92DF-00A0C9138C45}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:AutomaticUpdateVersionControl.txt||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 1,
+ "Children": [
+ {
+ "$type": "Bookmark",
+ "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "icc.png - PNG [1328x1328, 32 \u4F4D, PNG]",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png",
+ "RelativeDocumentMoniker": "icc.png",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\icc.png - PNG [1328x1328, 32 \u4F4D, PNG]",
+ "RelativeToolTip": "icc.png - PNG [1328x1328, 32 \u4F4D, PNG]",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001533|",
+ "WhenOpened": "2025-05-24T13:12:49.619Z",
+ "EditorCaption": " - PNG [1328x1328, 32 \u4F4D, PNG]"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "AutomaticUpdateVersionControl.txt",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt",
+ "RelativeDocumentMoniker": "AutomaticUpdateVersionControl.txt",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\AutomaticUpdateVersionControl.txt",
+ "RelativeToolTip": "AutomaticUpdateVersionControl.txt",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
+ "WhenOpened": "2025-05-24T13:12:49.575Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": ".gitignore",
+ "DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore",
+ "RelativeDocumentMoniker": ".gitignore",
+ "ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\.gitignore",
+ "RelativeToolTip": ".gitignore",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-05-24T13:12:49.025Z"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/icc-0610.2.3/v17/workspaceFileList.bin b/.vs/icc-0610.2.3/v17/workspaceFileList.bin
new file mode 100644
index 00000000..7eed11ec
Binary files /dev/null and b/.vs/icc-0610.2.3/v17/workspaceFileList.bin differ
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
new file mode 100644
index 00000000..c3f8b831
Binary files /dev/null and b/.vs/slnx.sqlite differ
diff --git a/AutomaticUpdateVersionControl.txt b/AutomaticUpdateVersionControl.txt
new file mode 100644
index 00000000..32f3eaad
--- /dev/null
+++ b/AutomaticUpdateVersionControl.txt
@@ -0,0 +1 @@
+5.0.1
\ No newline at end of file
diff --git a/Images/icc1.png b/Images/icc1.png
new file mode 100644
index 00000000..295d26a6
Binary files /dev/null and b/Images/icc1.png differ
diff --git a/Images/icc2.png b/Images/icc2.png
new file mode 100644
index 00000000..e47394fb
Binary files /dev/null and b/Images/icc2.png differ
diff --git a/Ink Canvas.sln b/Ink Canvas.sln
new file mode 100644
index 00000000..f100002a
--- /dev/null
+++ b/Ink Canvas.sln
@@ -0,0 +1,49 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33530.505
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InkCanvasForClass", "Ink Canvas\InkCanvasForClass.csproj", "{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|ARM.Build.0 = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|x64.ActiveCfg = Debug|x64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|x64.Build.0 = Debug|x64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Debug|x86.Build.0 = Debug|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|ARM.ActiveCfg = Release|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|ARM.Build.0 = Release|Any CPU
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|ARM64.Build.0 = Release|ARM64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|x64.ActiveCfg = Release|x64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|x64.Build.0 = Release|x64
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|x86.ActiveCfg = Release|x86
+ {8D0EDFC7-F974-4571-BC49-6F3A6653FE81}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {89B9DD11-110D-428C-AB08-859B7F4B4E19}
+ EndGlobalSection
+EndGlobal
diff --git a/Ink Canvas.sln.DotSettings.user b/Ink Canvas.sln.DotSettings.user
new file mode 100644
index 00000000..5ef2d603
--- /dev/null
+++ b/Ink Canvas.sln.DotSettings.user
@@ -0,0 +1,2 @@
+
+ WARNING
\ No newline at end of file
diff --git a/Ink Canvas/.vs/Ink Canvas.csproj.dtbcache.json b/Ink Canvas/.vs/Ink Canvas.csproj.dtbcache.json
new file mode 100644
index 00000000..e9ad49bb
--- /dev/null
+++ b/Ink Canvas/.vs/Ink Canvas.csproj.dtbcache.json
@@ -0,0 +1 @@
+{"RootPath":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas","ProjectFileName":"Ink Canvas.csproj","Configuration":"Release|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Helpers\\AutoUpdateHelper.cs"},{"SourceFile":"Helpers\\DelAutoSavedFiles.cs"},{"SourceFile":"Helpers\\ForegroundWindowInfo.cs"},{"SourceFile":"ChangeLogWindow.xaml.cs"},{"SourceFile":"OperatingGuideWindow.xaml.cs"},{"SourceFile":"CycleProcessBar.xaml.cs"},{"SourceFile":"Helpers\\AnimationsHelper.cs"},{"SourceFile":"Helpers\\InkRecognizeHelper.cs"},{"SourceFile":"Helpers\\LogHelper.cs"},{"SourceFile":"Helpers\\MultiTouchInput.cs"},{"SourceFile":"Helpers\\SoftwareLauncher.cs"},{"SourceFile":"Helpers\\TimeMachine.cs"},{"SourceFile":"Helpers\\Converters.cs"},{"SourceFile":"Helpers\\WinTabWindowsChecker.cs"},{"SourceFile":"NamesInputWindow.xaml.cs"},{"SourceFile":"RandWindow.xaml.cs"},{"SourceFile":"YesOrNoNotificationWindow.xaml.cs"},{"SourceFile":"Settings.cs"},{"SourceFile":"SettingsPage.xaml.cs"},{"SourceFile":"CountdownTimerWindow.xaml.cs"},{"SourceFile":"App.xaml.cs"},{"SourceFile":"Helpers\\Hotkey.cs"},{"SourceFile":"MainWindow.xaml.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"Properties\\Resources.Designer.cs"},{"SourceFile":"Properties\\Settings.Designer.cs"},{"SourceFile":"obj\\Release\\.NETFramework,Version=v4.7.2.AssemblyAttributes.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\ChangeLogWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\OperatingGuideWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\CycleProcessBar.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\MainWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\NamesInputWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\RandWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\YesOrNoNotificationWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\SettingsPage.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\CountdownTimerWindow.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\App.g.cs"},{"SourceFile":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\obj\\Release\\GeneratedInternalTypeHelper.g.cs"}],"References":[{"Reference":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\IACore.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\IALoader.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\IAWinFX.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\inkore.ui.wpf.modern\\0.9.26.3\\lib\\net452\\iNKORE.UI.WPF.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\inkore.ui.wpf.modern\\0.9.26.3\\lib\\net452\\iNKORE.UI.WPF.Modern.Controls.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\inkore.ui.wpf.modern\\0.9.26.3\\lib\\net452\\iNKORE.UI.WPF.Modern.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\microsoft.office.interop.powerpoint\\15.0.4420.1018\\lib\\net20\\Microsoft.Office.Interop.PowerPoint.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\Microsoft.VisualBasic.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\Facades\\netstandard.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\newtonsoft.json\\13.0.3\\lib\\net45\\Newtonsoft.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\microsoftofficecore\\15.0.0\\lib\\net35\\Office.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\PresentationCore.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\PresentationFramework.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Data.DataSetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Data.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Drawing.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Net.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Administrator\\.nuget\\packages\\system.valuetuple\\4.5.0\\ref\\net47\\System.ValueTuple.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Windows.Forms.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Xaml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\System.Xml.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\UIAutomationClient.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\UIAutomationTypes.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\WindowsBase.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.7.2\\WindowsFormsIntegration.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\bin\\Release\\Ink Canvas Annotation.exe","OutputItemRelativePath":"Ink Canvas Annotation.exe"},{"OutputItemFullPath":"E:\\projects\\VS source\\repos\\Ink-Canvas\\Ink Canvas\\bin\\Release\\Ink Canvas Annotation.pdb","OutputItemRelativePath":"Ink Canvas Annotation.pdb"}],"CopyToOutputEntries":[]}
\ No newline at end of file
diff --git a/Ink Canvas/App.config b/Ink Canvas/App.config
new file mode 100644
index 00000000..e778ef70
--- /dev/null
+++ b/Ink Canvas/App.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Ink Canvas/App.xaml b/Ink Canvas/App.xaml
new file mode 100644
index 00000000..6575dacc
--- /dev/null
+++ b/Ink Canvas/App.xaml
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs
new file mode 100644
index 00000000..c1fd08cc
--- /dev/null
+++ b/Ink Canvas/App.xaml.cs
@@ -0,0 +1,79 @@
+using Hardcodet.Wpf.TaskbarNotification;
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Windows;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+using MessageBox = System.Windows.MessageBox;
+using Window = System.Windows.Window;
+
+namespace Ink_Canvas
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ System.Threading.Mutex mutex;
+
+ public static string[] StartArgs = null;
+ public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\";
+
+ public App()
+ {
+ this.Startup += new StartupEventHandler(App_Startup);
+ this.DispatcherUnhandledException += App_DispatcherUnhandledException;
+ }
+
+ private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
+ {
+ Ink_Canvas.MainWindow.ShowNewMessage("抱歉,出现未预期的异常,可能导致 InkCanvasForClass 运行不稳定。\n建议保存墨迹后重启应用。", true);
+ LogHelper.NewLog(e.Exception.ToString());
+ e.Handled = true;
+ }
+
+ private TaskbarIcon _taskbar;
+
+ void App_Startup(object sender, StartupEventArgs e)
+ {
+ /*if (!StoreHelper.IsStoreApp) */RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
+
+ LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString()));
+
+ bool ret;
+ mutex = new System.Threading.Mutex(true, "InkCanvasForClass", out ret);
+
+ if (!ret && !e.Args.Contains("-m")) //-m multiple
+ {
+ LogHelper.NewLog("Detected existing instance");
+ MessageBox.Show("已有一个程序实例正在运行");
+ LogHelper.NewLog("Ink Canvas automatically closed");
+ Environment.Exit(0);
+ }
+
+ _taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
+
+ StartArgs = e.Args;
+ }
+
+ private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
+ {
+ try
+ {
+ if (System.Windows.Forms.SystemInformation.MouseWheelScrollLines == -1)
+ e.Handled = false;
+ else
+ try
+ {
+ ScrollViewerEx SenderScrollViewer = (ScrollViewerEx)sender;
+ SenderScrollViewer.ScrollToVerticalOffset(SenderScrollViewer.VerticalOffset - e.Delta * 10 * System.Windows.Forms.SystemInformation.MouseWheelScrollLines / (double)120);
+ e.Handled = true;
+ }
+ catch { }
+ }
+ catch { }
+ }
+ }
+}
diff --git a/Ink Canvas/AssemblyInfo.cs b/Ink Canvas/AssemblyInfo.cs
new file mode 100644
index 00000000..0a156b5e
--- /dev/null
+++ b/Ink Canvas/AssemblyInfo.cs
@@ -0,0 +1,53 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("InkCanvasForClass")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Dubi906w")]
+[assembly: AssemblyProduct("InkCanvasForClass")]
+[assembly: AssemblyCopyright("Copyright © HARKOTEK Studio 2024")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[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)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("5.0.2.0")]
+[assembly: AssemblyFileVersion("5.0.2.0")]
diff --git a/Ink Canvas/Helpers/AnimationsHelper.cs b/Ink Canvas/Helpers/AnimationsHelper.cs
new file mode 100644
index 00000000..b6fe0335
--- /dev/null
+++ b/Ink Canvas/Helpers/AnimationsHelper.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+
+namespace Ink_Canvas.Helpers
+{
+ internal class AnimationsHelper
+ {
+ public static void ShowWithFadeIn(UIElement element, double duration = 0.15)
+ {
+ if (element.Visibility == Visibility.Visible) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 渐变动画
+ var fadeInAnimation = new DoubleAnimation
+ {
+ From = 0.5,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
+
+ sb.Children.Add(fadeInAnimation);
+
+ element.Visibility = Visibility.Visible;
+
+ sb.Begin((FrameworkElement)element);
+ }
+
+ public static void ShowWithSlideFromBottomAndFade(UIElement element, double duration = 0.15)
+ {
+ try
+ {
+ if (element.Visibility == Visibility.Visible) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 渐变动画
+ var fadeInAnimation = new DoubleAnimation
+ {
+ From = 0.5,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ fadeInAnimation.EasingFunction = new CubicEase();
+
+ Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
+
+ // 滑动动画
+ var slideAnimation = new DoubleAnimation
+ {
+ From = element.RenderTransform.Value.OffsetY + 10, // 滑动距离
+ To = 0,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(slideAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
+
+ slideAnimation.EasingFunction = new CubicEase();
+
+ sb.Children.Add(fadeInAnimation);
+ sb.Children.Add(slideAnimation);
+
+ element.Visibility = Visibility.Visible;
+ element.RenderTransform = new TranslateTransform();
+
+ sb.Begin((FrameworkElement)element);
+ }
+ catch { }
+ }
+
+ public static void ShowWithSlideFromLeftAndFade(UIElement element, double duration = 0.25)
+ {
+ try
+ {
+ if (element.Visibility == Visibility.Visible) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 渐变动画
+ var fadeInAnimation = new DoubleAnimation
+ {
+ From = 0.5,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
+
+ // 滑动动画
+ var slideAnimation = new DoubleAnimation
+ {
+ From = element.RenderTransform.Value.OffsetX - 20, // 滑动距离
+ To = 0,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(slideAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
+
+ sb.Children.Add(fadeInAnimation);
+ sb.Children.Add(slideAnimation);
+
+ element.Visibility = Visibility.Visible;
+ element.RenderTransform = new TranslateTransform();
+
+ sb.Begin((FrameworkElement)element);
+ }
+ catch { }
+ }
+
+ public static void ShowWithScaleFromLeft(UIElement element, double duration = 0.2)
+ {
+ try
+ {
+ if (element.Visibility == Visibility.Visible) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 水平方向的缩放动画
+ var scaleXAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
+
+ // 垂直方向的缩放动画
+ var scaleYAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ scaleYAnimation.EasingFunction = new CubicEase();
+ scaleXAnimation.EasingFunction = new CubicEase();
+ Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
+
+ sb.Children.Add(scaleXAnimation);
+ sb.Children.Add(scaleYAnimation);
+
+ element.Visibility = Visibility.Visible;
+ element.RenderTransformOrigin = new Point(0, 0.5); // 左侧中心点为基准
+ element.RenderTransform = new ScaleTransform(0, 0);
+
+ sb.Begin((FrameworkElement)element);
+ }
+ catch { }
+ }
+
+ public static void ShowWithScaleFromRight(UIElement element, double duration = 0.2)
+ {
+ try
+ {
+ if (element.Visibility == Visibility.Visible) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 水平方向的缩放动画
+ var scaleXAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
+
+ // 垂直方向的缩放动画
+ var scaleYAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = 1,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
+
+ scaleYAnimation.EasingFunction = new CubicEase();
+ scaleXAnimation.EasingFunction = new CubicEase();
+
+ sb.Children.Add(scaleXAnimation);
+ sb.Children.Add(scaleYAnimation);
+
+ element.Visibility = Visibility.Visible;
+ element.RenderTransformOrigin = new Point(1, 0.5); // 右侧中心点为基准
+ element.RenderTransform = new ScaleTransform(0, 0);
+
+ sb.Begin((FrameworkElement)element);
+ }
+ catch { }
+ }
+
+ public static void HideWithSlideAndFade(UIElement element, double duration = 0.15)
+ {
+ try
+ {
+ if (element.Visibility == Visibility.Collapsed) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 渐变动画
+ var fadeOutAnimation = new DoubleAnimation
+ {
+ From = 1,
+ To = 0,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ fadeOutAnimation.EasingFunction = new CubicEase();
+ Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(UIElement.OpacityProperty));
+
+ // 滑动动画
+ var slideAnimation = new DoubleAnimation
+ {
+ From = 0,
+ To = element.RenderTransform.Value.OffsetY + 10, // 滑动距离
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ slideAnimation.EasingFunction = new CubicEase();
+
+ Storyboard.SetTargetProperty(slideAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
+
+ sb.Children.Add(fadeOutAnimation);
+ sb.Children.Add(slideAnimation);
+
+ sb.Completed += (s, e) =>
+ {
+ element.Visibility = Visibility.Collapsed;
+ };
+
+ element.RenderTransform = new TranslateTransform();
+ sb.Begin((FrameworkElement)element);
+ }
+ catch { }
+ }
+
+ public static void HideWithFadeOut(UIElement element, double duration = 0.15)
+ {
+ if (element.Visibility == Visibility.Collapsed) return;
+
+ if (element == null)
+ throw new ArgumentNullException(nameof(element));
+
+ var sb = new Storyboard();
+
+ // 渐变动画
+ var fadeOutAnimation = new DoubleAnimation
+ {
+ From = 1,
+ To = 0,
+ Duration = TimeSpan.FromSeconds(duration)
+ };
+ Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(UIElement.OpacityProperty));
+
+ sb.Children.Add(fadeOutAnimation);
+
+ sb.Completed += (s, e) =>
+ {
+ element.Visibility = Visibility.Collapsed;
+ };
+
+ sb.Begin((FrameworkElement)element);
+ }
+
+ }
+}
diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs
new file mode 100644
index 00000000..7bdee88f
--- /dev/null
+++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs
@@ -0,0 +1,258 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Reflection;
+using System.Windows;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows.Controls;
+
+namespace Ink_Canvas.Helpers
+{
+ internal class AutoUpdateHelper
+ {
+ public static async Task CheckForUpdates(string proxy = null)
+ {
+ try
+ {
+ string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ string remoteAddress = proxy;
+ remoteAddress += "https://gitea.bliemhax.com/kriastans/InkCanvasForClass/raw/branch/master/AutomaticUpdateVersionControl.txt";
+ string remoteVersion = await GetRemoteVersion(remoteAddress);
+
+ if (remoteVersion != null)
+ {
+ Version local = new Version(localVersion);
+ Version remote = new Version(remoteVersion);
+ if (remote > local)
+ {
+ LogHelper.WriteLogToFile("AutoUpdate | New version Availble: " + remoteVersion);
+ return remoteVersion;
+ }
+ else return null;
+ }
+ else
+ {
+ LogHelper.WriteLogToFile("Failed to retrieve remote version.", LogHelper.LogType.Error);
+ return null;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"AutoUpdate | Error: {ex.Message}");
+ return null;
+ }
+ }
+
+ public static async Task GetRemoteVersion(string fileUrl)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ try
+ {
+ HttpResponseMessage response = await client.GetAsync(fileUrl);
+ response.EnsureSuccessStatusCode();
+
+ return await response.Content.ReadAsStringAsync();
+ }
+ catch (HttpRequestException ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error);
+ }
+
+ return null;
+ }
+ }
+
+ private static string updatesFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ink Canvas Annotation", "AutoUpdate");
+ private static string statusFilePath = null;
+
+ public static async Task DownloadSetupFileAndSaveStatus(string version, string proxy = "")
+ {
+ try
+ {
+ statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt");
+
+ if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
+ {
+ LogHelper.WriteLogToFile("AutoUpdate | Setup file already downloaded.");
+ return true;
+ }
+
+ string downloadUrl = $"{proxy}https://github.com/ChangSakura/Ink-Canvas/releases/download/v{version}/Ink.Canvas.Annotation.V{version}.Setup.exe";
+
+ SaveDownloadStatus(false);
+ await DownloadFile(downloadUrl, $"{updatesFolderPath}\\Ink.Canvas.Annotation.V{version}.Setup.exe");
+ SaveDownloadStatus(true);
+
+ LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded.");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | Error downloading and installing update: {ex.Message}", LogHelper.LogType.Error);
+
+ SaveDownloadStatus(false);
+ return false;
+ }
+ }
+
+ private static async Task DownloadFile(string fileUrl, string destinationPath)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ try
+ {
+ HttpResponseMessage response = await client.GetAsync(fileUrl);
+ response.EnsureSuccessStatusCode();
+
+ using (FileStream fileStream = File.Create(destinationPath))
+ {
+ await response.Content.CopyToAsync(fileStream);
+ fileStream.Close();
+ }
+ }
+ catch (HttpRequestException ex)
+ {
+ Console.WriteLine($"AutoUpdate | HTTP request error: {ex.Message}");
+ throw;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"AutoUpdate | Error: {ex.Message}");
+ throw;
+ }
+ }
+ }
+
+ private static void SaveDownloadStatus(bool isSuccess)
+ {
+ try
+ {
+ if (statusFilePath == null) return;
+
+ string directory = Path.GetDirectoryName(statusFilePath);
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ File.WriteAllText(statusFilePath, isSuccess.ToString());
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | Error saving download status: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ public static void InstallNewVersionApp(string version, bool isInSilence)
+ {
+ try
+ {
+ string setupFilePath = Path.Combine(updatesFolderPath, $"Ink.Canvas.Annotation.V{version}.Setup.exe");
+
+ if (!File.Exists(setupFilePath))
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | Setup file not found: {setupFilePath}", LogHelper.LogType.Error);
+ return;
+ }
+
+ string InstallCommand = $"\"{setupFilePath}\" /SILENT";
+ if (isInSilence) InstallCommand += " /VERYSILENT";
+ ExecuteCommandLine(InstallCommand);
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ Application.Current.Shutdown();
+ });
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate | Error installing update: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+
+ private static void ExecuteCommandLine(string command)
+ {
+ try
+ {
+ ProcessStartInfo processStartInfo = new ProcessStartInfo
+ {
+ FileName = "cmd.exe",
+ Arguments = $"/c {command}",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using (Process process = new Process { StartInfo = processStartInfo })
+ {
+ process.Start();
+ Application.Current.Shutdown();
+ /*process.WaitForExit();
+ int exitCode = process.ExitCode;*/
+ }
+ }
+ catch { }
+ }
+
+ public static void DeleteUpdatesFolder()
+ {
+ try
+ {
+ if (Directory.Exists(updatesFolderPath))
+ {
+ Directory.Delete(updatesFolderPath, true);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"AutoUpdate clearing| Error deleting updates folder: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+ }
+
+ internal class AutoUpdateWithSilenceTimeComboBox
+ {
+ public static ObservableCollection Hours { get; set; } = new ObservableCollection();
+ public static ObservableCollection Minutes { get; set; } = new ObservableCollection();
+
+ public static void InitializeAutoUpdateWithSilenceTimeComboBoxOptions(ComboBox startTimeComboBox, ComboBox endTimeComboBox)
+ {
+ for (int hour = 0; hour <= 23; ++hour)
+ {
+ Hours.Add(hour.ToString("00"));
+ }
+ for (int minute = 0; minute <= 59; minute += 20)
+ {
+ Minutes.Add(minute.ToString("00"));
+ }
+ startTimeComboBox.ItemsSource = Hours.SelectMany(h => Minutes.Select(m => $"{h}:{m}"));
+ endTimeComboBox.ItemsSource = Hours.SelectMany(h => Minutes.Select(m => $"{h}:{m}"));
+ }
+
+ public static bool CheckIsInSilencePeriod(string startTime, string endTime)
+ {
+ if (startTime == endTime) return true;
+ DateTime currentTime = DateTime.Now;
+
+ DateTime StartTime = DateTime.ParseExact(startTime, "HH:mm", null);
+ DateTime EndTime = DateTime.ParseExact(endTime, "HH:mm", null);
+ if (StartTime <= EndTime)
+ { // 单日时间段
+ return currentTime >= StartTime && currentTime <= EndTime;
+ }
+ else
+ { // 跨越两天的时间段
+ return currentTime >= StartTime || currentTime <= EndTime;
+ }
+ }
+ }
+}
diff --git a/Ink Canvas/Helpers/Converters.cs b/Ink Canvas/Helpers/Converters.cs
new file mode 100644
index 00000000..1d219958
--- /dev/null
+++ b/Ink Canvas/Helpers/Converters.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Ink_Canvas.Converter
+{
+ public class BooleanToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if ((bool)value == true)
+ {
+ return Visibility.Visible;
+ }
+ else
+ {
+ return Visibility.Collapsed;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if ((bool)value == true)
+ {
+ return Visibility.Visible;
+ }
+ else
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ }
+ public class VisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ Visibility visibility = (Visibility)value;
+ if (visibility == Visibility.Visible)
+ {
+ return Visibility.Collapsed;
+ }
+ else
+ {
+ return Visibility.Visible;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ Visibility visibility = (Visibility)value;
+ if (visibility == Visibility.Visible)
+ {
+ return Visibility.Collapsed;
+ }
+ else
+ {
+ return Visibility.Visible;
+ }
+ }
+ }
+
+ public class IntNumberToString : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if ((double)value == 0)
+ {
+ return "无限制";
+ }
+ else
+ {
+ return ((double)value).ToString() + "人";
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if ((double)value == 0)
+ {
+ return "无限制";
+ }
+ else
+ {
+ return ((double)value).ToString() + "人";
+ }
+ }
+ }
+
+ public class IntNumberToString2 : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if ((double)value == 0)
+ {
+ return "自动截图";
+ }
+ else
+ {
+ return ((double)value).ToString() + "条";
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if ((double)value == 0)
+ {
+ return "自动截图";
+ }
+ else
+ {
+ return ((double)value).ToString() + "条";
+ }
+ }
+ }
+
+ public class IsEnabledToOpacityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ bool isChecked = (bool)value;
+ if (isChecked == true)
+ {
+ return 1d;
+ }
+ else
+ {
+ return 0.35;
+ }
+ }
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); }
+ }
+}
diff --git a/Ink Canvas/Helpers/DelAutoSavedFiles.cs b/Ink Canvas/Helpers/DelAutoSavedFiles.cs
new file mode 100644
index 00000000..2071ed89
--- /dev/null
+++ b/Ink Canvas/Helpers/DelAutoSavedFiles.cs
@@ -0,0 +1,51 @@
+using System;
+using System.IO;
+using System.Windows;
+
+namespace Ink_Canvas.Helpers {
+ internal class DelAutoSavedFiles {
+ public static void DeleteFilesOlder(string directoryPath, int daysThreshold) {
+ string[] extensionsToDel = { ".icstk", ".png" };
+ if (Directory.Exists(directoryPath)) {
+ // 获取目录中的所有子目录
+ string[] subDirectories = Directory.GetDirectories(directoryPath, "*", SearchOption.AllDirectories);
+ foreach (string subDirectory in subDirectories) {
+ try {
+ // 获取子目录下的所有文件
+ string[] files = Directory.GetFiles(subDirectory);
+ foreach (string filePath in files) {
+ // 获取文件的创建日期
+ DateTime creationDate = File.GetCreationTime(filePath);
+ // 获取文件的扩展名
+ string fileExtension = Path.GetExtension(filePath);
+ // 如果文件的创建日期早于指定天数且是要删除的扩展名,则删除文件
+ if (creationDate < DateTime.Now.AddDays(-daysThreshold)) {
+ if (Array.Exists(extensionsToDel, ext => ext.Equals(fileExtension, StringComparison.OrdinalIgnoreCase))
+ || Path.GetFileName(filePath).Equals("Position", StringComparison.OrdinalIgnoreCase)) {
+ File.Delete(filePath);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ try { // 递归删除空文件夹
+ DeleteEmptyFolders(directoryPath);
+ } catch (Exception ex) {
+ LogHelper.WriteLogToFile("DelAutoSavedFiles | 处理文件时出错: " + ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+ }
+
+ private static void DeleteEmptyFolders(string directoryPath) {
+ foreach (string dir in Directory.GetDirectories(directoryPath)) {
+ DeleteEmptyFolders(dir);
+ if (Directory.GetFiles(dir).Length == 0 && Directory.GetDirectories(dir).Length == 0) {
+ Directory.Delete(dir, false);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/DelayActionHelper.cs b/Ink Canvas/Helpers/DelayActionHelper.cs
new file mode 100644
index 00000000..bcf1fd51
--- /dev/null
+++ b/Ink Canvas/Helpers/DelayActionHelper.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+
+namespace Ink_Canvas.Helpers
+{
+ public class DelayAction
+ {
+ Timer _timerDebounce;
+
+ ///
+ /// 防抖函式
+ ///
+ /// 同步的對象,一般傳入控件,不需要可null
+ public void DebounceAction(int timeMs, ISynchronizeInvoke inv, Action action)
+ {
+ lock (this) {
+ if (_timerDebounce == null) {
+ _timerDebounce = new Timer(timeMs) { AutoReset = false };
+ _timerDebounce.Elapsed += (o, e) => {
+ _timerDebounce.Stop(); _timerDebounce.Close(); _timerDebounce = null;
+ InvokeAction(action, inv);
+ };
+ }
+ _timerDebounce.Stop();
+ _timerDebounce.Start();
+ }
+ }
+
+ private static void InvokeAction(Action action, ISynchronizeInvoke inv)
+ {
+ if (inv == null)
+ {
+ action();
+ }
+ else
+ {
+ if (inv.InvokeRequired)
+ {
+ inv.Invoke(action, null);
+ }
+ else
+ {
+ action();
+ }
+ }
+ }
+ }
+}
diff --git a/Ink Canvas/Helpers/EdgeGestureUtil.cs b/Ink Canvas/Helpers/EdgeGestureUtil.cs
new file mode 100644
index 00000000..26a6ffe6
--- /dev/null
+++ b/Ink Canvas/Helpers/EdgeGestureUtil.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.VisualBasic;
+using System.Collections;
+using System.Data;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Ink_Canvas.Helpers
+{
+
+ public static class EdgeGestureUtil
+ {
+
+ private static Guid DISABLE_TOUCH_SCREEN = new Guid("32CE38B2-2C9A-41B1-9BC5-B3784394AA44");
+ private static Guid IID_PROPERTY_STORE = new Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99");
+
+ private static short VT_BOOL = 11;
+ #region "Structures"
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct PropertyKey
+ {
+ public PropertyKey(Guid guid, UInt32 pid)
+ {
+ fmtid = guid;
+ this.pid = pid;
+ }
+
+ [MarshalAs(UnmanagedType.Struct)]
+ public Guid fmtid;
+ public uint pid;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct PropVariant
+ {
+ [FieldOffset(0)]
+ public short vt;
+ [FieldOffset(2)]
+ private short wReserved1;
+ [FieldOffset(4)]
+ private short wReserved2;
+ [FieldOffset(6)]
+ private short wReserved3;
+ [FieldOffset(8)]
+ private sbyte cVal;
+ [FieldOffset(8)]
+ private byte bVal;
+ [FieldOffset(8)]
+ private short iVal;
+ [FieldOffset(8)]
+ public ushort uiVal;
+ [FieldOffset(8)]
+ private int lVal;
+ [FieldOffset(8)]
+ private uint ulVal;
+ [FieldOffset(8)]
+ private int intVal;
+ [FieldOffset(8)]
+ private uint uintVal;
+ [FieldOffset(8)]
+ private long hVal;
+ [FieldOffset(8)]
+ private long uhVal;
+ [FieldOffset(8)]
+ private float fltVal;
+ [FieldOffset(8)]
+ private double dblVal;
+ [FieldOffset(8)]
+ public bool boolVal;
+ [FieldOffset(8)]
+ private int scode;
+ [FieldOffset(8)]
+ private DateTime date;
+ [FieldOffset(8)]
+ private System.Runtime.InteropServices.ComTypes.FILETIME filetime;
+
+ [FieldOffset(8)]
+ private Blob blobVal;
+ [FieldOffset(8)]
+ private IntPtr pwszVal;
+
+
+ ///
+ /// Helper method to gets blob data
+ ///
+ private byte[] GetBlob()
+ {
+ byte[] Result = new byte[blobVal.Length];
+ Marshal.Copy(blobVal.Data, Result, 0, Result.Length);
+ return Result;
+ }
+
+ ///
+ /// Property value
+ ///
+ public object Value
+ {
+ get
+ {
+ VarEnum ve = (VarEnum)vt;
+ switch (ve)
+ {
+ case VarEnum.VT_I1:
+ return bVal;
+ case VarEnum.VT_I2:
+ return iVal;
+ case VarEnum.VT_I4:
+ return lVal;
+ case VarEnum.VT_I8:
+ return hVal;
+ case VarEnum.VT_INT:
+ return iVal;
+ case VarEnum.VT_UI4:
+ return ulVal;
+ case VarEnum.VT_LPWSTR:
+ return Marshal.PtrToStringUni(pwszVal);
+ case VarEnum.VT_BLOB:
+ return GetBlob();
+ }
+ throw new NotImplementedException("PropVariant " + ve.ToString());
+ }
+ }
+ }
+
+ internal struct Blob
+ {
+ public int Length;
+
+ public IntPtr Data;
+ //Code Should Compile at warning level4 without any warnings,
+ //However this struct will give us Warning CS0649: Field [Fieldname]
+ //is never assigned to, and will always have its default value
+ //You can disable CS0649 in the project options but that will disable
+ //the warning for the whole project, it's a nice warning and we do want
+ //it in other places so we make a nice dummy function to keep the compiler
+ //happy.
+ // 代码应该在警告级别 4 下编译而不会出现任何警告,但是此结构将给出警告 CS0649:字段 [Fieldname] 从未分配,并且始终具有其默认值。您可以在项目选项中禁用 CS0649,但这将禁用整个项目的警告,这是一个很好的警告,我们确实希望它在其他地方,所以我们制作了一个不错的虚拟函数来让编译器满意。
+ private void FixCS0649()
+ {
+ Length = 0;
+ Data = IntPtr.Zero;
+ }
+ }
+
+ #endregion
+
+ #region "Interfaces"
+
+ [ComImport(), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IPropertyStore
+ {
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetCount([Out(), In()] ref uint cProps);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetAt([In()] uint iProp, ref PropertyKey pkey);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void GetValue([In()] ref PropertyKey key, ref PropVariant pv);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void SetValue([In()] ref PropertyKey key, [In()] ref PropVariant pv);
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Commit();
+ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void Release();
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ [DllImport("shell32.dll", SetLastError = true)]
+ private static extern int SHGetPropertyStoreForWindow(IntPtr handle, ref Guid riid, ref IPropertyStore propertyStore);
+
+ public static void DisableEdgeGestures(IntPtr hwnd, bool enable)
+ {
+ IPropertyStore pPropStore = null;
+ int hr = 0;
+ hr = SHGetPropertyStoreForWindow(hwnd, ref IID_PROPERTY_STORE, ref pPropStore);
+ if (hr == 0)
+ {
+ PropertyKey propKey = new PropertyKey();
+ propKey.fmtid = DISABLE_TOUCH_SCREEN;
+ propKey.pid = 2;
+ PropVariant var = new PropVariant();
+ var.vt = VT_BOOL;
+ var.boolVal = enable;
+ pPropStore.SetValue(ref propKey, ref var);
+ Marshal.FinalReleaseComObject(pPropStore);
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Ink Canvas/Helpers/ForegroundWindowInfo.cs b/Ink Canvas/Helpers/ForegroundWindowInfo.cs
new file mode 100644
index 00000000..7968fc49
--- /dev/null
+++ b/Ink Canvas/Helpers/ForegroundWindowInfo.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Ink_Canvas.Helpers
+{
+ internal class ForegroundWindowInfo
+ {
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
+
+ [DllImport("user32.dll")]
+ private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public int Width => Right - Left;
+ public int Height => Bottom - Top;
+ }
+
+ public static string WindowTitle() {
+ IntPtr foregroundWindowHandle = GetForegroundWindow();
+
+ const int nChars = 256;
+ StringBuilder windowTitle = new StringBuilder(nChars);
+ GetWindowText(foregroundWindowHandle, windowTitle, nChars);
+
+ return windowTitle.ToString();
+ }
+
+ public static string WindowClassName() {
+ IntPtr foregroundWindowHandle = GetForegroundWindow();
+
+ const int nChars = 256;
+ StringBuilder className = new StringBuilder(nChars);
+ GetClassName(foregroundWindowHandle, className, nChars);
+
+ return className.ToString();
+ }
+
+ public static RECT WindowRect() {
+ IntPtr foregroundWindowHandle = GetForegroundWindow();
+
+ RECT windowRect;
+ GetWindowRect(foregroundWindowHandle, out windowRect);
+
+ return windowRect;
+ }
+
+ public static string ProcessName() {
+ IntPtr foregroundWindowHandle = GetForegroundWindow();
+ uint processId;
+ GetWindowThreadProcessId(foregroundWindowHandle, out processId);
+
+ try {
+ Process process = Process.GetProcessById((int)processId);
+ return process.ProcessName;
+ } catch (ArgumentException) {
+ // Process with the given ID not found
+ return "Unknown";
+ }
+ }
+
+ public static string ProcessPath()
+ {
+ IntPtr foregroundWindowHandle = GetForegroundWindow();
+ uint processId;
+ GetWindowThreadProcessId(foregroundWindowHandle, out processId);
+
+ try
+ {
+ Process process = Process.GetProcessById((int)processId);
+ return process.MainModule.FileName;
+ }
+ catch {
+ // Process with the given ID not found
+ return "Unknown";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/FullScreenHelper.Win32.cs b/Ink Canvas/Helpers/FullScreenHelper.Win32.cs
new file mode 100644
index 00000000..fae1dd0d
--- /dev/null
+++ b/Ink Canvas/Helpers/FullScreenHelper.Win32.cs
@@ -0,0 +1,376 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+// 由衷感謝 lindexi 提供的 《WPF 稳定的全屏化窗口方法》
+// 文章鏈接:https://blog.lindexi.com/post/WPF-%E7%A8%B3%E5%AE%9A%E7%9A%84%E5%85%A8%E5%B1%8F%E5%8C%96%E7%AA%97%E5%8F%A3%E6%96%B9%E6%B3%95.html
+// lindexi 的部落格:https://blog.lindexi.com/
+
+namespace Ink_Canvas.Helpers
+{
+ public static partial class FullScreenHelper
+ {
+ static class Win32
+ {
+ [Flags]
+ public enum ShowWindowCommands
+ {
+ ///
+ /// Maximizes the specified window.
+ ///
+ SW_MAXIMIZE = 3,
+
+ ///
+ /// Activates and displays the window. If the window is minimized or maximized, the system restores it to its original
+ /// size and position. An application should specify this flag when restoring a minimized window.
+ ///
+ SW_RESTORE = 9,
+ }
+
+
+ internal static class Properties
+ {
+#if !ANSI
+ public const CharSet BuildCharSet = CharSet.Unicode;
+#else
+ public const CharSet BuildCharSet = CharSet.Ansi;
+#endif
+ }
+
+ public static class Dwmapi
+ {
+ public const string LibraryName = "Dwmapi.dll";
+
+ [DllImport(LibraryName, ExactSpelling = true, PreserveSig = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool DwmIsCompositionEnabled();
+
+ [DllImport("Dwmapi.dll", ExactSpelling = true, SetLastError = true)]
+ public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute,
+ in int pvAttribute, uint cbAttribute);
+ }
+
+ public static class User32
+ {
+ public const string LibraryName = "user32";
+
+ [DllImport(LibraryName, CharSet = Properties.BuildCharSet)]
+ public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfo lpmi);
+
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern IntPtr MonitorFromRect(in Rectangle lprc, MonitorFlag dwFlags);
+
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern bool IsIconic(IntPtr hwnd);
+
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
+
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern bool SetWindowPlacement(IntPtr hWnd,
+ [In] ref WINDOWPLACEMENT lpwndpl);
+
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect);
+
+ [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)]
+ public static extern Int32 SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, Int32 x, Int32 y, Int32 cx,
+ Int32 cy, Int32 wFlagslong);
+
+ [DllImport(LibraryName, ExactSpelling = true)]
+ public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
+
+ public static IntPtr GetWindowLongPtr(IntPtr hWnd, GetWindowLongFields nIndex) =>
+ GetWindowLongPtr(hWnd, (int) nIndex);
+
+ public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
+ {
+ return IntPtr.Size > 4
+#pragma warning disable CS0618 // 类型或成员已过时
+ ? GetWindowLongPtr_x64(hWnd, nIndex)
+ : new IntPtr(GetWindowLong(hWnd, nIndex));
+#pragma warning restore CS0618 // 类型或成员已过时
+ }
+
+ [DllImport(LibraryName, CharSet = Properties.BuildCharSet)]
+ public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport(LibraryName, CharSet = Properties.BuildCharSet, EntryPoint = "GetWindowLongPtr")]
+ public static extern IntPtr GetWindowLongPtr_x64(IntPtr hWnd, int nIndex);
+
+ public static IntPtr SetWindowLongPtr(IntPtr hWnd, GetWindowLongFields nIndex, IntPtr dwNewLong) =>
+ SetWindowLongPtr(hWnd, (int) nIndex, dwNewLong);
+
+ public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
+ {
+ return IntPtr.Size > 4
+#pragma warning disable CS0618 // 类型或成员已过时
+ ? SetWindowLongPtr_x64(hWnd, nIndex, dwNewLong)
+ : new IntPtr(SetWindowLong(hWnd, nIndex, dwNewLong.ToInt32()));
+#pragma warning restore CS0618 // 类型或成员已过时
+ }
+
+ [DllImport(LibraryName, CharSet = Properties.BuildCharSet, EntryPoint = "SetWindowLongPtr")]
+ public static extern IntPtr SetWindowLongPtr_x64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+
+ [DllImport(LibraryName, CharSet = Properties.BuildCharSet)]
+ public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct MonitorInfo
+ {
+ ///
+ /// The size of the structure, in bytes.
+ ///
+ public uint Size;
+
+ ///
+ /// A RECT structure that specifies the display monitor rectangle, expressed in virtual-screen coordinates. Note that
+ /// if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
+ ///
+ public Rectangle MonitorRect;
+
+ ///
+ /// A RECT structure that specifies the work area rectangle of the display monitor, expressed in virtual-screen
+ /// coordinates. Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may
+ /// be negative values.
+ ///
+ public Rectangle WorkRect;
+
+ ///
+ /// A set of flags that represent attributes of the display monitor.
+ ///
+ public MonitorInfoFlag Flags;
+ }
+
+ enum MonitorInfoFlag
+ {
+ }
+
+ enum MonitorFlag
+ {
+ ///
+ /// Returns a handle to the primary display monitor.
+ ///
+ MONITOR_DEFAULTTOPRIMARY = 1,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct WindowPosition
+ {
+ public IntPtr Hwnd;
+ public IntPtr HwndZOrderInsertAfter;
+ public int X;
+ public int Y;
+ public int Width;
+ public int Height;
+ public WindowPositionFlags Flags;
+ }
+
+ enum HwndZOrder
+ {
+ ///
+ /// Places the window at the top of the Z order.
+ ///
+ HWND_TOP = 0,
+ HWND_TOPMOST = -1,
+ }
+
+ enum DWMWINDOWATTRIBUTE : uint
+ {
+ DWMWA_TRANSITIONS_FORCEDISABLED = 3,
+ }
+
+ enum GetWindowLongFields
+ {
+ ///
+ /// 设定一个新的窗口风格
+ /// Retrieves the window styles
+ ///
+ GWL_STYLE = -16,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct WINDOWPLACEMENT // WindowPlacement
+ {
+ public uint Size;
+ public WindowPlacementFlags Flags;
+ public Win32.ShowWindowCommands ShowCmd;
+ public Point MinPosition;
+ public Point MaxPosition;
+ public Rectangle NormalPosition;
+ }
+
+ [Flags]
+ public enum WindowPositionFlags
+ {
+ ///
+ ///
+ /// 清除客户区的所有内容。如果未设置该标志,客户区的有效内容被保存并且在窗口尺寸更新和重定位后拷贝回客户区
+ ///
+ /// Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client
+ /// area are saved and copied back into the client area after the window is sized or repositioned.
+ ///
+ SWP_NOCOPYBITS = 0x0100,
+
+ ///
+ ///
+ /// 维持当前位置(忽略X和Y参数)
+ ///
+ /// Retains the current position (ignores X and Y parameters).
+ ///
+ SWP_NOMOVE = 0x0002,
+
+ ///
+ ///
+ /// 不重画改变的内容。如果设置了这个标志,则不发生任何重画动作。适用于客户区和非客户区(包括标题栏和滚动条)和任何由于窗回移动而露出的父窗口的所有部分。如果设置了这个标志,应用程序必须明确地使窗口无效并区重画窗口的任何部分和父窗口需要重画的部分
+ ///
+ /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area,
+ /// the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a
+ /// result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any
+ /// parts of the window and parent window that need redrawing.
+ ///
+ SWP_NOREDRAW = 0x0008,
+
+ ///
+ ///
+ /// 维持当前尺寸(忽略 cx 和 cy 参数)
+ ///
+ /// Retains the current size (ignores the cx and cy parameters).
+ ///
+ SWP_NOSIZE = 0x0001,
+
+ ///
+ ///
+ /// 维持当前 Z 序(忽略 hWndlnsertAfter 参数)
+ ///
+ /// Retains the current Z order (ignores the hWndInsertAfter parameter).
+ ///
+ SWP_NOZORDER = 0x0004,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct Rectangle
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ ///
+ /// 矩形的宽度
+ ///
+ public int Width
+ {
+ get { return unchecked((int) (Right - Left)); }
+ set { Right = unchecked((int) (Left + value)); }
+ }
+
+ ///
+ /// 矩形的高度
+ ///
+ public int Height
+ {
+ get { return unchecked((int) (Bottom - Top)); }
+ set { Bottom = unchecked((int) (Top + value)); }
+ }
+
+ public bool Equals(Rectangle other)
+ {
+ return (Left == other.Left) && (Right == other.Right) && (Top == other.Top) && (Bottom == other.Bottom);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Rectangle rectangle && Equals(rectangle);
+ }
+
+ public static bool operator ==(Rectangle left, Rectangle right)
+ {
+ return left.Equals(right);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (int) Left;
+ hashCode = (hashCode * 397) ^ (int) Top;
+ hashCode = (hashCode * 397) ^ (int) Right;
+ hashCode = (hashCode * 397) ^ (int) Bottom;
+ return hashCode;
+ }
+ }
+
+ public static bool operator !=(Rectangle left, Rectangle right)
+ {
+ return !(left == right);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct Point
+ {
+ public int X;
+ public int Y;
+ }
+
+ [Flags]
+ enum WindowPlacementFlags
+ {
+ }
+
+ [Flags]
+ enum WindowStyles
+ {
+ ///
+ /// The window is initially maximized.
+ ///
+ WS_MAXIMIZE = 0x01000000,
+
+ ///
+ /// The window has a maximize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must
+ /// also be specified.
+ ///
+ WS_MAXIMIZEBOX = 0x00010000,
+
+ ///
+ /// The window is initially minimized. Same as the WS_ICONIC style.
+ ///
+ WS_MINIMIZE = 0x20000000,
+
+ ///
+ /// The window has a sizing border. Same as the WS_SIZEBOX style.
+ ///
+ WS_THICKFRAME = 0x00040000,
+ }
+
+ [ComImport]
+ [Guid("602D4995-B13A-429b-A66E-1935E44F4317")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ITaskbarList2
+ {
+ [PreserveSig]
+ int HrInit();
+
+ [PreserveSig]
+ int AddTab(IntPtr hwnd);
+
+ [PreserveSig]
+ int DeleteTab(IntPtr hwnd);
+
+ [PreserveSig]
+ int ActivateTab(IntPtr hwnd);
+
+ [PreserveSig]
+ int SetActiveAlt(IntPtr hwnd);
+
+ [PreserveSig]
+ int MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/FullScreenHelper.cs b/Ink Canvas/Helpers/FullScreenHelper.cs
new file mode 100644
index 00000000..b80a4a33
--- /dev/null
+++ b/Ink Canvas/Helpers/FullScreenHelper.cs
@@ -0,0 +1,301 @@
+using System;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Interop;
+
+// 由衷感謝 lindexi 提供的 《WPF 稳定的全屏化窗口方法》
+// 文章鏈接:https://blog.lindexi.com/post/WPF-%E7%A8%B3%E5%AE%9A%E7%9A%84%E5%85%A8%E5%B1%8F%E5%8C%96%E7%AA%97%E5%8F%A3%E6%96%B9%E6%B3%95.html
+// lindexi 的部落格:https://blog.lindexi.com/
+
+namespace Ink_Canvas.Helpers
+{
+ ///
+ /// 用来使窗口变得全屏的辅助类
+ /// 采用设置窗口位置和尺寸,确保盖住整个屏幕的方式来实现全屏
+ /// 目前已知需要满足的条件是:窗口盖住整个屏幕、窗口没有WS_THICKFRAME样式、窗口不能有标题栏且最大化
+ ///
+ public static partial class FullScreenHelper
+ {
+ public static void MarkFullscreenWindowTaskbarList(IntPtr hwnd, bool isFullscreen)
+ {
+ try
+ {
+ var CLSID_TaskbarList = new Guid("56FDF344-FD6D-11D0-958A-006097C9A090");
+ var obj = Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_TaskbarList));
+ (obj as ITaskbarList2)?.MarkFullscreenWindow(hwnd, isFullscreen);
+ }
+ catch
+ {
+ //应该不会挂
+ }
+ }
+
+ ///
+ /// 用于记录窗口全屏前位置的附加属性
+ ///
+ private static readonly DependencyProperty BeforeFullScreenWindowPlacementProperty =
+ DependencyProperty.RegisterAttached("BeforeFullScreenWindowPlacement", typeof(WINDOWPLACEMENT?),
+ typeof(Window));
+
+ ///
+ /// 用于记录窗口全屏前样式的附加属性
+ ///
+ private static readonly DependencyProperty BeforeFullScreenWindowStyleProperty =
+ DependencyProperty.RegisterAttached("BeforeFullScreenWindowStyle", typeof(WindowStyles?), typeof(Window));
+
+ ///
+ /// 开始进入全屏模式
+ /// 进入全屏模式后,窗口可通过 API 方式(也可以用 Win + Shift + Left/Right)移动,调整大小,但会根据目标矩形寻找显示器重新调整到全屏状态。
+ /// 进入全屏后,不要修改样式等窗口属性,在退出时,会恢复到进入前的状态
+ /// 进入全屏模式后会禁用 DWM 过渡动画
+ ///
+ ///
+ public static void StartFullScreen(Window window)
+ {
+ if (window == null)
+ {
+ throw new ArgumentNullException(nameof(window), $"{nameof(window)} 不能为 null");
+ }
+
+ //确保不在全屏模式
+ if (window.GetValue(BeforeFullScreenWindowPlacementProperty) == null &&
+ window.GetValue(BeforeFullScreenWindowStyleProperty) == null)
+ {
+ var hwnd = new WindowInteropHelper(window).EnsureHandle();
+ var hwndSource = HwndSource.FromHwnd(hwnd);
+
+ //获取当前窗口的位置大小状态并保存
+ var placement = new WINDOWPLACEMENT();
+ placement.Size = (uint) Marshal.SizeOf(placement);
+ Win32.User32.GetWindowPlacement(hwnd, ref placement);
+ window.SetValue(BeforeFullScreenWindowPlacementProperty, placement);
+
+ //修改窗口样式
+ var style = (WindowStyles) Win32.User32.GetWindowLongPtr(hwnd, GetWindowLongFields.GWL_STYLE);
+ window.SetValue(BeforeFullScreenWindowStyleProperty, style);
+ //将窗口恢复到还原模式,在有标题栏的情况下最大化模式下无法全屏,
+ //这里采用还原,不修改标题栏的方式
+ //在退出全屏时,窗口原有的状态会恢复
+ //去掉WS_THICKFRAME,在有该样式的情况下不能全屏
+ //去掉WS_MAXIMIZEBOX,禁用最大化,如果最大化会退出全屏
+ //去掉WS_MAXIMIZE,使窗口变成还原状态,不使用ShowWindow(hwnd, ShowWindowCommands.SW_RESTORE),避免看到窗口变成还原状态这一过程(也避免影响窗口的Visible状态)
+ style &= (~(WindowStyles.WS_THICKFRAME | WindowStyles.WS_MAXIMIZEBOX | WindowStyles.WS_MAXIMIZE));
+ Win32.User32.SetWindowLongPtr(hwnd, GetWindowLongFields.GWL_STYLE, (IntPtr) style);
+
+ //禁用 DWM 过渡动画 忽略返回值,若DWM关闭不做处理
+ Win32.Dwmapi.DwmSetWindowAttribute(hwnd, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 1,
+ sizeof(int));
+
+ //添加Hook,在窗口尺寸位置等要发生变化时,确保全屏
+ hwndSource.AddHook(KeepFullScreenHook);
+
+ if (Win32.User32.GetWindowRect(hwnd, out var rect))
+ {
+ //不能用 placement 的坐标,placement是工作区坐标,不是屏幕坐标。
+
+ //使用窗口当前的矩形调用下设置窗口位置和尺寸的方法,让Hook来进行调整窗口位置和尺寸到全屏模式
+ Win32.User32.SetWindowPos(hwnd, (IntPtr) HwndZOrder.HWND_TOPMOST, rect.Left, rect.Top, rect.Width,
+ rect.Height, (int) WindowPositionFlags.SWP_NOZORDER);
+ }
+ }
+ }
+
+ ///
+ /// 退出全屏模式
+ /// 窗口会回到进入全屏模式时保存的状态
+ /// 退出全屏模式后会重新启用 DWM 过渡动画
+ ///
+ ///
+ public static void EndFullScreen(Window window)
+ {
+ if (window == null)
+ {
+ throw new ArgumentNullException(nameof(window), $"{nameof(window)} 不能为 null");
+ }
+
+ //确保在全屏模式并获取之前保存的状态
+ if (window.GetValue(BeforeFullScreenWindowPlacementProperty) is WINDOWPLACEMENT placement
+ && window.GetValue(BeforeFullScreenWindowStyleProperty) is WindowStyles style)
+ {
+ var hwnd = new WindowInteropHelper(window).Handle;
+
+ if (hwnd == IntPtr.Zero)
+ {
+ // 句柄为 0 只有两种情况:
+ // 1. 虽然窗口已进入全屏,但窗口已被关闭;
+ // 2. 窗口初始化前,在还没有调用 StartFullScreen 的前提下就调用了此方法。
+ // 所以,直接 return 就好。
+ return;
+ }
+
+
+ var hwndSource = HwndSource.FromHwnd(hwnd);
+
+ //去除hook
+ hwndSource.RemoveHook(KeepFullScreenHook);
+
+ //恢复保存的状态
+ //不要改变Style里的WS_MAXIMIZE,否则会使窗口变成最大化状态,但是尺寸不对
+ //也不要设置回Style里的WS_MINIMIZE,否则会导致窗口最小化按钮显示成还原按钮
+ Win32.User32.SetWindowLongPtr(hwnd, GetWindowLongFields.GWL_STYLE,
+ (IntPtr) (style & (~(WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE))));
+
+ if ((style & WindowStyles.WS_MINIMIZE) != 0)
+ {
+ //如果窗口进入全屏前是最小化的,这里不让窗口恢复到之前的最小化状态,而是到还原的状态。
+ //大多数情况下,都不期望在退出全屏的时候,恢复到最小化。
+ placement.ShowCmd = Win32.ShowWindowCommands.SW_RESTORE;
+ }
+
+ if ((style & WindowStyles.WS_MAXIMIZE) != 0)
+ {
+ //提前调用 ShowWindow 使窗口恢复最大化,若通过 SetWindowPlacement 最大化会导致闪烁,只靠其恢复 RestoreBounds.
+ Win32.User32.ShowWindow(hwnd, Win32.ShowWindowCommands.SW_MAXIMIZE);
+ }
+
+ Win32.User32.SetWindowPlacement(hwnd, ref placement);
+
+ if ((style & WindowStyles.WS_MAXIMIZE) ==
+ 0) //如果窗口是最大化就不要修改WPF属性,否则会破坏RestoreBounds,且WPF窗口自身在最大化时,不会修改 Left Top Width Height 属性
+ {
+ if (Win32.User32.GetWindowRect(hwnd, out var rect))
+ {
+ //不能用 placement 的坐标,placement是工作区坐标,不是屏幕坐标。
+
+ //确保窗口的 WPF 属性与 Win32 位置一致
+ var logicalPos =
+ hwndSource.CompositionTarget.TransformFromDevice.Transform(
+ new System.Windows.Point(rect.Left, rect.Top));
+ var logicalSize =
+ hwndSource.CompositionTarget.TransformFromDevice.Transform(
+ new System.Windows.Point(rect.Width, rect.Height));
+ window.Left = logicalPos.X;
+ window.Top = logicalPos.Y;
+ window.Width = logicalSize.X;
+ window.Height = logicalSize.Y;
+ }
+ }
+
+ //重新启用 DWM 过渡动画 忽略返回值,若DWM关闭不做处理
+ Win32.Dwmapi.DwmSetWindowAttribute(hwnd, DWMWINDOWATTRIBUTE.DWMWA_TRANSITIONS_FORCEDISABLED, 0,
+ sizeof(int));
+
+ //删除保存的状态
+ window.ClearValue(BeforeFullScreenWindowPlacementProperty);
+ window.ClearValue(BeforeFullScreenWindowStyleProperty);
+ }
+ }
+
+ ///
+ /// 确保窗口全屏的Hook
+ /// 使用HandleProcessCorruptedStateExceptions,防止访问内存过程中因为一些致命异常导致程序崩溃
+ ///
+ [HandleProcessCorruptedStateExceptions]
+ private static IntPtr KeepFullScreenHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ //处理WM_WINDOWPOSCHANGING消息
+ const int WINDOWPOSCHANGING = 0x0046;
+ if (msg == WINDOWPOSCHANGING)
+ {
+ try
+ {
+ //得到WINDOWPOS结构体
+ var pos = (WindowPosition) Marshal.PtrToStructure(lParam, typeof(WindowPosition));
+
+ if ((pos.Flags & WindowPositionFlags.SWP_NOMOVE) != 0 &&
+ (pos.Flags & WindowPositionFlags.SWP_NOSIZE) != 0)
+ {
+ //既然你既不改变位置,也不改变尺寸,我就不管了...
+ return IntPtr.Zero;
+ }
+
+ if (Win32.User32.IsIconic(hwnd))
+ {
+ // 如果在全屏期间最小化了窗口,那么忽略后续的位置调整。
+ // 否则按后续逻辑,会根据窗口在 -32000 的位置,计算出错误的目标位置,然后就跳到主屏了。
+ return IntPtr.Zero;
+ }
+
+ //获取窗口现在的矩形,下面用来参考计算目标矩形
+ if (Win32.User32.GetWindowRect(hwnd, out var rect))
+ {
+ var targetRect = rect; //窗口想要变化的目标矩形
+
+ if ((pos.Flags & WindowPositionFlags.SWP_NOMOVE) == 0)
+ {
+ //需要移动
+ targetRect.Left = pos.X;
+ targetRect.Top = pos.Y;
+ }
+
+ if ((pos.Flags & WindowPositionFlags.SWP_NOSIZE) == 0)
+ {
+ //要改变尺寸
+ targetRect.Right = targetRect.Left + pos.Width;
+ targetRect.Bottom = targetRect.Top + pos.Height;
+ }
+ else
+ {
+ //不改变尺寸
+ targetRect.Right = targetRect.Left + rect.Width;
+ targetRect.Bottom = targetRect.Top + rect.Height;
+ }
+
+ //使用目标矩形获取显示器信息
+ var monitor = Win32.User32.MonitorFromRect(targetRect, MonitorFlag.MONITOR_DEFAULTTOPRIMARY);
+ var info = new MonitorInfo();
+ info.Size = (uint) Marshal.SizeOf(info);
+ if (Win32.User32.GetMonitorInfo(monitor, ref info))
+ {
+ //基于显示器信息设置窗口尺寸位置
+ pos.X = info.MonitorRect.Left;
+ pos.Y = info.MonitorRect.Top;
+ pos.Width = info.MonitorRect.Right - info.MonitorRect.Left;
+ pos.Height = info.MonitorRect.Bottom - info.MonitorRect.Top;
+ pos.Flags &= ~(WindowPositionFlags.SWP_NOSIZE | WindowPositionFlags.SWP_NOMOVE |
+ WindowPositionFlags.SWP_NOREDRAW);
+ pos.Flags |= WindowPositionFlags.SWP_NOCOPYBITS;
+
+ if (rect == info.MonitorRect)
+ {
+ var hwndSource = HwndSource.FromHwnd(hwnd);
+ if (hwndSource?.RootVisual is Window window)
+ {
+ //确保窗口的 WPF 属性与 Win32 位置一致,防止有逗比全屏后改 WPF 的属性,发生一些诡异的行为
+ //下面这样做其实不太好,会再次触发 WM_WINDOWPOSCHANGING 来着.....但是又没有其他时机了
+ // WM_WINDOWPOSCHANGED 不能用
+ //(例如:在进入全屏后,修改 Left 属性,会进入 WM_WINDOWPOSCHANGING,然后在这里将消息里的结构体中的 Left 改回,
+ // 使对 Left 的修改无效,那么将不会进入 WM_WINDOWPOSCHANGED,窗口尺寸正常,但窗口的 Left 属性值错误。)
+ var logicalPos =
+ hwndSource.CompositionTarget.TransformFromDevice.Transform(
+ new System.Windows.Point(pos.X, pos.Y));
+ var logicalSize =
+ hwndSource.CompositionTarget.TransformFromDevice.Transform(
+ new System.Windows.Point(pos.Width, pos.Height));
+ window.Left = logicalPos.X;
+ window.Top = logicalPos.Y;
+ window.Width = logicalSize.X;
+ window.Height = logicalSize.Y;
+ }
+ else
+ {
+ //这个hwnd是前面从Window来的,如果现在他不是Window...... 你信么
+ }
+ }
+
+ //将修改后的结构体拷贝回去
+ Marshal.StructureToPtr(pos, lParam, false);
+ }
+ }
+ }
+ catch
+ {
+ // 这里也不需要日志啥的,只是为了防止上面有逗比逻辑,在消息循环里面炸了
+ }
+ }
+
+ return IntPtr.Zero;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/Hotkey.cs b/Ink Canvas/Helpers/Hotkey.cs
new file mode 100644
index 00000000..0a60a215
--- /dev/null
+++ b/Ink Canvas/Helpers/Hotkey.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+
+namespace Ink_Canvas
+{
+ static class Hotkey
+ {
+ #region 系统api
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool RegisterHotKey(IntPtr hWnd, int id, HotkeyModifiers fsModifiers, uint vk);
+
+ [DllImport("user32.dll")]
+ static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+ #endregion
+
+ ///
+ /// 注册快捷键
+ ///
+ /// 持有快捷键窗口
+ /// 组合键
+ /// 快捷键
+ /// 回调函数
+ public static bool Regist(Window window, HotkeyModifiers fsModifiers, Key key, HotKeyCallBackHanlder callBack)
+ {
+ var hwnd = new WindowInteropHelper(window).Handle;
+ var _hwndSource = HwndSource.FromHwnd(hwnd);
+
+ if (keyid == 10)
+ {
+ _hwndSource.AddHook(WndProc);
+ }
+
+ int id = keyid++;
+
+ var vk = KeyInterop.VirtualKeyFromKey(key);
+ if (!RegisterHotKey(hwnd, id, fsModifiers, (uint)vk))
+ {
+ //throw new Exception("regist hotkey fail.");
+ return false;
+ }
+ keymap[id] = callBack;
+ return true;
+ }
+
+ ///
+ /// 快捷键消息处理
+ ///
+ static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ if (msg == WM_HOTKEY)
+ {
+ int id = wParam.ToInt32();
+ if (keymap.TryGetValue(id, out var callback))
+ {
+ callback();
+ }
+ }
+ return IntPtr.Zero;
+ }
+
+ ///
+ /// 注销快捷键
+ ///
+ /// 持有快捷键窗口的句柄
+ /// 回调函数
+ public static void UnRegist(IntPtr hWnd, HotKeyCallBackHanlder callBack)
+ {
+ foreach (KeyValuePair var in keymap)
+ {
+ if (var.Value == callBack)
+ UnregisterHotKey(hWnd, var.Key);
+ }
+ }
+
+
+ const int WM_HOTKEY = 0x312;
+ static int keyid = 10;
+ static Dictionary keymap = new Dictionary();
+
+ public delegate void HotKeyCallBackHanlder();
+ }
+
+ enum HotkeyModifiers
+ {
+ MOD_ALT = 0x1,
+ MOD_CONTROL = 0x2,
+ MOD_SHIFT = 0x4,
+ MOD_WIN = 0x8
+ }
+
+}
diff --git a/Ink Canvas/Helpers/InkRecognizeHelper.cs b/Ink Canvas/Helpers/InkRecognizeHelper.cs
new file mode 100644
index 00000000..af13de86
--- /dev/null
+++ b/Ink Canvas/Helpers/InkRecognizeHelper.cs
@@ -0,0 +1,200 @@
+using System.Linq;
+using System.Windows;
+using System.Windows.Ink;
+using System.Windows.Media;
+
+namespace Ink_Canvas.Helpers
+{
+ public class InkRecognizeHelper
+ {
+ //识别形状
+ public static ShapeRecognizeResult RecognizeShape(StrokeCollection strokes)
+ {
+ if (strokes == null || strokes.Count == 0)
+ return default;
+
+ var analyzer = new InkAnalyzer();
+ analyzer.AddStrokes(strokes);
+ analyzer.SetStrokesType(strokes, System.Windows.Ink.StrokeType.Drawing);
+
+ AnalysisAlternate analysisAlternate = null;
+ int strokesCount = strokes.Count;
+ var sfsaf = analyzer.Analyze();
+ if (sfsaf.Successful)
+ {
+ var alternates = analyzer.GetAlternates();
+ if (alternates.Count > 0)
+ {
+ while ((!alternates[0].Strokes.Contains(strokes.Last()) ||
+ !IsContainShapeType(((InkDrawingNode)alternates[0].AlternateNodes[0]).GetShapeName()))
+ && strokesCount >= 2)
+ {
+ analyzer.RemoveStroke(strokes[strokes.Count - strokesCount]);
+ strokesCount--;
+ sfsaf = analyzer.Analyze();
+ if (sfsaf.Successful)
+ {
+ alternates = analyzer.GetAlternates();
+ }
+ }
+ analysisAlternate = alternates[0];
+ }
+ }
+
+ analyzer.Dispose();
+
+ if (analysisAlternate != null && analysisAlternate.AlternateNodes.Count > 0)
+ {
+ var node = analysisAlternate.AlternateNodes[0] as InkDrawingNode;
+ return new ShapeRecognizeResult(node.Centroid, node.HotPoints, analysisAlternate, node);
+ }
+
+ return default;
+ }
+
+ public static bool IsContainShapeType(string name)
+ {
+ if (name.Contains("Triangle") || name.Contains("Circle") ||
+ name.Contains("Rectangle") || name.Contains("Diamond") ||
+ name.Contains("Parallelogram") || name.Contains("Square")
+ || name.Contains("Ellipse"))
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ //Recognizer 的实现
+
+ public enum RecognizeLanguage
+ {
+ SimplifiedChinese = 0x0804,
+ TraditionalChinese = 0x7c03,
+ English = 0x0809
+ }
+
+ public class ShapeRecognizeResult
+ {
+ public ShapeRecognizeResult(Point centroid, PointCollection hotPoints, AnalysisAlternate analysisAlternate, InkDrawingNode node)
+ {
+ Centroid = centroid;
+ HotPoints = hotPoints;
+ AnalysisAlternate = analysisAlternate;
+ InkDrawingNode = node;
+ }
+
+ public AnalysisAlternate AnalysisAlternate { get; }
+
+ public Point Centroid { get; set; }
+
+ public PointCollection HotPoints { get; }
+
+ public InkDrawingNode InkDrawingNode { get; }
+ }
+
+ ///
+ /// 图形识别类
+ ///
+ //public class ShapeRecogniser
+ //{
+ // public InkAnalyzer _inkAnalyzer = null;
+
+ // private ShapeRecogniser()
+ // {
+ // this._inkAnalyzer = new InkAnalyzer
+ // {
+ // AnalysisModes = AnalysisModes.AutomaticReconciliationEnabled
+ // };
+ // }
+
+ // ///
+ // /// 根据笔迹集合返回图形名称字符串
+ // ///
+ // ///
+ // ///
+ // public InkDrawingNode Recognition(StrokeCollection strokeCollection)
+ // {
+ // if (strokeCollection == null)
+ // {
+ // //MessageBox.Show("dddddd");
+ // return null;
+ // }
+
+ // InkDrawingNode result = null;
+ // try
+ // {
+ // this._inkAnalyzer.AddStrokes(strokeCollection);
+ // if (this._inkAnalyzer.Analyze().Successful)
+ // {
+ // result = _internalAnalyzer(this._inkAnalyzer);
+ // this._inkAnalyzer.RemoveStrokes(strokeCollection);
+ // }
+ // }
+ // catch (System.Exception ex)
+ // {
+ // //result = ex.Message;
+ // System.Diagnostics.Debug.WriteLine(ex.Message);
+ // }
+
+ // return result;
+ // }
+
+ // ///
+ // /// 实现笔迹的分析,返回图形对应的字符串
+ // /// 你在实际的应用中根据返回的字符串来生成对应的Shape
+ // ///
+ // ///
+ // ///
+ // private InkDrawingNode _internalAnalyzer(InkAnalyzer ink)
+ // {
+ // try
+ // {
+ // ContextNodeCollection nodecollections = ink.FindNodesOfType(ContextNodeType.InkDrawing);
+ // foreach (ContextNode node in nodecollections)
+ // {
+ // InkDrawingNode drawingNode = node as InkDrawingNode;
+ // if (drawingNode != null)
+ // {
+ // return drawingNode;//.GetShapeName();
+ // }
+ // }
+ // }
+ // catch (System.Exception ex)
+ // {
+ // System.Diagnostics.Debug.WriteLine(ex.Message);
+ // }
+
+ // return null;
+ // }
+
+
+ // private static ShapeRecogniser instance = null;
+ // public static ShapeRecogniser Instance
+ // {
+ // get
+ // {
+ // return instance == null ? (instance = new ShapeRecogniser()) : instance;
+ // }
+ // }
+ //}
+
+
+ //用于自动控制其他形状相对于圆的位置
+
+ public class Circle
+ {
+ public Circle(Point centroid, double r, Stroke stroke)
+ {
+ Centroid = centroid;
+ R = r;
+ Stroke = stroke;
+ }
+
+ public Point Centroid { get; set; }
+
+ public double R { get; set; }
+
+ public Stroke Stroke { get; set; }
+ }
+}
diff --git a/Ink Canvas/Helpers/IsOutsideOfScreenHelper.cs b/Ink Canvas/Helpers/IsOutsideOfScreenHelper.cs
new file mode 100644
index 00000000..ca159271
--- /dev/null
+++ b/Ink Canvas/Helpers/IsOutsideOfScreenHelper.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Interop;
+using System.Windows;
+
+namespace Ink_Canvas.Helpers {
+ internal class IsOutsideOfScreenHelper {
+ public static bool IsOutsideOfScreen(FrameworkElement target) {
+ var hwndSource = (HwndSource)PresentationSource.FromVisual(target);
+ if (hwndSource is null) {
+ return true;
+ }
+
+ var hWnd = hwndSource.Handle;
+ var targetBounds = GetPixelBoundsToScreen(target);
+
+ var screens = System.Windows.Forms.Screen.AllScreens;
+ return !screens.Any(x => x.Bounds.IntersectsWith(targetBounds));
+
+ System.Drawing.Rectangle GetPixelBoundsToScreen(FrameworkElement visual) {
+ var pixelBoundsToScreen = Rect.Empty;
+ pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, 0)));
+ pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, 0)));
+ pixelBoundsToScreen.Union(visual.PointToScreen(new Point(0, visual.ActualHeight)));
+ pixelBoundsToScreen.Union(visual.PointToScreen(new Point(visual.ActualWidth, visual.ActualHeight)));
+ return new System.Drawing.Rectangle(
+ (int)pixelBoundsToScreen.X, (int)pixelBoundsToScreen.Y,
+ (int)pixelBoundsToScreen.Width, (int)pixelBoundsToScreen.Height);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/LogHelper.cs b/Ink Canvas/Helpers/LogHelper.cs
new file mode 100644
index 00000000..0e1129b2
--- /dev/null
+++ b/Ink Canvas/Helpers/LogHelper.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+namespace Ink_Canvas.Helpers
+{
+ class LogHelper
+ {
+ public static string LogFile = "Log.txt";
+
+ public static void NewLog(string str)
+ {
+ WriteLogToFile(str, LogType.Info);
+ }
+
+ public static void NewLog(Exception ex)
+ {
+
+ }
+
+ public static void WriteLogToFile(string str, LogType logType = LogType.Info)
+ {
+ string strLogType = "Info";
+ switch (logType)
+ {
+ case LogType.Event:
+ strLogType = "Event";
+ break;
+ case LogType.Trace:
+ strLogType = "Trace";
+ break;
+ case LogType.Error:
+ strLogType = "Error";
+ break;
+ }
+ try
+ {
+ var file = App.RootPath + LogFile;
+ if (!Directory.Exists(App.RootPath))
+ {
+ Directory.CreateDirectory(App.RootPath);
+ }
+ StreamWriter sw = new StreamWriter(file, true);
+ sw.WriteLine(string.Format("{0} [{1}] {2}", DateTime.Now.ToString("O"), strLogType, str));
+ sw.Close();
+ }
+ catch { }
+ }
+
+ internal static void WriteLogToFile(string v, object warning)
+ {
+ throw new NotImplementedException();
+ }
+
+ public enum LogType
+ {
+ Info,
+ Trace,
+ Error,
+ Event,
+ Warning
+ }
+ }
+}
diff --git a/Ink Canvas/Helpers/MultiTouchInput.cs b/Ink Canvas/Helpers/MultiTouchInput.cs
new file mode 100644
index 00000000..14f40e92
--- /dev/null
+++ b/Ink Canvas/Helpers/MultiTouchInput.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Windows;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Ink_Canvas.Helpers
+{
+ public class VisualCanvas : FrameworkElement
+ {
+ protected override Visual GetVisualChild(int index)
+ {
+ return Visual;
+ }
+
+ protected override int VisualChildrenCount => 1;
+
+ public VisualCanvas(DrawingVisual visual)
+ {
+ Visual = visual;
+ AddVisualChild(visual);
+ }
+
+ public DrawingVisual Visual { get; }
+ }
+
+ ///
+ /// 用于显示笔迹的类
+ ///
+ public class StrokeVisual : DrawingVisual
+ {
+ ///
+ /// 创建显示笔迹的类
+ ///
+ public StrokeVisual() : this(new DrawingAttributes()
+ {
+ Color = Colors.Red,
+ //FitToCurve = true,
+ Width = 3,
+ Height = 3
+ })
+ {
+ }
+
+ ///
+ /// 创建显示笔迹的类
+ ///
+ ///
+ public StrokeVisual(DrawingAttributes drawingAttributes)
+ {
+ _drawingAttributes = drawingAttributes;
+ }
+
+ ///
+ /// 设置或获取显示的笔迹
+ ///
+ public Stroke Stroke { set; get; }
+
+ ///
+ /// 在笔迹中添加点
+ ///
+ ///
+ public void Add(StylusPoint point)
+ {
+ if (Stroke == null)
+ {
+ var collection = new StylusPointCollection { point };
+ Stroke = new Stroke(collection) { DrawingAttributes = _drawingAttributes };
+ }
+ else
+ {
+ Stroke.StylusPoints.Add(point);
+ }
+ }
+
+ ///
+ /// 重新画出笔迹
+ ///
+ public void Redraw()
+ {
+ try
+ {
+ using (var dc = RenderOpen())
+ {
+ Stroke.Draw(dc);
+ }
+ }
+ catch { }
+ }
+
+ private readonly DrawingAttributes _drawingAttributes;
+
+ public static implicit operator Stroke(StrokeVisual v)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Ink Canvas/Helpers/SoftwareLauncher.cs b/Ink Canvas/Helpers/SoftwareLauncher.cs
new file mode 100644
index 00000000..54fd107a
--- /dev/null
+++ b/Ink Canvas/Helpers/SoftwareLauncher.cs
@@ -0,0 +1,74 @@
+using Microsoft.Win32;
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Ink_Canvas.Helpers
+{
+ internal class SoftwareLauncher
+ {
+ [DllImport("user32.dll")]
+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ public static void LaunchEasiCamera(string softwareName)
+ {
+ string executablePath = FindEasiCameraExecutablePath(softwareName);
+
+ if (!string.IsNullOrEmpty(executablePath))
+ {
+ try
+ {
+ Process.Start(executablePath);
+ //Console.WriteLine(softwareName + " 启动成功!");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("启动失败: " + ex.Message);
+ //MessageBox.Show("启动失败: " + ex.Message);
+ }
+ }
+ else
+ {
+ //Console.WriteLine(softwareName + " 未找到可执行文件路径。");
+ }
+ }
+
+ private static string FindEasiCameraExecutablePath(string softwareName)
+ {
+ string executablePath = null;
+
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall"))
+ {
+ foreach (string subkeyName in key.GetSubKeyNames())
+ {
+ using (RegistryKey subkey = key.OpenSubKey(subkeyName))
+ {
+ string displayName = subkey.GetValue("DisplayName") as string;
+ string installLocation = subkey.GetValue("InstallLocation") as string;
+ string uninstallString = subkey.GetValue("UninstallString") as string;
+
+ if (!string.IsNullOrEmpty(displayName) && displayName.Contains(softwareName))
+ {
+ if (!string.IsNullOrEmpty(installLocation))
+ {
+ executablePath = System.IO.Path.Combine(installLocation, "sweclauncher.exe");
+ }
+ else if (!string.IsNullOrEmpty(uninstallString))
+ {
+ int lastSlashIndex = uninstallString.LastIndexOf("\\");
+ if (lastSlashIndex >= 0)
+ {
+ string folderPath = uninstallString.Substring(0, lastSlashIndex);
+ executablePath = System.IO.Path.Combine(folderPath, "sweclauncher", "sweclauncher.exe");
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return executablePath;
+ }
+ }
+}
diff --git a/Ink Canvas/Helpers/TimeMachine.cs b/Ink Canvas/Helpers/TimeMachine.cs
new file mode 100644
index 00000000..6c9838e3
--- /dev/null
+++ b/Ink Canvas/Helpers/TimeMachine.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Ink_Canvas.Helpers
+{
+ public class TimeMachine
+ {
+ private readonly List _currentStrokeHistory = new List();
+
+ private int _currentIndex = -1;
+
+ public delegate void OnUndoStateChange(bool status);
+
+ public event OnUndoStateChange OnUndoStateChanged;
+
+ public delegate void OnRedoStateChange(bool status);
+
+ public event OnRedoStateChange OnRedoStateChanged;
+
+ public void CommitStrokeUserInputHistory(StrokeCollection stroke)
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ _currentStrokeHistory.Add(new TimeMachineHistory(stroke, TimeMachineHistoryType.UserInput, false));
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ }
+
+ public void CommitStrokeShapeHistory(StrokeCollection strokeToBeReplaced, StrokeCollection generatedStroke)
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ _currentStrokeHistory.Add(new TimeMachineHistory(generatedStroke,
+ TimeMachineHistoryType.ShapeRecognition,
+ false,
+ strokeToBeReplaced));
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ }
+
+ public void CommitStrokeManipulationHistory(Dictionary> stylusPointDictionary)
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ _currentStrokeHistory.Add(
+ new TimeMachineHistory(stylusPointDictionary,
+ TimeMachineHistoryType.Manipulation));
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ }
+ public void CommitStrokeDrawingAttributesHistory(Dictionary> drawingAttributes)
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ _currentStrokeHistory.Add(
+ new TimeMachineHistory(drawingAttributes,
+ TimeMachineHistoryType.DrawingAttributes));
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ }
+
+ public void CommitStrokeEraseHistory(StrokeCollection stroke, StrokeCollection sourceStroke = null)
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ _currentStrokeHistory.Add(new TimeMachineHistory(stroke, TimeMachineHistoryType.Clear, true, sourceStroke));
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ }
+
+ public void ClearStrokeHistory()
+ {
+ _currentStrokeHistory.Clear();
+ _currentIndex = -1;
+ NotifyUndoRedoState();
+ }
+
+ public TimeMachineHistory Undo()
+ {
+ var item = _currentStrokeHistory[_currentIndex];
+ item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
+ _currentIndex--;
+ OnUndoStateChanged?.Invoke(_currentIndex > -1);
+ OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
+ return item;
+ }
+
+ public TimeMachineHistory Redo()
+ {
+ var item = _currentStrokeHistory[++_currentIndex];
+ item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
+ NotifyUndoRedoState();
+ return item;
+ }
+
+ public TimeMachineHistory[] ExportTimeMachineHistory()
+ {
+ if (_currentIndex + 1 < _currentStrokeHistory.Count)
+ {
+ _currentStrokeHistory.RemoveRange(_currentIndex + 1, (_currentStrokeHistory.Count - 1) - _currentIndex);
+ }
+ return _currentStrokeHistory.ToArray();
+ }
+
+ public bool ImportTimeMachineHistory(TimeMachineHistory[] sourceHistory)
+ {
+ _currentStrokeHistory.Clear();
+ _currentStrokeHistory.AddRange(sourceHistory);
+ _currentIndex = _currentStrokeHistory.Count - 1;
+ NotifyUndoRedoState();
+ return true;
+ }
+ private void NotifyUndoRedoState()
+ {
+ OnUndoStateChanged?.Invoke(_currentIndex > -1);
+ OnRedoStateChanged?.Invoke(_currentStrokeHistory.Count - _currentIndex - 1 > 0);
+ }
+ }
+
+ public class TimeMachineHistory
+ {
+ public TimeMachineHistoryType CommitType;
+ public bool StrokeHasBeenCleared = false;
+ public StrokeCollection CurrentStroke;
+ public StrokeCollection ReplacedStroke;
+ //这里说一下 Tuple的 Value1 是初始值 ; Value 2 是改变值
+ public Dictionary> StylusPointDictionary;
+ public Dictionary> DrawingAttributes;
+ public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared)
+ {
+ CommitType = commitType;
+ CurrentStroke = currentStroke;
+ StrokeHasBeenCleared = strokeHasBeenCleared;
+ ReplacedStroke = null;
+ }
+ public TimeMachineHistory(Dictionary> stylusPointDictionary, TimeMachineHistoryType commitType)
+ {
+ CommitType = commitType;
+ StylusPointDictionary = stylusPointDictionary;
+ }
+ public TimeMachineHistory(Dictionary> drawingAttributes, TimeMachineHistoryType commitType)
+ {
+ CommitType = commitType;
+ DrawingAttributes = drawingAttributes;
+ }
+ public TimeMachineHistory(StrokeCollection currentStroke, TimeMachineHistoryType commitType, bool strokeHasBeenCleared, StrokeCollection replacedStroke)
+ {
+ CommitType = commitType;
+ CurrentStroke = currentStroke;
+ StrokeHasBeenCleared = strokeHasBeenCleared;
+ ReplacedStroke = replacedStroke;
+ }
+ }
+
+ public enum TimeMachineHistoryType
+ {
+ UserInput,
+ ShapeRecognition,
+ Clear,
+ Manipulation,
+ DrawingAttributes
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/Helpers/WinTabWindowsChecker.cs b/Ink Canvas/Helpers/WinTabWindowsChecker.cs
new file mode 100644
index 00000000..e97e58d3
--- /dev/null
+++ b/Ink Canvas/Helpers/WinTabWindowsChecker.cs
@@ -0,0 +1,73 @@
+using System.Windows.Automation;
+
+namespace Ink_Canvas.Helpers {
+ internal class WinTabWindowsChecker {
+ /*
+ public static bool IsWindowMinimized(string windowName, bool matchFullName = true) {
+ // 获取Win+Tab预览中的窗口
+ AutomationElementCollection windows = AutomationElement.RootElement.FindAll(
+ TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
+
+ foreach (AutomationElement window in windows) {
+ //LogHelper.WriteLogToFile("" + window.Current.Name);
+
+ string windowTitle = window.Current.Name;
+
+ // 如果窗口标题包含 windowName,则进行检查
+ if (!string.IsNullOrEmpty(windowTitle) && windowTitle.Contains(windowName)) {
+ if (matchFullName) {
+ if (windowTitle.Length == windowName.Length) {
+ // 检查窗口是否最小化
+ WindowPattern windowPattern = window.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
+ if (windowPattern != null) {
+ bool isMinimized = windowPattern.Current.WindowVisualState == WindowVisualState.Minimized;
+ //LogHelper.WriteLogToFile("" + windowTitle + isMinimized);
+ return isMinimized;
+ }
+ }
+ } else {
+ // 检查窗口是否最小化
+ WindowPattern windowPattern = window.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
+ if (windowPattern != null) {
+ bool isMinimized = windowPattern.Current.WindowVisualState == WindowVisualState.Minimized;
+ return isMinimized;
+ }
+ }
+ }
+ }
+ // 未找到软件白板窗口
+ return true;
+ }
+ */
+
+ public static bool IsWindowExisted(string windowName, bool matchFullName = true) {
+ // 获取Win+Tab预览中的窗口
+ AutomationElementCollection windows = AutomationElement.RootElement.FindAll(
+ TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
+
+ foreach (AutomationElement window in windows) {
+ //LogHelper.WriteLogToFile("" + window.Current.Name);
+
+ string windowTitle = window.Current.Name;
+
+ // 如果窗口标题包含 windowName,则进行检查
+ if (!string.IsNullOrEmpty(windowTitle) && windowTitle.Contains(windowName)) {
+ if (matchFullName) {
+ if (windowTitle.Length == windowName.Length) {
+ WindowPattern windowPattern = window.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
+ if (windowPattern != null) {
+ return true;
+ }
+ }
+ } else {
+ WindowPattern windowPattern = window.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
+ if (windowPattern != null) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/Ink Canvas/InkCanvasForClass.csproj b/Ink Canvas/InkCanvasForClass.csproj
new file mode 100644
index 00000000..fdd34062
--- /dev/null
+++ b/Ink Canvas/InkCanvasForClass.csproj
@@ -0,0 +1,561 @@
+
+
+ win;win-x86;win-x64;win-arm64
+ WinExe
+ Ink_Canvas
+ InkCanvasForClass
+ net472
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ true
+ false
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 2
+ 2.0.2.%2a
+ false
+ false
+ False
+ true
+ Debug;Release;x86 Debug
+
+
+ embedded
+ bin\$(Configuration)\
+ True
+
+
+ embedded
+ bin\$(Configuration)\
+ True
+
+
+ embedded
+ bin\$(Configuration)\
+ True
+
+
+ Resources\icc.ico
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ pdbonly
+ 7.3
+ true
+
+
+ app.manifest
+ InkCanvasForClass
+ 5.0.4
+ Dubi906w
+ InkCanvasForClass
+ © Copyright HARKOTEK Studio 2024-now
+ https://icc.bliemhax.com
+ bundled
+ False
+ AnyCPU
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ pdbonly
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ full
+ 7.3
+ true
+
+
+ bin\$(Platform)\$(Configuration)\
+ pdbonly
+ 7.3
+ true
+
+
+
+ .\IACore.dll
+
+
+ .\IALoader.dll
+
+
+ .\IAWinFX.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}
+ 1
+ 0
+ 0
+ tlbimp
+ False
+ True
+
+
+ {00020430-0000-0000-C000-000000000046}
+ 2
+ 0
+ 0
+ primary
+ False
+ True
+
+
+ {0002E157-0000-0000-C000-000000000046}
+ 5
+ 3
+ 0
+ primary
+ False
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/InkCanvasForClass.csproj.user b/Ink Canvas/InkCanvasForClass.csproj.user
new file mode 100644
index 00000000..92ed6d11
--- /dev/null
+++ b/Ink Canvas/InkCanvasForClass.csproj.user
@@ -0,0 +1,6 @@
+
+
+
+ <_LastSelectedProfileId>D:\vs\ica\Ink Canvas\Properties\PublishProfiles\FolderProfile.pubxml
+
+
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml
new file mode 100644
index 00000000..9e0f92e6
--- /dev/null
+++ b/Ink Canvas/MainWindow.xaml
@@ -0,0 +1,7254 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 左下
+
+
+ 右下
+
+
+ 左侧
+
+
+ 右侧
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 显示页码
+
+
+ 半透明
+
+
+ 黑色背景
+
+
+
+
+
+ 显示页码
+
+
+ 半透明
+
+
+ 黑色背景
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DesktopAnnotation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dubi906w
+
+
+ ICC 的开发者
+
+
+
+
+
+
+
+
+
+ ChangSakura
+
+
+ ICA 的开发者
+
+
+
+
+
+
+
+
+
+ WXRIW
+
+
+ Ink Canvas 的开发者
+
+
+
+
+
+ ICC 仓库源:
+
+
+
+
+
+ ICA 仓库源:
+
+
+
+
+
+ Ink Canvas 仓库源:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Raspberry Kan
+
+
+
+
+
+
+
+
+
+ Kengwang
+
+
+
+
+
+
+
+
+
+ Charles Jia
+
+
+
+
+
+
+
+
+
+ clover_yan
+
+
+
+
+
+
+
+
+
+ Netherite_Bowl
+
+
+
+
+
+
+
+
+
+ Yoojun Zhou
+
+
+
+
+
+
+
+
+
+ YuWenHui2020
+
+
+
+
+
+
+
+
+
+ ZongziTEK
+
+
+
+
+
+
+
+
+
+ Aesthed
+
+
+
+
+
+
+
+
+
+ Wei
+
+
+
+
+
+
+
+
+
+ Alan-CRL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs
new file mode 100644
index 00000000..f921ed2a
--- /dev/null
+++ b/Ink Canvas/MainWindow.xaml.cs
@@ -0,0 +1,310 @@
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern;
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Media;
+using System.Diagnostics;
+using File = System.IO.File;
+using MessageBox = System.Windows.MessageBox;
+using System.Runtime.InteropServices;
+using System.Windows.Interop;
+using System.Windows.Controls.Primitives;
+using System.Drawing;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Win32;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region Window Initialization
+
+ public MainWindow() {
+ /*
+ 处于画板模式内:Topmost == false / currentMode != 0
+ 处于 PPT 放映内:BtnPPTSlideShowEnd.Visibility
+ */
+ InitializeComponent();
+
+ BlackboardLeftSide.Visibility = Visibility.Collapsed;
+ BlackboardCenterSide.Visibility = Visibility.Collapsed;
+ BlackboardRightSide.Visibility = Visibility.Collapsed;
+ BorderTools.Visibility = Visibility.Collapsed;
+ BorderSettings.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ BorderSettings.Margin = new Thickness(0, 0, 0, 0);
+ TwoFingerGestureBorder.Visibility = Visibility.Collapsed;
+ BoardTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
+ BorderDrawShape.Visibility = Visibility.Collapsed;
+ BoardBorderDrawShape.Visibility = Visibility.Collapsed;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+
+ //if (!App.StartArgs.Contains("-o"))
+
+ ViewBoxStackPanelMain.Visibility = Visibility.Collapsed;
+ ViewBoxStackPanelShapes.Visibility = Visibility.Collapsed;
+ ViewboxFloatingBar.Margin = new Thickness((SystemParameters.WorkArea.Width - 284) / 2,
+ SystemParameters.WorkArea.Height - 60, -2000, -200);
+ ViewboxFloatingBarMarginAnimation(100, true);
+
+ try {
+ if (File.Exists("debug.ini")) Label.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ try {
+ if (File.Exists("Log.txt")) {
+ var fileInfo = new FileInfo("Log.txt");
+ var fileSizeInKB = fileInfo.Length / 1024;
+ if (fileSizeInKB > 512)
+ try {
+ File.Delete("Log.txt");
+ LogHelper.WriteLogToFile(
+ "The Log.txt file has been successfully deleted. Original file size: " + fileSizeInKB +
+ " KB", LogHelper.LogType.Info);
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(
+ ex + " | Can not delete the Log.txt file. File size: " + fileSizeInKB + " KB",
+ LogHelper.LogType.Error);
+ }
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ InitTimers();
+ timeMachine.OnRedoStateChanged += TimeMachine_OnRedoStateChanged;
+ timeMachine.OnUndoStateChanged += TimeMachine_OnUndoStateChanged;
+ inkCanvas.Strokes.StrokesChanged += StrokesOnStrokesChanged;
+
+ Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
+ try {
+ if (File.Exists("SpecialVersion.ini")) SpecialVersionResetToSuggestion_Click();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ CheckColorTheme(true);
+ CheckPenTypeUIState();
+ }
+
+ #endregion
+
+ #region Ink Canvas Functions
+
+ private System.Windows.Media.Color Ink_DefaultColor = Colors.Red;
+
+ private DrawingAttributes drawingAttributes;
+
+ private void loadPenCanvas() {
+ try {
+ //drawingAttributes = new DrawingAttributes();
+ drawingAttributes = inkCanvas.DefaultDrawingAttributes;
+ drawingAttributes.Color = Ink_DefaultColor;
+
+
+ drawingAttributes.Height = 2.5;
+ drawingAttributes.Width = 2.5;
+ drawingAttributes.IsHighlighter = false;
+ drawingAttributes.FitToCurve = Settings.Canvas.FitToCurve;
+
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.Gesture += InkCanvas_Gesture;
+ }
+ catch { }
+ }
+
+ //ApplicationGesture lastApplicationGesture = ApplicationGesture.AllGestures;
+ private DateTime lastGestureTime = DateTime.Now;
+
+ private void InkCanvas_Gesture(object sender, InkCanvasGestureEventArgs e) {
+ var gestures = e.GetGestureRecognitionResults();
+ try {
+ foreach (var gest in gestures)
+ //Trace.WriteLine(string.Format("Gesture: {0}, Confidence: {1}", gest.ApplicationGesture, gest.RecognitionConfidence));
+ if (StackPanelPPTControls.Visibility == Visibility.Visible) {
+ if (gest.ApplicationGesture == ApplicationGesture.Left)
+ BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
+ if (gest.ApplicationGesture == ApplicationGesture.Right)
+ BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
+ }
+ }
+ catch { }
+ }
+
+ private void inkCanvas_EditingModeChanged(object sender, RoutedEventArgs e) {
+ var inkCanvas1 = sender as InkCanvas;
+ if (inkCanvas1 == null) return;
+ if (Settings.Canvas.IsShowCursor) {
+ if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink || drawingShapeMode != 0)
+ inkCanvas1.ForceCursor = true;
+ else
+ inkCanvas1.ForceCursor = false;
+ } else {
+ inkCanvas1.ForceCursor = false;
+ }
+
+ if (inkCanvas1.EditingMode == InkCanvasEditingMode.Ink) forcePointEraser = !forcePointEraser;
+ }
+
+ #endregion Ink Canvas
+
+ #region Definations and Loading
+
+ public static Settings Settings = new Settings();
+ public static string settingsFileName = "Settings.json";
+ private bool isLoaded = false;
+
+ private void Window_Loaded(object sender, RoutedEventArgs e) {
+ loadPenCanvas();
+ //加载设置
+ LoadSettings(true);
+ // HasNewUpdateWindow hasNewUpdateWindow = new HasNewUpdateWindow();
+ if (Environment.Is64BitProcess) GroupBoxInkRecognition.Visibility = Visibility.Collapsed;
+
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
+ SystemEvents_UserPreferenceChanged(null, null);
+
+ //TextBlockVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ LogHelper.WriteLogToFile("Ink Canvas Loaded", LogHelper.LogType.Event);
+
+ isLoaded = true;
+
+ BlackBoardLeftSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection;
+ BlackBoardRightSidePageListView.ItemsSource = blackBoardSidePageListViewObservableCollection;
+
+ BtnLeftWhiteBoardSwitchPreviousGeometry.Brush =
+ new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
+ BtnRightWhiteBoardSwitchPreviousGeometry.Brush =
+ new SolidColorBrush(System.Windows.Media.Color.FromArgb(127, 24, 24, 27));
+ BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
+
+ BtnWhiteBoardSwitchPrevious.IsEnabled = CurrentWhiteboardIndex != 1;
+ BorderInkReplayToolBox.Visibility = Visibility.Collapsed;
+
+ // 提前加载IA库,优化第一笔等待时间
+ if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
+ var strokeEmpty = new StrokeCollection();
+ InkRecognizeHelper.RecognizeShape(strokeEmpty);
+ }
+
+ SystemEvents.DisplaySettingsChanged += SystemEventsOnDisplaySettingsChanged;
+ }
+
+ private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) {
+ if (!Settings.Advanced.IsEnableResolutionChangeDetection) return;
+ ShowNotification($"检测到显示器信息变化,变为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}");
+ new Thread(() => {
+ var isFloatingBarOutsideScreen = false;
+ var isInPPTPresentationMode = false;
+ Dispatcher.Invoke(() => {
+ isFloatingBarOutsideScreen = IsOutsideOfScreenHelper.IsOutsideOfScreen(ViewboxFloatingBar);
+ isInPPTPresentationMode = BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
+ });
+ if (isFloatingBarOutsideScreen) dpiChangedDelayAction.DebounceAction(3000, null, () => {
+ if (!isFloatingBarFolded)
+ {
+ if (isInPPTPresentationMode) ViewboxFloatingBarMarginAnimation(60);
+ else ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ });
+ }).Start();
+ }
+
+ public DelayAction dpiChangedDelayAction = new DelayAction();
+
+ private void MainWindow_OnDpiChanged(object sender, DpiChangedEventArgs e)
+ {
+ if (e.OldDpi.DpiScaleX != e.NewDpi.DpiScaleX && e.OldDpi.DpiScaleY != e.NewDpi.DpiScaleY && Settings.Advanced.IsEnableDPIChangeDetection)
+ {
+ ShowNotification($"系统DPI发生变化,从 {e.OldDpi.DpiScaleX}x{e.OldDpi.DpiScaleY} 变化为 {e.NewDpi.DpiScaleX}x{e.NewDpi.DpiScaleY}");
+
+ new Thread(() => {
+ var isFloatingBarOutsideScreen = false;
+ var isInPPTPresentationMode = false;
+ Dispatcher.Invoke(() => {
+ isFloatingBarOutsideScreen = IsOutsideOfScreenHelper.IsOutsideOfScreen(ViewboxFloatingBar);
+ isInPPTPresentationMode = BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
+ });
+ if (isFloatingBarOutsideScreen) dpiChangedDelayAction.DebounceAction(3000,null, () => {
+ if (!isFloatingBarFolded)
+ {
+ if (isInPPTPresentationMode) ViewboxFloatingBarMarginAnimation(60);
+ else ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ });
+ }).Start();
+ }
+ }
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
+ LogHelper.WriteLogToFile("Ink Canvas closing", LogHelper.LogType.Event);
+ if (!CloseIsFromButton && Settings.Advanced.IsSecondConfirmWhenShutdownApp) {
+ e.Cancel = true;
+ if (MessageBox.Show("是否继续关闭 InkCanvasForClass,这将丢失当前未保存的墨迹。", "InkCanvasForClass",
+ MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.OK)
+ if (MessageBox.Show("真的狠心关闭 InkCanvasForClass吗?", "InkCanvasForClass", MessageBoxButton.OKCancel,
+ MessageBoxImage.Error) == MessageBoxResult.OK)
+ if (MessageBox.Show("是否取消关闭 InkCanvasForClass?", "InkCanvasForClass", MessageBoxButton.OKCancel,
+ MessageBoxImage.Error) != MessageBoxResult.OK)
+ e.Cancel = false;
+ }
+
+ if (e.Cancel) LogHelper.WriteLogToFile("Ink Canvas closing cancelled", LogHelper.LogType.Event);
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
+
+ private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e) {
+ if (Settings.Advanced.IsEnableForceFullScreen) {
+ if (isLoaded) ShowNotification(
+ $"检测到窗口大小变化,已自动恢复到全屏:{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}(缩放比例为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight})");
+ WindowState = WindowState.Maximized;
+ MoveWindow(new WindowInteropHelper(this).Handle, 0, 0,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true);
+ }
+ }
+
+ private void Window_Closed(object sender, EventArgs e) {
+ SystemEvents.DisplaySettingsChanged -= SystemEventsOnDisplaySettingsChanged;
+
+ LogHelper.WriteLogToFile("Ink Canvas closed", LogHelper.LogType.Event);
+ }
+
+ private async void AutoUpdate() {
+ AvailableLatestVersion = await AutoUpdateHelper.CheckForUpdates();
+
+ if (AvailableLatestVersion != null) {
+ var IsDownloadSuccessful = false;
+ IsDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion);
+
+ if (IsDownloadSuccessful) {
+ if (!Settings.Startup.IsAutoUpdateWithSilence) {
+ if (MessageBox.Show("InkCanvasForClass 新版本安装包已下载完成,是否立即更新?",
+ "InkCanvasForClass New Version Available", MessageBoxButton.YesNo,
+ MessageBoxImage.Question) ==
+ MessageBoxResult.Yes) AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, false);
+ } else {
+ timerCheckAutoUpdateWithSilence.Start();
+ }
+ }
+ } else {
+ AutoUpdateHelper.DeleteUpdatesFolder();
+ }
+ }
+
+ #endregion Definations and Loading
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/ConfigHelper.cs b/Ink Canvas/MainWindow_cs/ConfigHelper.cs
new file mode 100644
index 00000000..9fa03cf7
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/ConfigHelper.cs
@@ -0,0 +1,6 @@
+namespace Ink_Canvas
+{
+ internal class ConfigHelper
+ {
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_AutoFold.cs b/Ink Canvas/MainWindow_cs/MW_AutoFold.cs
new file mode 100644
index 00000000..ee0c69df
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_AutoFold.cs
@@ -0,0 +1,272 @@
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern;
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Imaging;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ public bool isFloatingBarFolded = false;
+ private bool isFloatingBarChangingHideMode = false;
+
+ private void CloseWhiteboardImmediately() {
+ if (isDisplayingOrHidingBlackboard) return;
+ isDisplayingOrHidingBlackboard = true;
+ HideSubPanelsImmediately();
+ if (Settings.Gesture.AutoSwitchTwoFingerGesture) // 自动启用多指书写
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = false;
+ WaterMarkTime.Visibility = Visibility.Collapsed;
+ WaterMarkDate.Visibility = Visibility.Collapsed;
+ BlackBoardWaterMark.Visibility = Visibility.Collapsed;
+ ICCWaterMarkDark.Visibility = Visibility.Collapsed;
+ ICCWaterMarkWhite.Visibility = Visibility.Collapsed;
+ BtnSwitch_Click(BtnSwitch, null);
+ BtnExit.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(200);
+ Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; });
+ })).Start();
+ }
+
+ public async void FoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) {
+ await FoldFloatingBar(sender);
+ }
+
+ public async Task FoldFloatingBar(object sender)
+ {
+ var isShouldRejectAction = false;
+
+ await Dispatcher.InvokeAsync(() => {
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == Fold_Icon && lastBorderMouseDownObject != Fold_Icon) isShouldRejectAction = true;
+ });
+
+ if (isShouldRejectAction) return;
+
+ // FloatingBarIcons_MouseUp_New(sender);
+ if (sender == null)
+ foldFloatingBarByUser = false;
+ else
+ foldFloatingBarByUser = true;
+ unfoldFloatingBarByUser = false;
+
+ if (isFloatingBarChangingHideMode) return;
+
+ await Dispatcher.InvokeAsync(() => {
+ InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
+ InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
+ InkCanvasGridForInkReplay.IsHitTestVisible = true;
+ FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
+ FloatingbarUIForInkReplay.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+ AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
+ isStopInkReplay = true;
+ });
+
+ await Dispatcher.InvokeAsync(() => {
+ isFloatingBarChangingHideMode = true;
+ isFloatingBarFolded = true;
+ if (currentMode != 0) CloseWhiteboardImmediately();
+ if (StackPanelCanvasControls.Visibility == Visibility.Visible)
+ if (foldFloatingBarByUser && inkCanvas.Strokes.Count > 2)
+ ShowNotification("正在清空墨迹并收纳至侧边栏,可进入批注模式后通过【撤销】功能来恢复原先墨迹。");
+ lastBorderMouseDownObject = sender;
+ CursorWithDelIcon_Click(sender, null);
+ });
+
+ await Task.Delay(10);
+
+ await Dispatcher.InvokeAsync(() => {
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ ViewboxFloatingBarMarginAnimation(-60);
+ HideSubPanels("cursor");
+ SidePannelMarginAnimation(-10);
+ });
+ isFloatingBarChangingHideMode = false;
+ }
+
+ private async void LeftUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (Settings.Appearance.IsShowQuickPanel == true) {
+ HideRightQuickPanel();
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = new Thickness(-50, 0, 0, -150),
+ To = new Thickness(-1, 0, 0, -150)
+ };
+ marginAnimation.EasingFunction = new CubicEase();
+ LeftUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
+ });
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => {
+ LeftUnFoldButtonQuickPanel.Margin = new Thickness(-1, 0, 0, -150);
+ });
+ }
+ else {
+ UnFoldFloatingBar_MouseUp(sender, e);
+ }
+ }
+
+ private async void RightUnFoldButtonDisplayQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (Settings.Appearance.IsShowQuickPanel == true) {
+ HideLeftQuickPanel();
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Visible;
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = new Thickness(0, 0, -50, -150),
+ To = new Thickness(0, 0, -1, -150)
+ };
+ marginAnimation.EasingFunction = new CubicEase();
+ RightUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
+ });
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => {
+ RightUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -1, -150);
+ });
+ }
+ else {
+ UnFoldFloatingBar_MouseUp(sender, e);
+ }
+ }
+
+ private async void HideLeftQuickPanel() {
+ if (LeftUnFoldButtonQuickPanel.Visibility == Visibility.Visible) {
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = new Thickness(-1, 0, 0, -150),
+ To = new Thickness(-50, 0, 0, -150)
+ };
+ marginAnimation.EasingFunction = new CubicEase();
+ LeftUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
+ });
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => {
+ LeftUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -50, -150);
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ });
+ }
+ }
+
+ private async void HideRightQuickPanel() {
+ if (RightUnFoldButtonQuickPanel.Visibility == Visibility.Visible) {
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = new Thickness(0, 0, -1, -150),
+ To = new Thickness(0, 0, -50, -150)
+ };
+ marginAnimation.EasingFunction = new CubicEase();
+ RightUnFoldButtonQuickPanel.BeginAnimation(MarginProperty, marginAnimation);
+ });
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => {
+ RightUnFoldButtonQuickPanel.Margin = new Thickness(0, 0, -50, -150);
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ });
+ }
+ }
+
+ private void HideQuickPanel_MouseUp(object sender, MouseButtonEventArgs e) {
+ HideLeftQuickPanel();
+ HideRightQuickPanel();
+ }
+
+ public async void UnFoldFloatingBar_MouseUp(object sender, MouseButtonEventArgs e) {
+ await UnFoldFloatingBar(sender);
+ }
+
+ public async Task UnFoldFloatingBar(object sender)
+ {
+ await Dispatcher.InvokeAsync(() => {
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ });
+ if (sender == null || StackPanelPPTControls.Visibility == Visibility.Visible)
+ unfoldFloatingBarByUser = false;
+ else
+ unfoldFloatingBarByUser = true;
+ foldFloatingBarByUser = false;
+
+ if (isFloatingBarChangingHideMode) return;
+
+ await Dispatcher.InvokeAsync(() => {
+ isFloatingBarChangingHideMode = true;
+ isFloatingBarFolded = false;
+ });
+
+ await Task.Delay(0);
+
+ await Dispatcher.InvokeAsync(() => {
+ if (StackPanelPPTControls.Visibility == Visibility.Visible)
+ {
+ var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ var dopsc = dops.ToCharArray();
+ if (dopsc[0] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftBottomPanelForPPTNavigation);
+ if (dopsc[1] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightBottomPanelForPPTNavigation);
+ if (dopsc[2] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftSidePanelForPPTNavigation);
+ if (dopsc[3] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightSidePanelForPPTNavigation);
+ }
+
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ ViewboxFloatingBarMarginAnimation(60);
+ else
+ ViewboxFloatingBarMarginAnimation(100, true);
+ SidePannelMarginAnimation(-50, !unfoldFloatingBarByUser);
+ });
+
+ isFloatingBarChangingHideMode = false;
+ }
+
+ private async void SidePannelMarginAnimation(int MarginFromEdge, bool isNoAnimation = false) // Possible value: -50, -10
+ {
+ await Dispatcher.InvokeAsync(() => {
+ if (MarginFromEdge == -10) LeftSidePanel.Visibility = Visibility.Visible;
+
+ var LeftSidePanelmarginAnimation = new ThicknessAnimation {
+ Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
+ From = LeftSidePanel.Margin,
+ To = new Thickness(MarginFromEdge, 0, 0, -150)
+ };
+ LeftSidePanelmarginAnimation.EasingFunction = new CubicEase();
+ var RightSidePanelmarginAnimation = new ThicknessAnimation {
+ Duration = isNoAnimation == true ? TimeSpan.FromSeconds(0) : TimeSpan.FromSeconds(0.175),
+ From = RightSidePanel.Margin,
+ To = new Thickness(0, 0, MarginFromEdge, -150)
+ };
+ RightSidePanelmarginAnimation.EasingFunction = new CubicEase();
+ LeftSidePanel.BeginAnimation(MarginProperty, LeftSidePanelmarginAnimation);
+ RightSidePanel.BeginAnimation(MarginProperty, RightSidePanelmarginAnimation);
+ });
+
+ await Task.Delay(600);
+
+ await Dispatcher.InvokeAsync(() => {
+ LeftSidePanel.Margin = new Thickness(MarginFromEdge, 0, 0, -150);
+ RightSidePanel.Margin = new Thickness(0, 0, MarginFromEdge, -150);
+
+ if (MarginFromEdge == -50) LeftSidePanel.Visibility = Visibility.Collapsed;
+ });
+ isFloatingBarChangingHideMode = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_AutoStart.cs b/Ink Canvas/MainWindow_cs/MW_AutoStart.cs
new file mode 100644
index 00000000..b7887e5d
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_AutoStart.cs
@@ -0,0 +1,42 @@
+using IWshRuntimeLibrary;
+using System;
+using System.Windows;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ public static bool StartAutomaticallyCreate(string exeName) {
+ try {
+ var shell = new WshShell();
+ var shortcut = (IWshShortcut)shell.CreateShortcut(
+ Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk");
+ //设置快捷方式的目标所在的位置(源程序完整路径)
+ shortcut.TargetPath = System.Windows.Forms.Application.ExecutablePath;
+ //应用程序的工作目录
+ //当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
+ shortcut.WorkingDirectory = Environment.CurrentDirectory;
+ //目标应用程序窗口类型(1.Normal window普通窗口,3.Maximized最大化窗口,7.Minimized最小化)
+ shortcut.WindowStyle = 1;
+ //快捷方式的描述
+ shortcut.Description = exeName + "_Ink";
+ //设置快捷键(如果有必要的话.)
+ //shortcut.Hotkey = "CTRL+ALT+D";
+ shortcut.Save();
+ return true;
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+
+ public static bool StartAutomaticallyDel(string exeName) {
+ try {
+ System.IO.File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName +
+ ".lnk");
+ return true;
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs b/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs
new file mode 100644
index 00000000..7f0d7154
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs
@@ -0,0 +1,86 @@
+using Microsoft.Win32;
+using iNKORE.UI.WPF.Modern;
+using System;
+using System.Windows;
+using System.Windows.Media;
+using Application = System.Windows.Application;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private Color FloatBarForegroundColor = Color.FromRgb(102, 102, 102);
+
+ private void SetTheme(string theme) {
+ if (theme == "Light") {
+ var rd1 = new ResourceDictionary()
+ { Source = new Uri("Resources/Styles/Light.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd1);
+
+ var rd2 = new ResourceDictionary()
+ { Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd2);
+
+ var rd3 = new ResourceDictionary()
+ { Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd3);
+
+ var rd4 = new ResourceDictionary()
+ { Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd4);
+
+ ThemeManager.SetRequestedTheme(window, ElementTheme.Light);
+
+ FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
+ }
+ else if (theme == "Dark") {
+ var rd1 = new ResourceDictionary() { Source = new Uri("Resources/Styles/Dark.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd1);
+
+ var rd2 = new ResourceDictionary()
+ { Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd2);
+
+ var rd3 = new ResourceDictionary()
+ { Source = new Uri("Resources/SeewoImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd3);
+
+ var rd4 = new ResourceDictionary()
+ { Source = new Uri("Resources/IconImageDictionary.xaml", UriKind.Relative) };
+ Application.Current.Resources.MergedDictionaries.Add(rd4);
+
+ ThemeManager.SetRequestedTheme(window, ElementTheme.Dark);
+
+ FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
+ }
+ }
+
+ private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
+ switch (Settings.Appearance.Theme) {
+ case 0:
+ SetTheme("Light");
+ break;
+ case 1:
+ SetTheme("Dark");
+ break;
+ case 2:
+ if (IsSystemThemeLight()) SetTheme("Light");
+ else SetTheme("Dark");
+ break;
+ }
+ }
+
+ private bool IsSystemThemeLight() {
+ var light = false;
+ try {
+ var registryKey = Registry.CurrentUser;
+ var themeKey =
+ registryKey.OpenSubKey("software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
+ var keyValue = 0;
+ if (themeKey != null) keyValue = (int)themeKey.GetValue("SystemUsesLightTheme");
+ if (keyValue == 1) light = true;
+ }
+ catch { }
+
+ return light;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_BoardControls.cs b/Ink Canvas/MainWindow_cs/MW_BoardControls.cs
new file mode 100644
index 00000000..6e81a4d0
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_BoardControls.cs
@@ -0,0 +1,232 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media.Animation;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Xml.Linq;
+using System.Windows.Controls;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private StrokeCollection[] strokeCollections = new StrokeCollection[101];
+ private bool[] whiteboadLastModeIsRedo = new bool[101];
+ private StrokeCollection lastTouchDownStrokeCollection = new StrokeCollection();
+
+ private int CurrentWhiteboardIndex = 1;
+ private int WhiteboardTotalCount = 1;
+ private TimeMachineHistory[][] TimeMachineHistories = new TimeMachineHistory[101][]; //最多99页,0用来存储非白板时的墨迹以便还原
+
+ private void SaveStrokes(bool isBackupMain = false) {
+ if (isBackupMain) {
+ var timeMachineHistory = timeMachine.ExportTimeMachineHistory();
+ TimeMachineHistories[0] = timeMachineHistory;
+ timeMachine.ClearStrokeHistory();
+ } else {
+ var timeMachineHistory = timeMachine.ExportTimeMachineHistory();
+ TimeMachineHistories[CurrentWhiteboardIndex] = timeMachineHistory;
+ timeMachine.ClearStrokeHistory();
+ }
+ }
+
+ private void ClearStrokes(bool isErasedByCode) {
+ _currentCommitType = CommitReason.ClearingCanvas;
+ if (isErasedByCode) _currentCommitType = CommitReason.CodeInput;
+ inkCanvas.Strokes.Clear();
+ _currentCommitType = CommitReason.UserInput;
+ }
+
+ private void RestoreStrokes(bool isBackupMain = false) {
+ try {
+ if (TimeMachineHistories[CurrentWhiteboardIndex] == null) return; //防止白板打开后不居中
+ if (isBackupMain) {
+ timeMachine.ImportTimeMachineHistory(TimeMachineHistories[0]);
+ foreach (var item in TimeMachineHistories[0]) ApplyHistoryToCanvas(item);
+ } else {
+ timeMachine.ImportTimeMachineHistory(TimeMachineHistories[CurrentWhiteboardIndex]);
+ foreach (var item in TimeMachineHistories[CurrentWhiteboardIndex]) ApplyHistoryToCanvas(item);
+ }
+ }
+ catch {
+ // ignored
+ }
+ }
+
+ private async void BtnWhiteBoardPageIndex_Click(object sender, EventArgs e) {
+ if (sender == BtnLeftPageListWB) {
+ if (BoardBorderLeftPageListView.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
+ } else {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
+ RefreshBlackBoardSidePageListView();
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderLeftPageListView);
+ await Task.Delay(1);
+ ScrollViewToVerticalTop(
+ (ListViewItem)BlackBoardLeftSidePageListView.ItemContainerGenerator.ContainerFromIndex(
+ CurrentWhiteboardIndex - 1), BlackBoardLeftSidePageListScrollViewer);
+ }
+ } else if (sender == BtnRightPageListWB)
+ {
+ if (BoardBorderRightPageListView.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
+ } else {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
+ RefreshBlackBoardSidePageListView();
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderRightPageListView);
+ await Task.Delay(1);
+ ScrollViewToVerticalTop(
+ (ListViewItem)BlackBoardRightSidePageListView.ItemContainerGenerator.ContainerFromIndex(
+ CurrentWhiteboardIndex - 1), BlackBoardRightSidePageListScrollViewer);
+ }
+ }
+
+ }
+
+ private void BtnWhiteBoardSwitchPrevious_Click(object sender, EventArgs e) {
+ if (CurrentWhiteboardIndex <= 1) return;
+
+ SaveStrokes();
+
+ ClearStrokes(true);
+ CurrentWhiteboardIndex--;
+
+ RestoreStrokes();
+
+ UpdateIndexInfoDisplay();
+ }
+
+ private void BtnWhiteBoardSwitchNext_Click(object sender, EventArgs e) {
+ Trace.WriteLine("113223234");
+
+ if (Settings.Automation.IsAutoSaveStrokesAtClear &&
+ inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true);
+ if (CurrentWhiteboardIndex >= WhiteboardTotalCount) {
+ BtnWhiteBoardAdd_Click(sender, e);
+ return;
+ }
+
+ SaveStrokes();
+
+ ClearStrokes(true);
+ CurrentWhiteboardIndex++;
+
+ RestoreStrokes();
+
+ UpdateIndexInfoDisplay();
+ }
+
+ private void BtnWhiteBoardAdd_Click(object sender, EventArgs e) {
+ if (WhiteboardTotalCount >= 99) return;
+ if (Settings.Automation.IsAutoSaveStrokesAtClear &&
+ inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true);
+ SaveStrokes();
+ ClearStrokes(true);
+
+ WhiteboardTotalCount++;
+ CurrentWhiteboardIndex++;
+
+ if (CurrentWhiteboardIndex != WhiteboardTotalCount)
+ for (var i = WhiteboardTotalCount; i > CurrentWhiteboardIndex; i--)
+ TimeMachineHistories[i] = TimeMachineHistories[i - 1];
+
+ UpdateIndexInfoDisplay();
+
+ if (WhiteboardTotalCount >= 99) BtnWhiteBoardAdd.IsEnabled = false;
+
+ if (BlackBoardLeftSidePageListView.Visibility == Visibility.Visible) {
+ RefreshBlackBoardSidePageListView();
+ }
+ }
+
+ private void BtnWhiteBoardDelete_Click(object sender, RoutedEventArgs e) {
+ ClearStrokes(true);
+
+ if (CurrentWhiteboardIndex != WhiteboardTotalCount)
+ for (var i = CurrentWhiteboardIndex; i <= WhiteboardTotalCount; i++)
+ TimeMachineHistories[i] = TimeMachineHistories[i + 1];
+ else
+ CurrentWhiteboardIndex--;
+
+ WhiteboardTotalCount--;
+
+ RestoreStrokes();
+
+ UpdateIndexInfoDisplay();
+
+ if (WhiteboardTotalCount < 99) BtnWhiteBoardAdd.IsEnabled = true;
+ }
+
+ private void UpdateIndexInfoDisplay() {
+ TextBlockWhiteBoardIndexInfo.Text =
+ $"{CurrentWhiteboardIndex}/{WhiteboardTotalCount}";
+
+ if (CurrentWhiteboardIndex == WhiteboardTotalCount) {
+ var newImageSource = new BitmapImage();
+ newImageSource.BeginInit();
+ newImageSource.UriSource = new Uri("/Resources/Icons-Fluent/ic_fluent_add_circle_24_regular.png",
+ UriKind.RelativeOrAbsolute);
+ newImageSource.EndInit();
+ //BoardLeftPannelNextPage.Source = newImageSource;
+ //BoardRightPannelNextPage.Source = newImageSource;
+ //BoardRightPannelNextPageTextBlock.Text = "加页";
+ //BoardLeftPannelNextPageTextBlock.Text = "加页";
+ } else {
+ var newImageSource = new BitmapImage();
+ newImageSource.BeginInit();
+ newImageSource.UriSource =
+ new Uri("/Resources/Icons-Fluent/ic_fluent_arrow_circle_right_24_regular.png",
+ UriKind.RelativeOrAbsolute);
+ newImageSource.EndInit();
+ //BoardLeftPannelNextPage.Source = newImageSource;
+ //BoardRightPannelNextPage.Source = newImageSource;
+ //BoardRightPannelNextPageTextBlock.Text = "下一页";
+ //BoardLeftPannelNextPageTextBlock.Text = "下一页";
+ }
+
+ BtnWhiteBoardSwitchPrevious.IsEnabled = true;
+ BtnWhiteBoardSwitchNext.IsEnabled = true;
+
+ if (CurrentWhiteboardIndex == 1) {
+ BtnWhiteBoardSwitchPrevious.IsEnabled = false;
+ BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
+ BtnLeftWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchNextLabel.Opacity = 1;
+
+ BtnRightWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
+ BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
+ BtnRightWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnRightWhiteBoardSwitchNextLabel.Opacity = 1;
+ } else {
+ BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 1;
+
+ BtnRightWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 1;
+
+ if (CurrentWhiteboardIndex == WhiteboardTotalCount) {
+ BtnLeftWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchNextLabel.Opacity = 0.5;
+
+ BtnRightWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
+ BtnRightWhiteBoardSwitchNextLabel.Opacity = 0.5;
+ BtnWhiteBoardSwitchNext.IsEnabled = false;
+ } else {
+ BtnLeftWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnLeftWhiteBoardSwitchNextLabel.Opacity = 1;
+
+ BtnRightWhiteBoardSwitchNextGeometry.Brush = new SolidColorBrush(Color.FromArgb(255, 24, 24, 27));
+ BtnRightWhiteBoardSwitchNextLabel.Opacity = 1;
+ }
+ }
+
+ BtnWhiteBoardDelete.IsEnabled = WhiteboardTotalCount != 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs
new file mode 100644
index 00000000..9c810095
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs
@@ -0,0 +1,126 @@
+using Ink_Canvas.Helpers;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private void BoardChangeBackgroundColorBtn_MouseUp(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.UsingWhiteboard = !Settings.Canvas.UsingWhiteboard;
+ SaveSettingsToFile();
+ if (Settings.Canvas.UsingWhiteboard) {
+ if (inkColor == 5) lastBoardInkColor = 0;
+ ICCWaterMarkDark.Visibility = Visibility.Visible;
+ ICCWaterMarkWhite.Visibility = Visibility.Collapsed;
+ }
+ else {
+ if (inkColor == 0) lastBoardInkColor = 5;
+ ICCWaterMarkWhite.Visibility = Visibility.Visible;
+ ICCWaterMarkDark.Visibility = Visibility.Collapsed;
+ }
+
+ CheckColorTheme(true);
+ }
+
+ private void BoardEraserIcon_Click(object sender, RoutedEventArgs e) {
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint ||
+ inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke) {
+ if (BoardEraserSizePanel.Visibility == Visibility.Collapsed) {
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardEraserSizePanel);
+ } else {
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ }
+ } else {
+ forceEraser = true;
+ forcePointEraser = true;
+ double k = 1;
+ if (Settings.Canvas.EraserShapeType == 0) {
+ switch (BoardComboBoxEraserSize.SelectedIndex)
+ {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+ inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
+ } else if (Settings.Canvas.EraserShapeType == 1) {
+ switch (BoardComboBoxEraserSize.SelectedIndex)
+ {
+ case 0:
+ k = 0.7;
+ break;
+ case 1:
+ k = 0.9;
+ break;
+ case 3:
+ k = 1.2;
+ break;
+ case 4:
+ k = 1.6;
+ break;
+ }
+ inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
+ }
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ drawingShapeMode = 0;
+
+ inkCanvas_EditingModeChanged(inkCanvas, null);
+ CancelSingleFingerDragMode();
+
+ HideSubPanels("eraser");
+ }
+ }
+
+ private void BoardEraserIconByStrokes_Click(object sender, RoutedEventArgs e) {
+ //if (BoardEraserByStrokes.Background.ToString() == "#FF679CF4") {
+ // AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardDeleteIcon);
+ //}
+ //else {
+ forceEraser = true;
+ forcePointEraser = false;
+
+ inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
+ drawingShapeMode = 0;
+
+ inkCanvas_EditingModeChanged(inkCanvas, null);
+ CancelSingleFingerDragMode();
+
+ HideSubPanels("eraserByStrokes");
+ //}
+ }
+
+ private void BoardSymbolIconDelete_MouseUp(object sender, RoutedEventArgs e) {
+ PenIcon_Click(null, null);
+ SymbolIconDelete_MouseUp(null, null);
+ }
+ private void BoardSymbolIconDeleteInkAndHistories_MouseUp(object sender, RoutedEventArgs e)
+ {
+ PenIcon_Click(null, null);
+ SymbolIconDelete_MouseUp(null, null);
+ if (Settings.Canvas.ClearCanvasAndClearTimeMachine == false) timeMachine.ClearStrokeHistory();
+ }
+
+ private void BoardLaunchEasiCamera_MouseUp(object sender, MouseButtonEventArgs e) {
+ ImageBlackboard_MouseUp(null, null);
+ SoftwareLauncher.LaunchEasiCamera("希沃视频展台");
+ }
+
+ private void BoardLaunchDesmos_MouseUp(object sender, MouseButtonEventArgs e) {
+ HideSubPanelsImmediately();
+ ImageBlackboard_MouseUp(null, null);
+ Process.Start("https://www.desmos.com/calculator?lang=zh-CN");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs
new file mode 100644
index 00000000..d1d11883
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs
@@ -0,0 +1,695 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Media.Imaging;
+using System.Windows.Media;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media.Animation;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private int inkColor = 1;
+
+ private void ColorSwitchCheck() {
+ HideSubPanels("color");
+ if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
+ if (currentMode == 1) {
+ currentMode = 0;
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+ }
+
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+ }
+
+ var strokes = inkCanvas.GetSelectedStrokes();
+ if (strokes.Count != 0) {
+ foreach (var stroke in strokes)
+ try {
+ stroke.DrawingAttributes.Color = inkCanvas.DefaultDrawingAttributes.Color;
+ }
+ catch {
+ // ignored
+ }
+ }
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ else {
+ inkCanvas.IsManipulationEnabled = true;
+ drawingShapeMode = 0;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ CancelSingleFingerDragMode();
+ forceEraser = false;
+ CheckColorTheme();
+ }
+
+ isLongPressSelected = false;
+ }
+
+ private bool isUselightThemeColor = false, isDesktopUselightThemeColor = false;
+ private int penType = 0; // 0是签字笔,1是荧光笔
+ private int lastDesktopInkColor = 1, lastBoardInkColor = 5;
+ private int highlighterColor = 102;
+
+ private void CheckColorTheme(bool changeColorTheme = false) {
+ if (changeColorTheme)
+ if (currentMode != 0) {
+ if (Settings.Canvas.UsingWhiteboard) {
+ GridBackgroundCover.Background = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ isUselightThemeColor = false;
+ }
+ else {
+ GridBackgroundCover.Background = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ isUselightThemeColor = true;
+ }
+ }
+
+ if (currentMode == 0) {
+ isUselightThemeColor = isDesktopUselightThemeColor;
+ inkColor = lastDesktopInkColor;
+ }
+ else {
+ inkColor = lastBoardInkColor;
+ }
+
+ double alpha = inkCanvas.DefaultDrawingAttributes.Color.A;
+
+ if (penType == 0) {
+ if (inkColor == 0) {
+ // Black
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 0, 0, 0);
+ }
+ else if (inkColor == 5) {
+ // White
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 255, 255, 255);
+ }
+ else if (isUselightThemeColor) {
+ if (inkColor == 1)
+ // Red
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 239, 68, 68);
+ else if (inkColor == 2)
+ // Green
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 34, 197, 94);
+ else if (inkColor == 3)
+ // Blue
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 59, 130, 246);
+ else if (inkColor == 4)
+ // Yellow
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 250, 204, 21);
+ else if (inkColor == 6)
+ // Pink
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 236, 72, 153);
+ else if (inkColor == 7)
+ // Teal (亮色)
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 20, 184, 166);
+ else if (inkColor == 8)
+ // Orange (亮色)
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 249, 115, 22);
+ }
+ else {
+ if (inkColor == 1)
+ // Red
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 220, 38, 38);
+ else if (inkColor == 2)
+ // Green
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 22, 163, 74);
+ else if (inkColor == 3)
+ // Blue
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 37, 99, 235);
+ else if (inkColor == 4)
+ // Yellow
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 234, 179, 8);
+ else if (inkColor == 6)
+ // Pink ( Purple )
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 147, 51, 234);
+ else if (inkColor == 7)
+ // Teal (暗色)
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 13, 148, 136);
+ else if (inkColor == 8)
+ // Orange (暗色)
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb((byte)alpha, 234, 88, 12);
+ }
+ }
+ else if (penType == 1) {
+ if (highlighterColor == 100)
+ // Black
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(0, 0, 0);
+ else if (highlighterColor == 101)
+ // White
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(250, 250, 250);
+ else if (highlighterColor == 102)
+ // Red
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(239, 68, 68);
+ else if (highlighterColor == 103)
+ // Yellow
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(253, 224, 71);
+ else if (highlighterColor == 104)
+ // Green
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(74, 222, 128);
+ else if (highlighterColor == 105)
+ // Zinc
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(113, 113, 122);
+ else if (highlighterColor == 106)
+ // Blue
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(59, 130, 246);
+ else if (highlighterColor == 107)
+ // Purple
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(168, 85, 247);
+ else if (highlighterColor == 108)
+ // teal
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(45, 212, 191);
+ else if (highlighterColor == 109)
+ // Orange
+ inkCanvas.DefaultDrawingAttributes.Color = Color.FromRgb(249, 115, 22);
+ }
+
+ if (isUselightThemeColor) {
+ // 亮系
+ // 亮色的红色
+ BorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(239, 68, 68));
+ BoardBorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(239, 68, 68));
+ // 亮色的绿色
+ BorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(34, 197, 94));
+ BoardBorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(34, 197, 94));
+ // 亮色的蓝色
+ BorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(59, 130, 246));
+ BoardBorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(59, 130, 246));
+ // 亮色的黄色
+ BorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(250, 204, 21));
+ BoardBorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(250, 204, 21));
+ // 亮色的粉色
+ BorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(236, 72, 153));
+ BoardBorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(236, 72, 153));
+ // 亮色的Teal
+ BorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(20, 184, 166));
+ BoardBorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(20, 184, 166));
+ // 亮色的Orange
+ BorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(249, 115, 22));
+ BoardBorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(249, 115, 22));
+
+ var newImageSource = new BitmapImage();
+ newImageSource.BeginInit();
+ newImageSource.UriSource = new Uri("/Resources/Icons-Fluent/ic_fluent_weather_moon_24_regular.png",
+ UriKind.RelativeOrAbsolute);
+ newImageSource.EndInit();
+ ColorThemeSwitchIcon.Source = newImageSource;
+ BoardColorThemeSwitchIcon.Source = newImageSource;
+
+ ColorThemeSwitchTextBlock.Text = "暗系";
+ BoardColorThemeSwitchTextBlock.Text = "暗系";
+ }
+ else {
+ // 暗系
+ // 暗色的红色
+ BorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(220, 38, 38));
+ BoardBorderPenColorRed.Background = new SolidColorBrush(Color.FromRgb(220, 38, 38));
+ // 暗色的绿色
+ BorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74));
+ BoardBorderPenColorGreen.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74));
+ // 暗色的蓝色
+ BorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardBorderPenColorBlue.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ // 暗色的黄色
+ BorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(234, 179, 8));
+ BoardBorderPenColorYellow.Background = new SolidColorBrush(Color.FromRgb(234, 179, 8));
+ // 暗色的紫色对应亮色的粉色
+ BorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(147, 51, 234));
+ BoardBorderPenColorPink.Background = new SolidColorBrush(Color.FromRgb(147, 51, 234));
+ // 暗色的Teal
+ BorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(13, 148, 136));
+ BoardBorderPenColorTeal.Background = new SolidColorBrush(Color.FromRgb(13, 148, 136));
+ // 暗色的Orange
+ BorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(234, 88, 12));
+ BoardBorderPenColorOrange.Background = new SolidColorBrush(Color.FromRgb(234, 88, 12));
+
+ var newImageSource = new BitmapImage();
+ newImageSource.BeginInit();
+ newImageSource.UriSource = new Uri("/Resources/Icons-Fluent/ic_fluent_weather_sunny_24_regular.png",
+ UriKind.RelativeOrAbsolute);
+ newImageSource.EndInit();
+ ColorThemeSwitchIcon.Source = newImageSource;
+ BoardColorThemeSwitchIcon.Source = newImageSource;
+
+ ColorThemeSwitchTextBlock.Text = "亮系";
+ BoardColorThemeSwitchTextBlock.Text = "亮系";
+ }
+
+ // 改变选中提示
+ ViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorPinkContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
+ ViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
+
+ BoardViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorPinkContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
+ BoardViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
+
+ HighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
+ HighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Collapsed;
+
+ BoardHighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Collapsed;
+
+ switch (inkColor) {
+ case 0:
+ ViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
+ break;
+ case 1:
+ ViewboxBtnColorRedContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorRedContent.Visibility = Visibility.Visible;
+ break;
+ case 2:
+ ViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
+ break;
+ case 3:
+ ViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
+ break;
+ case 4:
+ ViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
+ break;
+ case 5:
+ ViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
+ break;
+ case 6:
+ ViewboxBtnColorPinkContent.Visibility = Visibility.Visible;
+ BoardViewboxBtnColorPinkContent.Visibility = Visibility.Visible;
+ break;
+ case 7:
+ ViewboxBtnColorTealContent.Visibility = Visibility.Visible;
+ break;
+ case 8:
+ ViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
+ break;
+ }
+
+ switch (highlighterColor) {
+ case 100:
+ HighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorBlackContent.Visibility = Visibility.Visible;
+ break;
+ case 101:
+ HighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorWhiteContent.Visibility = Visibility.Visible;
+ break;
+ case 102:
+ HighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorRedContent.Visibility = Visibility.Visible;
+ break;
+ case 103:
+ HighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorYellowContent.Visibility = Visibility.Visible;
+ break;
+ case 104:
+ HighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorGreenContent.Visibility = Visibility.Visible;
+ break;
+ case 105:
+ HighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorZincContent.Visibility = Visibility.Visible;
+ break;
+ case 106:
+ HighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorBlueContent.Visibility = Visibility.Visible;
+ break;
+ case 107:
+ HighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorPurpleContent.Visibility = Visibility.Visible;
+ break;
+ case 108:
+ HighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorTealContent.Visibility = Visibility.Visible;
+ break;
+ case 109:
+ HighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
+ BoardHighlighterPenViewboxBtnColorOrangeContent.Visibility = Visibility.Visible;
+ break;
+ }
+ }
+
+ private void CheckLastColor(int inkColor, bool isHighlighter = false) {
+ if (isHighlighter == true) {
+ highlighterColor = inkColor;
+ }
+ else {
+ if (currentMode == 0) lastDesktopInkColor = inkColor;
+ else lastBoardInkColor = inkColor;
+ }
+ }
+
+ private async void CheckPenTypeUIState() {
+ if (penType == 0) {
+ DefaultPenPropsPanel.Visibility = Visibility.Visible;
+ DefaultPenColorsPanel.Visibility = Visibility.Visible;
+ HighlighterPenColorsPanel.Visibility = Visibility.Collapsed;
+ HighlighterPenPropsPanel.Visibility = Visibility.Collapsed;
+ DefaultPenTabButton.Opacity = 1;
+ DefaultPenTabButtonText.FontWeight = FontWeights.Bold;
+ DefaultPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ DefaultPenTabButtonText.FontSize = 9.5;
+ DefaultPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
+ DefaultPenTabButtonIndicator.Visibility = Visibility.Visible;
+ HighlightPenTabButton.Opacity = 0.9;
+ HighlightPenTabButtonText.FontWeight = FontWeights.Normal;
+ HighlightPenTabButtonText.FontSize = 9;
+ HighlightPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ HighlightPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ HighlightPenTabButtonIndicator.Visibility = Visibility.Collapsed;
+
+ BoardDefaultPenPropsPanel.Visibility = Visibility.Visible;
+ BoardDefaultPenColorsPanel.Visibility = Visibility.Visible;
+ BoardHighlighterPenColorsPanel.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenPropsPanel.Visibility = Visibility.Collapsed;
+ BoardDefaultPenTabButton.Opacity = 1;
+ BoardDefaultPenTabButtonText.FontWeight = FontWeights.Bold;
+ BoardDefaultPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ BoardDefaultPenTabButtonText.FontSize = 9.5;
+ BoardDefaultPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
+ BoardDefaultPenTabButtonIndicator.Visibility = Visibility.Visible;
+ BoardHighlightPenTabButton.Opacity = 0.9;
+ BoardHighlightPenTabButtonText.FontWeight = FontWeights.Normal;
+ BoardHighlightPenTabButtonText.FontSize = 9;
+ BoardHighlightPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ BoardHighlightPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ BoardHighlightPenTabButtonIndicator.Visibility = Visibility.Collapsed;
+
+ // PenPalette.Margin = new Thickness(-160, -200, -33, 32);
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = PenPalette.Margin,
+ To = new Thickness(-160, -200, -33, 32),
+ EasingFunction = new CubicEase()
+ };
+ PenPalette.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = PenPalette.Margin,
+ To = new Thickness(-160, -200, -33, 50),
+ EasingFunction = new CubicEase()
+ };
+ BoardPenPaletteGrid.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => { PenPalette.Margin = new Thickness(-160, -200, -33, 32); });
+
+ await Dispatcher.InvokeAsync(() => { BoardPenPaletteGrid.Margin = new Thickness(-160, -200, -33, 50); });
+ }
+ else if (penType == 1) {
+ DefaultPenPropsPanel.Visibility = Visibility.Collapsed;
+ DefaultPenColorsPanel.Visibility = Visibility.Collapsed;
+ HighlighterPenColorsPanel.Visibility = Visibility.Visible;
+ HighlighterPenPropsPanel.Visibility = Visibility.Visible;
+ DefaultPenTabButton.Opacity = 0.9;
+ DefaultPenTabButtonText.FontWeight = FontWeights.Normal;
+ DefaultPenTabButtonText.FontSize = 9;
+ DefaultPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ DefaultPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ DefaultPenTabButtonIndicator.Visibility = Visibility.Collapsed;
+ HighlightPenTabButton.Opacity = 1;
+ HighlightPenTabButtonText.FontWeight = FontWeights.Bold;
+ HighlightPenTabButtonText.FontSize = 9.5;
+ HighlightPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ HighlightPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
+ HighlightPenTabButtonIndicator.Visibility = Visibility.Visible;
+
+ BoardDefaultPenPropsPanel.Visibility = Visibility.Collapsed;
+ BoardDefaultPenColorsPanel.Visibility = Visibility.Collapsed;
+ BoardHighlighterPenColorsPanel.Visibility = Visibility.Visible;
+ BoardHighlighterPenPropsPanel.Visibility = Visibility.Visible;
+ BoardDefaultPenTabButton.Opacity = 0.9;
+ BoardDefaultPenTabButtonText.FontWeight = FontWeights.Normal;
+ BoardDefaultPenTabButtonText.FontSize = 9;
+ BoardDefaultPenTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ BoardDefaultPenTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ BoardDefaultPenTabButtonIndicator.Visibility = Visibility.Collapsed;
+ BoardHighlightPenTabButton.Opacity = 1;
+ BoardHighlightPenTabButtonText.FontWeight = FontWeights.Bold;
+ BoardHighlightPenTabButtonText.FontSize = 9.5;
+ BoardHighlightPenTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ BoardHighlightPenTabButton.Background = new SolidColorBrush(Color.FromArgb(72, 219, 234, 254));
+ BoardHighlightPenTabButtonIndicator.Visibility = Visibility.Visible;
+
+ // PenPalette.Margin = new Thickness(-160, -157, -33, 32);
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = PenPalette.Margin,
+ To = new Thickness(-160, -157, -33, 32),
+ EasingFunction = new CubicEase()
+ };
+ PenPalette.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Dispatcher.InvokeAsync(() => {
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.1),
+ From = PenPalette.Margin,
+ To = new Thickness(-160, -154, -33, 50),
+ EasingFunction = new CubicEase()
+ };
+ BoardPenPaletteGrid.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Task.Delay(100);
+
+ await Dispatcher.InvokeAsync(() => { PenPalette.Margin = new Thickness(-160, -157, -33, 32); });
+
+ await Dispatcher.InvokeAsync(() => { BoardPenPaletteGrid.Margin = new Thickness(-160, -154, -33, 50); });
+ }
+ }
+
+ private void SwitchToDefaultPen(object sender, MouseButtonEventArgs e) {
+ penType = 0;
+ CheckPenTypeUIState();
+ CheckColorTheme();
+ drawingAttributes.Width = Settings.Canvas.InkWidth;
+ drawingAttributes.Height = Settings.Canvas.InkWidth;
+ drawingAttributes.StylusTip = StylusTip.Ellipse;
+ drawingAttributes.IsHighlighter = false;
+ }
+
+ private void SwitchToHighlighterPen(object sender, MouseButtonEventArgs e) {
+ penType = 1;
+ CheckPenTypeUIState();
+ CheckColorTheme();
+ drawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2;
+ drawingAttributes.Height = Settings.Canvas.HighlighterWidth;
+ drawingAttributes.StylusTip = StylusTip.Rectangle;
+ drawingAttributes.IsHighlighter = true;
+ }
+
+ private void BtnColorBlack_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(0);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorRed_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(1);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorGreen_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(2);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorBlue_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(3);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorYellow_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(4);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorWhite_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(5);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorPink_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(6);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorOrange_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(8);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnColorTeal_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(7);
+ forceEraser = false;
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorBlack_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(100, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorWhite_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(101, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorRed_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(102, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorYellow_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(103, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorGreen_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(104, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorZinc_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(105, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorBlue_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(106, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorPurple_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(107, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorTeal_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(108, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private void BtnHighlighterColorOrange_Click(object sender, RoutedEventArgs e) {
+ CheckLastColor(109, true);
+ penType = 1;
+ forceEraser = false;
+ CheckPenTypeUIState();
+ ColorSwitchCheck();
+ }
+
+ private Color StringToColor(string colorStr) {
+ var argb = new byte[4];
+ for (var i = 0; i < 4; i++) {
+ var charArray = colorStr.Substring(i * 2 + 1, 2).ToCharArray();
+ var b1 = toByte(charArray[0]);
+ var b2 = toByte(charArray[1]);
+ argb[i] = (byte)(b2 | (b1 << 4));
+ }
+
+ return Color.FromArgb(argb[0], argb[1], argb[2], argb[3]); //#FFFFFFFF
+ }
+
+ private static byte toByte(char c) {
+ var b = (byte)"0123456789ABCDEF".IndexOf(c);
+ return b;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs
new file mode 100644
index 00000000..bcd4c143
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs
@@ -0,0 +1,1895 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Threading;
+using System.Windows.Interop;
+using System.Windows.Media.Imaging;
+using iNKORE.UI.WPF.Modern;
+using System.Threading;
+using Application = System.Windows.Application;
+using Point = System.Windows.Point;
+using System.Diagnostics;
+using iNKORE.UI.WPF.Modern.Controls;
+using System.IO;
+using System.Windows.Media.Effects;
+using static System.Net.Mime.MediaTypeNames;
+using System.Text;
+using System.Globalization;
+using System.Windows.Data;
+using System.Xml.Linq;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region “手勢”按鈕
+
+ ///
+ /// 用於浮動工具欄的“手勢”按鈕和白板工具欄的“手勢”按鈕的點擊事件
+ ///
+ private void TwoFingerGestureBorder_MouseUp(object sender, RoutedEventArgs e) {
+ if (TwoFingerGestureBorder.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ }
+ else {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardTwoFingerGestureBorder);
+ }
+ }
+
+ ///
+ /// 用於更新浮動工具欄的“手勢”按鈕和白板工具欄的“手勢”按鈕的樣式(開啟和關閉狀態)
+ ///
+ private void CheckEnableTwoFingerGestureBtnColorPrompt() {
+ if (ToggleSwitchEnableMultiTouchMode.IsOn) {
+ TwoFingerGestureSimpleStackPanel.Opacity = 0.5;
+ TwoFingerGestureSimpleStackPanel.IsHitTestVisible = false;
+ EnableTwoFingerGestureBtn.Source =
+ new BitmapImage(new Uri("/Resources/new-icons/gesture.png", UriKind.Relative));
+
+ BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ BoardGestureGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.DisabledGestureIcon);
+ BoardGestureGeometry2.Geometry = Geometry.Parse("F0 M24,24z M0,0z");
+ }
+ else {
+ TwoFingerGestureSimpleStackPanel.Opacity = 1;
+ TwoFingerGestureSimpleStackPanel.IsHitTestVisible = true;
+ if (Settings.Gesture.IsEnableTwoFingerGesture) {
+ EnableTwoFingerGestureBtn.Source =
+ new BitmapImage(new Uri("/Resources/new-icons/gesture-enabled.png", UriKind.Relative));
+
+ BoardGesture.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardGestureGeometry.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardGestureGeometry2.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardGestureLabel.Foreground = new SolidColorBrush(Colors.GhostWhite);
+ BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardGestureGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.EnabledGestureIcon);
+ BoardGestureGeometry2.Geometry = Geometry.Parse("F0 M24,24z M0,0z "+XamlGraphicsIconGeometries.EnabledGestureIconBadgeCheck);
+ }
+ else {
+ EnableTwoFingerGestureBtn.Source =
+ new BitmapImage(new Uri("/Resources/new-icons/gesture.png", UriKind.Relative));
+
+ BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ BoardGestureGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.DisabledGestureIcon);
+ BoardGestureGeometry2.Geometry = Geometry.Parse("F0 M24,24z M0,0z");
+ }
+ }
+ }
+
+ ///
+ /// 控制是否顯示浮動工具欄的“手勢”按鈕
+ ///
+ private void CheckEnableTwoFingerGestureBtnVisibility(bool isVisible) {
+ if (StackPanelCanvasControls.Visibility != Visibility.Visible
+ || BorderFloatingBarMainControls.Visibility != Visibility.Visible) {
+ EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
+ }
+ else if (isVisible == true) {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
+ else EnableTwoFingerGestureBorder.Visibility = Visibility.Visible;
+ }
+ else {
+ EnableTwoFingerGestureBorder.Visibility = Visibility.Collapsed;
+ }
+ }
+
+ #endregion “手勢”按鈕
+
+ #region 浮動工具欄的拖動實現
+
+ private bool isDragDropInEffect = false;
+ private Point pos = new Point();
+ private Point downPos = new Point();
+ private Point pointDesktop = new Point(-1, -1); //用于记录上次在桌面时的坐标
+ private Point pointPPT = new Point(-1, -1); //用于记录上次在PPT中的坐标
+
+ private void SymbolIconEmoji_MouseMove(object sender, MouseEventArgs e) {
+ if (isDragDropInEffect) {
+ var xPos = e.GetPosition(null).X - pos.X + ViewboxFloatingBar.Margin.Left;
+ var yPos = e.GetPosition(null).Y - pos.Y + ViewboxFloatingBar.Margin.Top;
+ ViewboxFloatingBar.Margin = new Thickness(xPos, yPos, -2000, -200);
+
+ pos = e.GetPosition(null);
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ pointPPT = new Point(xPos, yPos);
+ else
+ pointDesktop = new Point(xPos, yPos);
+ }
+ }
+
+ private void SymbolIconEmoji_MouseDown(object sender, MouseButtonEventArgs e) {
+ if (isViewboxFloatingBarMarginAnimationRunning) {
+ ViewboxFloatingBar.BeginAnimation(MarginProperty, null);
+ isViewboxFloatingBarMarginAnimationRunning = false;
+ }
+
+ isDragDropInEffect = true;
+ pos = e.GetPosition(null);
+ downPos = e.GetPosition(null);
+ GridForFloatingBarDraging.Visibility = Visibility.Visible;
+ }
+
+ private void SymbolIconEmoji_MouseUp(object sender, MouseButtonEventArgs e) {
+ isDragDropInEffect = false;
+
+ if (e is null || (Math.Abs(downPos.X - e.GetPosition(null).X) <= 10 &&
+ Math.Abs(downPos.Y - e.GetPosition(null).Y) <= 10)) {
+ if (BorderFloatingBarMainControls.Visibility == Visibility.Visible) {
+ BorderFloatingBarMainControls.Visibility = Visibility.Collapsed;
+ CheckEnableTwoFingerGestureBtnVisibility(false);
+ }
+ else {
+ BorderFloatingBarMainControls.Visibility = Visibility.Visible;
+ CheckEnableTwoFingerGestureBtnVisibility(true);
+ }
+ }
+
+ GridForFloatingBarDraging.Visibility = Visibility.Collapsed;
+ }
+
+ #endregion 浮動工具欄的拖動實現
+
+ #region 隱藏子面板和按鈕背景高亮
+
+ ///
+ /// 隱藏形狀繪製面板
+ ///
+ private void CollapseBorderDrawShape()
+ {
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ }
+
+ ///
+ /// HideSubPanels的青春版。目前需要修改BorderSettings的關閉機制(改為動畫關閉)。
+ ///
+ private void HideSubPanelsImmediately()
+ {
+ BorderTools.Visibility = Visibility.Collapsed;
+ BoardBorderTools.Visibility = Visibility.Collapsed;
+ PenPalette.Visibility = Visibility.Collapsed;
+ BoardPenPalette.Visibility = Visibility.Collapsed;
+ BoardEraserSizePanel.Visibility = Visibility.Collapsed;
+ EraserSizePanel.Visibility = Visibility.Collapsed;
+ BorderSettings.Visibility = Visibility.Collapsed;
+ BoardBorderLeftPageListView.Visibility = Visibility.Collapsed;
+ BoardBorderRightPageListView.Visibility = Visibility.Collapsed;
+ }
+
+ ///
+ ///
+ /// 易嚴定真,這個多功能函數包括了以下的內容:
+ ///
+ ///
+ /// -
+ /// 隱藏浮動工具欄和白板模式下的“更多功能”面板
+ ///
+ /// -
+ /// 隱藏白板模式下和浮動工具欄的畫筆調色盤
+ ///
+ /// -
+ /// 隱藏白板模式下的“清屏”按鈕(已作廢)
+ ///
+ /// -
+ /// 負責給Settings設置面板做隱藏動畫
+ ///
+ /// -
+ /// 隱藏白板模式下和浮動工具欄的“手勢”面板
+ ///
+ /// -
+ /// 當ToggleSwitchDrawShapeBorderAutoHide開啟時,會自動隱藏白板模式下和浮動工具欄的“形狀”面板
+ ///
+ /// -
+ /// 按需高亮指定的浮動工具欄和白板工具欄中的按鈕,通過param: 來指定
+ ///
+ /// -
+ /// 將浮動工具欄自動居中,通過param:
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 按需高亮指定的浮動工具欄和白板工具欄中的按鈕,有下面幾種情況:
+ ///
+ ///
+ /// -
+ /// 當==null時,不會執行任何有關操作
+ ///
+ /// -
+ /// 當!="clear"時,會先取消高亮所有工具欄按鈕,然後根據下面的情況進行高亮處理
+ ///
+ /// -
+ /// 當=="color" || =="pen"時,會高亮浮動工具欄和白板工具欄中的“批註”,“筆”按鈕
+ ///
+ /// -
+ /// 當=="eraser"時,會高亮白板工具欄中的“橡皮”和浮動工具欄中的“面積擦”按鈕
+ ///
+ /// -
+ /// 當=="eraserByStrokes"時,會高亮白板工具欄中的“橡皮”和浮動工具欄中的“墨跡擦”按鈕
+ ///
+ /// -
+ /// 當=="select"時,會高亮浮動工具欄和白板工具欄中的“選擇”,“套索選”按鈕
+ ///
+ ///
+ ///
+ ///
+ /// 是否自動居中浮動工具欄
+ ///
+ private async void HideSubPanels(string mode = null, bool autoAlignCenter = false) {
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
+
+ if (BorderSettings.Visibility == Visibility.Visible) {
+ BorderSettingsMask.IsHitTestVisible = false;
+ BorderSettingsMask.Background = null;
+ var sb = new Storyboard();
+
+ // 滑动动画
+ var slideAnimation = new DoubleAnimation {
+ From = 0, // 滑动距离
+ To = BorderSettings.RenderTransform.Value.OffsetX - 440,
+ Duration = TimeSpan.FromSeconds(0.6)
+ };
+ slideAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
+ Storyboard.SetTargetProperty(slideAnimation,
+ new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
+
+ sb.Children.Add(slideAnimation);
+
+ sb.Completed += (s, _) => {
+ BorderSettings.Visibility = Visibility.Collapsed;
+ isOpeningOrHidingSettingsPane = false;
+ };
+
+ BorderSettings.Visibility = Visibility.Visible;
+ BorderSettings.RenderTransform = new TranslateTransform();
+
+ isOpeningOrHidingSettingsPane = true;
+ sb.Begin((FrameworkElement)BorderSettings);
+ }
+
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) {
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ }
+
+ if (mode != null) {
+ if (mode != "clear") {
+ CursorIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
+ CursorIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedCursorIcon);
+ PenIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
+ PenIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedPenIcon);
+ StrokeEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
+ StrokeEraserIconGeometry.Geometry =
+ Geometry.Parse(XamlGraphicsIconGeometries.LinedEraserStrokeIcon);
+ CircleEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
+ CircleEraserIconGeometry.Geometry =
+ Geometry.Parse(XamlGraphicsIconGeometries.LinedEraserCircleIcon);
+ LassoSelectIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
+ LassoSelectIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedLassoSelectIcon);
+
+ BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ BoardSelect.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ BoardEraser.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ BoardSelectGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardEraserGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardSelectLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardEraserLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+
+ FloatingbarSelectionBG.Visibility = Visibility.Hidden;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 0);
+ }
+
+ switch (mode) {
+ case "pen":
+ case "color": {
+ PenIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138));
+ PenIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.SolidPenIcon);
+ BoardPen.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardPenGeometry.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardPenLabel.Foreground = new SolidColorBrush(Colors.GhostWhite);
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28);
+ break;
+ }
+ case "eraser": {
+ CircleEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138));
+ CircleEraserIconGeometry.Geometry =
+ Geometry.Parse(XamlGraphicsIconGeometries.SolidEraserCircleIcon);
+ BoardEraser.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardEraserGeometry.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardEraserLabel.Foreground = new SolidColorBrush(Colors.GhostWhite);
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28 * 3);
+ break;
+ }
+ case "eraserByStrokes": {
+ StrokeEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138));
+ StrokeEraserIconGeometry.Geometry =
+ Geometry.Parse(XamlGraphicsIconGeometries.SolidEraserStrokeIcon);
+ BoardEraser.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardEraserGeometry.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardEraserLabel.Foreground = new SolidColorBrush(Colors.GhostWhite);
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28 * 4);
+ break;
+ }
+ case "select": {
+ LassoSelectIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138));
+ LassoSelectIconGeometry.Geometry =
+ Geometry.Parse(XamlGraphicsIconGeometries.SolidLassoSelectIcon);
+ BoardSelect.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235));
+ BoardSelectGeometry.Brush = new SolidColorBrush(Colors.GhostWhite);
+ BoardSelectLabel.Foreground = new SolidColorBrush(Colors.GhostWhite);
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28 * 5);
+ break;
+ }
+ }
+
+
+ if (autoAlignCenter) // 控制居中
+ {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
+ await Task.Delay(50);
+ ViewboxFloatingBarMarginAnimation(60);
+ }
+ else if (Topmost == true) //非黑板
+ {
+ await Task.Delay(50);
+ ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ else //黑板
+ {
+ await Task.Delay(50);
+ ViewboxFloatingBarMarginAnimation(60);
+ }
+ }
+ }
+
+ await Task.Delay(150);
+ isHidingSubPanelsWhenInking = false;
+ }
+
+ #endregion
+
+ #region 撤銷重做按鈕
+ private void SymbolIconUndo_MouseUp(object sender, MouseButtonEventArgs e) {
+ //if (lastBorderMouseDownObject != sender) return;
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == SymbolIconUndo && lastBorderMouseDownObject != SymbolIconUndo) return;
+
+ if (!BtnUndo.IsEnabled) return;
+ BtnUndo_Click(BtnUndo, null);
+ HideSubPanels();
+ }
+
+ private void SymbolIconRedo_MouseUp(object sender, MouseButtonEventArgs e) {
+ //if (lastBorderMouseDownObject != sender) return;
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == SymbolIconRedo && lastBorderMouseDownObject != SymbolIconRedo) return;
+
+ if (!BtnRedo.IsEnabled) return;
+ BtnRedo_Click(BtnRedo, null);
+ HideSubPanels();
+ }
+
+ #endregion
+
+ #region 白板按鈕和退出白板模式按鈕
+
+ //private bool Not_Enter_Blackboard_fir_Mouse_Click = true;
+ private bool isDisplayingOrHidingBlackboard = false;
+
+ private void ImageBlackboard_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == WhiteboardFloatingBarBtn && lastBorderMouseDownObject != WhiteboardFloatingBarBtn) return;
+
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ if (isDisplayingOrHidingBlackboard) return;
+ isDisplayingOrHidingBlackboard = true;
+
+ UnFoldFloatingBar_MouseUp(null, null);
+
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.Select) PenIcon_Click(null, null);
+
+ if (currentMode == 0)
+ {
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ //进入黑板
+
+ /*
+ if (Not_Enter_Blackboard_fir_Mouse_Click) {// BUG-Fixed_tmp:程序启动后直接进入白板会导致后续撤销功能、退出白板无法恢复墨迹
+ BtnColorRed_Click(BorderPenColorRed, null);
+ await Task.Delay(200);
+ SimulateMouseClick.SimulateMouseClickAtTopLeft();
+ await Task.Delay(10);
+ Not_Enter_Blackboard_fir_Mouse_Click = false;
+ }
+ */
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(100);
+ Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); });
+ })).Start();
+
+ HideSubPanels();
+ if (GridTransparencyFakeBackground.Background == Brushes.Transparent)
+ {
+ if (currentMode == 1)
+ {
+ currentMode = 0;
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+ }
+
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+ }
+
+ if (Settings.Gesture.AutoSwitchTwoFingerGesture) // 自动关闭多指书写、开启双指移动
+ {
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = true;
+ if (isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = false;
+ }
+
+ if (Settings.Appearance.EnableTimeDisplayInWhiteboardMode == true)
+ {
+ WaterMarkTime.Visibility = Visibility.Visible;
+ WaterMarkDate.Visibility = Visibility.Visible;
+ } else {
+ WaterMarkTime.Visibility = Visibility.Collapsed;
+ WaterMarkDate.Visibility = Visibility.Collapsed;
+ }
+
+ if (Settings.Appearance.EnableChickenSoupInWhiteboardMode == true)
+ {
+ BlackBoardWaterMark.Visibility = Visibility.Visible;
+ } else {
+ BlackBoardWaterMark.Visibility = Visibility.Collapsed;
+ }
+
+ if (Settings.Appearance.ChickenSoupSource == 0) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.OSUPlayerYuLu.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.OSUPlayerYuLu[randChickenSoupIndex];
+ } else if (Settings.Appearance.ChickenSoupSource == 1) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.MingYanJingJu.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.MingYanJingJu[randChickenSoupIndex];
+ } else if (Settings.Appearance.ChickenSoupSource == 2) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.GaoKaoPhrases.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.GaoKaoPhrases[randChickenSoupIndex];
+ }
+
+ if (Settings.Canvas.UsingWhiteboard)
+ {
+ ICCWaterMarkDark.Visibility = Visibility.Visible;
+ ICCWaterMarkWhite.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ ICCWaterMarkWhite.Visibility = Visibility.Visible;
+ ICCWaterMarkDark.Visibility = Visibility.Collapsed;
+ }
+ }
+ else
+ {
+ //关闭黑板
+ HideSubPanelsImmediately();
+
+ if (StackPanelPPTControls.Visibility == Visibility.Visible)
+ {
+ var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ var dopsc = dops.ToCharArray();
+ if (dopsc[0] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftBottomPanelForPPTNavigation);
+ if (dopsc[1] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightBottomPanelForPPTNavigation);
+ if (dopsc[2] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(LeftSidePanelForPPTNavigation);
+ if (dopsc[3] == '2' && isDisplayingOrHidingBlackboard == false) AnimationsHelper.ShowWithFadeIn(RightSidePanelForPPTNavigation);
+ }
+
+ if (Settings.Automation.IsAutoSaveStrokesAtClear &&
+ inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true);
+
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Collapsed)
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(300);
+ Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(100, true); });
+ })).Start();
+ else
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(300);
+ Application.Current.Dispatcher.Invoke(() => { ViewboxFloatingBarMarginAnimation(60); });
+ })).Start();
+
+ if (System.Windows.Controls.Canvas.GetLeft(FloatingbarSelectionBG)!=28) PenIcon_Click(null, null);
+
+ if (Settings.Gesture.AutoSwitchTwoFingerGesture) // 自动启用多指书写
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = false;
+ // 2024.5.2 need to be tested
+ // if (!isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ WaterMarkTime.Visibility = Visibility.Collapsed;
+ WaterMarkDate.Visibility = Visibility.Collapsed;
+ BlackBoardWaterMark.Visibility = Visibility.Collapsed;
+ ICCWaterMarkDark.Visibility = Visibility.Collapsed;
+ ICCWaterMarkWhite.Visibility = Visibility.Collapsed;
+ }
+
+ BtnSwitch_Click(BtnSwitch, null);
+
+ if (currentMode == 0 && inkCanvas.Strokes.Count == 0 && BtnPPTSlideShowEnd.Visibility != Visibility.Visible)
+ CursorIcon_Click(null, null);
+
+ BtnExit.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(200);
+ Application.Current.Dispatcher.Invoke(() => { isDisplayingOrHidingBlackboard = false; });
+ })).Start();
+
+ SwitchToDefaultPen(null, null);
+ CheckColorTheme(true);
+ }
+
+ #endregion
+ private async void SymbolIconCursor_Click(object sender, RoutedEventArgs e) {
+ if (currentMode != 0) {
+ ImageBlackboard_MouseUp(null, null);
+ }
+ else {
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
+ await Task.Delay(100);
+ ViewboxFloatingBarMarginAnimation(60);
+ }
+ }
+ }
+
+ #region 清空畫布按鈕
+
+ private void SymbolIconDelete_MouseUp(object sender, MouseButtonEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == SymbolIconDelete && lastBorderMouseDownObject != SymbolIconDelete) return;
+
+ if (inkCanvas.GetSelectedStrokes().Count > 0) {
+ inkCanvas.Strokes.Remove(inkCanvas.GetSelectedStrokes());
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ }
+ else if (inkCanvas.Strokes.Count > 0) {
+ if (Settings.Automation.IsAutoSaveStrokesAtClear &&
+ inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ SaveScreenShot(true, $"{pptName}/{previousSlideID}_{DateTime.Now:HH-mm-ss}");
+ else
+ SaveScreenShot(true);
+ }
+
+ BtnClear_Click(null, null);
+ }
+ }
+
+ #endregion
+
+ #region 主要的工具按鈕事件
+
+ ///
+ /// 浮動工具欄的“套索選”按鈕事件,重定向到舊UI的BtnSelect_Click方法
+ ///
+ /// sender
+ /// MouseButtonEventArgs
+ private void SymbolIconSelect_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == SymbolIconSelect && lastBorderMouseDownObject != SymbolIconSelect) return;
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 140);
+ BtnSelect_Click(null, null);
+ HideSubPanels("select");
+ }
+
+ #endregion
+
+ private void FloatingBarToolBtnMouseDownFeedback_Panel(object sender, MouseButtonEventArgs e) {
+ var s = (Panel)sender;
+ lastBorderMouseDownObject = sender;
+ if (s == SymbolIconDelete) s.Background = new SolidColorBrush(Color.FromArgb(28, 127, 29, 29));
+ else s.Background = new SolidColorBrush(Color.FromArgb(28, 24, 24, 27));
+ }
+
+ private void FloatingBarToolBtnMouseLeaveFeedback_Panel(object sender, MouseEventArgs e) {
+ var s = (Panel)sender;
+ lastBorderMouseDownObject = null;
+ s.Background = new SolidColorBrush(Colors.Transparent);
+ }
+
+ private void SymbolIconSettings_Click(object sender, RoutedEventArgs e) {
+ if (isOpeningOrHidingSettingsPane != false) return;
+ HideSubPanels();
+ BtnSettings_Click(null, null);
+ }
+
+ private async void SymbolIconScreenshot_MouseUp(object sender, MouseButtonEventArgs e) {
+ HideSubPanelsImmediately();
+ await Task.Delay(50);
+ SaveScreenShotToDesktop();
+ }
+
+
+
+ private void ImageCountdownTimer_MouseUp(object sender, MouseButtonEventArgs e) {
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ new CountdownTimerWindow().Show();
+ }
+
+ private void OperatingGuideWindowIcon_MouseUp(object sender, MouseButtonEventArgs e) {
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ new OperatingGuideWindow().Show();
+ }
+
+ private void SymbolIconRand_MouseUp(object sender, MouseButtonEventArgs e) {
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ if (lastBorderMouseDownObject != sender) return;
+
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ new RandWindow(Settings).Show();
+ }
+
+ public void CheckEraserTypeTab() {
+ if (Settings.Canvas.EraserShapeType == 0) {
+ CircleEraserTabButton.Background = new SolidColorBrush(Color.FromArgb(85, 59, 130, 246));
+ CircleEraserTabButton.Opacity = 1;
+ CircleEraserTabButtonText.FontWeight = FontWeights.Bold;
+ CircleEraserTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ CircleEraserTabButtonText.FontSize = 9.5;
+ CircleEraserTabButtonIndicator.Visibility = Visibility.Visible;
+ RectangleEraserTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ RectangleEraserTabButton.Opacity = 0.75;
+ RectangleEraserTabButtonText.FontWeight = FontWeights.Normal;
+ RectangleEraserTabButtonText.FontSize = 9;
+ RectangleEraserTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ RectangleEraserTabButtonIndicator.Visibility = Visibility.Collapsed;
+
+ BoardCircleEraserTabButton.Background = new SolidColorBrush(Color.FromArgb(85, 59, 130, 246));
+ BoardCircleEraserTabButton.Opacity = 1;
+ BoardCircleEraserTabButtonText.FontWeight = FontWeights.Bold;
+ BoardCircleEraserTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ BoardCircleEraserTabButtonText.FontSize = 9.5;
+ BoardCircleEraserTabButtonIndicator.Visibility = Visibility.Visible;
+ BoardRectangleEraserTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ BoardRectangleEraserTabButton.Opacity = 0.75;
+ BoardRectangleEraserTabButtonText.FontWeight = FontWeights.Normal;
+ BoardRectangleEraserTabButtonText.FontSize = 9;
+ BoardRectangleEraserTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ BoardRectangleEraserTabButtonIndicator.Visibility = Visibility.Collapsed;
+ }
+ else {
+ RectangleEraserTabButton.Background = new SolidColorBrush(Color.FromArgb(85, 59, 130, 246));
+ RectangleEraserTabButton.Opacity = 1;
+ RectangleEraserTabButtonText.FontWeight = FontWeights.Bold;
+ RectangleEraserTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ RectangleEraserTabButtonText.FontSize = 9.5;
+ RectangleEraserTabButtonIndicator.Visibility = Visibility.Visible;
+ CircleEraserTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ CircleEraserTabButton.Opacity = 0.75;
+ CircleEraserTabButtonText.FontWeight = FontWeights.Normal;
+ CircleEraserTabButtonText.FontSize = 9;
+ CircleEraserTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ CircleEraserTabButtonIndicator.Visibility = Visibility.Collapsed;
+
+ BoardRectangleEraserTabButton.Background = new SolidColorBrush(Color.FromArgb(85, 59, 130, 246));
+ BoardRectangleEraserTabButton.Opacity = 1;
+ BoardRectangleEraserTabButtonText.FontWeight = FontWeights.Bold;
+ BoardRectangleEraserTabButtonText.Margin = new Thickness(2, 0.5, 0, 0);
+ BoardRectangleEraserTabButtonText.FontSize = 9.5;
+ BoardRectangleEraserTabButtonIndicator.Visibility = Visibility.Visible;
+ BoardCircleEraserTabButton.Background = new SolidColorBrush(Colors.Transparent);
+ BoardCircleEraserTabButton.Opacity = 0.75;
+ BoardCircleEraserTabButtonText.FontWeight = FontWeights.Normal;
+ BoardCircleEraserTabButtonText.FontSize = 9;
+ BoardCircleEraserTabButtonText.Margin = new Thickness(2, 1, 0, 0);
+ BoardCircleEraserTabButtonIndicator.Visibility = Visibility.Collapsed;
+ }
+ }
+
+ private void SymbolIconRandOne_MouseUp(object sender, MouseButtonEventArgs e) {
+ LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
+ if (lastBorderMouseDownObject != sender) return;
+
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ new RandWindow(Settings,true).ShowDialog();
+ }
+
+ private void GridInkReplayButton_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ CollapseBorderDrawShape();
+
+ InkCanvasForInkReplay.Visibility = Visibility.Visible;
+ InkCanvasGridForInkReplay.Visibility = Visibility.Hidden;
+ InkCanvasGridForInkReplay.IsHitTestVisible = false;
+ FloatingbarUIForInkReplay.Visibility = Visibility.Hidden;
+ FloatingbarUIForInkReplay.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.Visibility = Visibility.Hidden;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+
+ AnimationsHelper.ShowWithFadeIn(BorderInkReplayToolBox);
+ InkReplayPanelStatusText.Text = "正在重播墨迹...";
+ InkReplayPlayPauseBorder.Background = new SolidColorBrush(Colors.Transparent);
+ InkReplayPlayButtonImage.Visibility = Visibility.Collapsed;
+ InkReplayPauseButtonImage.Visibility = Visibility.Visible;
+
+ isStopInkReplay = false;
+ isPauseInkReplay = false;
+ isRestartInkReplay = false;
+ inkReplaySpeed = 1;
+ InkCanvasForInkReplay.Strokes.Clear();
+ var strokes = inkCanvas.Strokes.Clone();
+ if (inkCanvas.GetSelectedStrokes().Count != 0) strokes = inkCanvas.GetSelectedStrokes().Clone();
+ int k = 1, i = 0;
+ new Thread(() => {
+ isRestartInkReplay = true;
+ while (isRestartInkReplay) {
+ isRestartInkReplay = false;
+ Application.Current.Dispatcher.Invoke(() => {
+ InkCanvasForInkReplay.Strokes.Clear();
+ });
+ foreach (var stroke in strokes) {
+
+ if (isRestartInkReplay) break;
+
+ var stylusPoints = new StylusPointCollection();
+ if (stroke.StylusPoints.Count == 629) //圆或椭圆
+ {
+ Stroke s = null;
+ foreach (var stylusPoint in stroke.StylusPoints) {
+
+ if (isRestartInkReplay) break;
+
+ while (isPauseInkReplay) {
+ Thread.Sleep(10);
+ }
+
+ if (i++ >= 50) {
+ i = 0;
+ Thread.Sleep((int)(10 / inkReplaySpeed));
+ if (isStopInkReplay) return;
+ }
+
+ Application.Current.Dispatcher.Invoke(() => {
+ try {
+ InkCanvasForInkReplay.Strokes.Remove(s);
+ }
+ catch { }
+
+ stylusPoints.Add(stylusPoint);
+ s = new Stroke(stylusPoints.Clone());
+ s.DrawingAttributes = stroke.DrawingAttributes;
+ InkCanvasForInkReplay.Strokes.Add(s);
+ });
+ }
+ } else {
+ Stroke s = null;
+ foreach (var stylusPoint in stroke.StylusPoints) {
+
+ if (isRestartInkReplay) break;
+
+ while (isPauseInkReplay) {
+ Thread.Sleep(10);
+ }
+
+ if (i++ >= k) {
+ i = 0;
+ Thread.Sleep((int)(10 / inkReplaySpeed));
+ if (isStopInkReplay) return;
+ }
+
+ Application.Current.Dispatcher.Invoke(() => {
+ try {
+ InkCanvasForInkReplay.Strokes.Remove(s);
+ }
+ catch { }
+
+ stylusPoints.Add(stylusPoint);
+ s = new Stroke(stylusPoints.Clone());
+ s.DrawingAttributes = stroke.DrawingAttributes;
+ InkCanvasForInkReplay.Strokes.Add(s);
+ });
+ }
+ }
+ }
+ }
+
+ Thread.Sleep(100);
+ Application.Current.Dispatcher.Invoke(() => {
+ InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
+ InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
+ InkCanvasGridForInkReplay.IsHitTestVisible = true;
+ AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
+ FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
+ FloatingbarUIForInkReplay.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+ });
+ }).Start();
+ }
+
+ private bool isStopInkReplay = false;
+ private bool isPauseInkReplay = false;
+ private bool isRestartInkReplay = false;
+ private double inkReplaySpeed = 1;
+
+ private void InkCanvasForInkReplay_MouseDown(object sender, MouseButtonEventArgs e) {
+ if (e.ClickCount == 2) {
+ InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
+ InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
+ InkCanvasGridForInkReplay.IsHitTestVisible = true;
+ FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
+ FloatingbarUIForInkReplay.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+ AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
+ isStopInkReplay = true;
+ }
+ }
+
+ private void InkReplayPlayPauseBorder_OnMouseDown(object sender, MouseButtonEventArgs e) {
+ InkReplayPlayPauseBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
+ }
+
+ private void InkReplayPlayPauseBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ InkReplayPlayPauseBorder.Background = new SolidColorBrush(Colors.Transparent);
+ isPauseInkReplay = !isPauseInkReplay;
+ InkReplayPanelStatusText.Text = isPauseInkReplay?"已暂停!":"正在重播墨迹...";
+ InkReplayPlayButtonImage.Visibility = isPauseInkReplay ? Visibility.Visible: Visibility.Collapsed;
+ InkReplayPauseButtonImage.Visibility = !isPauseInkReplay ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ private void InkReplayStopButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ InkReplayStopButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
+ }
+
+ private void InkReplayStopButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ InkReplayStopButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
+ InkCanvasForInkReplay.Visibility = Visibility.Collapsed;
+ InkCanvasGridForInkReplay.Visibility = Visibility.Visible;
+ InkCanvasGridForInkReplay.IsHitTestVisible = true;
+ FloatingbarUIForInkReplay.Visibility = Visibility.Visible;
+ FloatingbarUIForInkReplay.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.Visibility = Visibility.Visible;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+ AnimationsHelper.HideWithFadeOut(BorderInkReplayToolBox);
+ isStopInkReplay = true;
+ }
+
+ private void InkReplayReplayButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ InkReplayReplayButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
+ }
+
+ private void InkReplayReplayButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ InkReplayReplayButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
+ isRestartInkReplay = true;
+ isPauseInkReplay = false;
+ InkReplayPanelStatusText.Text = "正在重播墨迹...";
+ InkReplayPlayButtonImage.Visibility = Visibility.Collapsed;
+ InkReplayPauseButtonImage.Visibility = Visibility.Visible;
+ }
+
+ private void InkReplaySpeedButtonBorder_OnMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ InkReplaySpeedButtonBorder.Background = new SolidColorBrush(Color.FromArgb(34, 9, 9, 11));
+ }
+
+ private void InkReplaySpeedButtonBorder_OnMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ InkReplaySpeedButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
+ inkReplaySpeed = inkReplaySpeed == 0.5 ? 1 :
+ inkReplaySpeed == 1 ? 2 :
+ inkReplaySpeed == 2 ? 4 :
+ inkReplaySpeed == 4 ? 8 : 0.5;
+ InkReplaySpeedTextBlock.Text = inkReplaySpeed + "x";
+ }
+
+ private void SymbolIconTools_MouseUp(object sender, MouseButtonEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == ToolsFloatingBarBtn && lastBorderMouseDownObject != ToolsFloatingBarBtn) return;
+
+ if (BorderTools.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ }
+ else {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BorderTools);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderTools);
+ }
+ }
+
+ private bool isViewboxFloatingBarMarginAnimationRunning = false;
+
+ public async void ViewboxFloatingBarMarginAnimation(int MarginFromEdge,
+ bool PosXCaculatedWithTaskbarHeight = false) {
+ if (MarginFromEdge == 60) MarginFromEdge = 55;
+ await Dispatcher.InvokeAsync(() => {
+ if (Topmost == false)
+ MarginFromEdge = -60;
+ else
+ ViewboxFloatingBar.Visibility = Visibility.Visible;
+ isViewboxFloatingBarMarginAnimationRunning = true;
+
+ double dpiScaleX = 1, dpiScaleY = 1;
+ var source = PresentationSource.FromVisual(this);
+ if (source != null) {
+ dpiScaleX = source.CompositionTarget.TransformToDevice.M11;
+ dpiScaleY = source.CompositionTarget.TransformToDevice.M22;
+ }
+
+ var windowHandle = new WindowInteropHelper(this).Handle;
+ var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
+ double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
+ var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
+ SystemParameters.WindowCaptionHeight;
+ pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
+
+ if (PosXCaculatedWithTaskbarHeight == false)
+ pos.Y = screenHeight - MarginFromEdge * ViewboxFloatingBarScaleTransform.ScaleY;
+ else if (PosXCaculatedWithTaskbarHeight == true)
+ pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
+ toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
+
+ if (MarginFromEdge != -60) {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
+ if (pointPPT.X != -1 || pointPPT.Y != -1) {
+ if (Math.Abs(pointPPT.Y - pos.Y) > 50)
+ pos = pointPPT;
+ else
+ pointPPT = pos;
+ }
+ }
+ else {
+ if (pointDesktop.X != -1 || pointDesktop.Y != -1) {
+ if (Math.Abs(pointDesktop.Y - pos.Y) > 50)
+ pos = pointDesktop;
+ else
+ pointDesktop = pos;
+ }
+ }
+ }
+
+ var marginAnimation = new ThicknessAnimation {
+ Duration = TimeSpan.FromSeconds(0.35),
+ From = ViewboxFloatingBar.Margin,
+ To = new Thickness(pos.X, pos.Y, 0, -20)
+ };
+ marginAnimation.EasingFunction = new CircleEase();
+ ViewboxFloatingBar.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Task.Delay(200);
+
+ await Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBar.Margin = new Thickness(pos.X, pos.Y, -2000, -200);
+ if (Topmost == false) ViewboxFloatingBar.Visibility = Visibility.Hidden;
+ });
+ }
+
+ public async void PureViewboxFloatingBarMarginAnimationInDesktopMode()
+ {
+ await Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBar.Visibility = Visibility.Visible;
+ isViewboxFloatingBarMarginAnimationRunning = true;
+
+ double dpiScaleX = 1, dpiScaleY = 1;
+ var source = PresentationSource.FromVisual(this);
+ if (source != null)
+ {
+ dpiScaleX = source.CompositionTarget.TransformToDevice.M11;
+ dpiScaleY = source.CompositionTarget.TransformToDevice.M22;
+ }
+
+ var windowHandle = new WindowInteropHelper(this).Handle;
+ var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
+ double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
+ var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
+ SystemParameters.WindowCaptionHeight;
+ pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
+
+ pos.Y = screenHeight - ViewboxFloatingBar.ActualHeight * ViewboxFloatingBarScaleTransform.ScaleY -
+ toolbarHeight - ViewboxFloatingBarScaleTransform.ScaleY * 3;
+
+ if (pointDesktop.X != -1 || pointDesktop.Y != -1) pointDesktop = pos;
+
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.35),
+ From = ViewboxFloatingBar.Margin,
+ To = new Thickness(pos.X, pos.Y, 0, -20)
+ };
+ marginAnimation.EasingFunction = new CircleEase();
+ ViewboxFloatingBar.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Task.Delay(349);
+
+ await Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBar.Margin = new Thickness(pos.X, pos.Y, -2000, -200);
+ });
+ }
+
+ public async void PureViewboxFloatingBarMarginAnimationInPPTMode()
+ {
+ await Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBar.Visibility = Visibility.Visible;
+ isViewboxFloatingBarMarginAnimationRunning = true;
+
+ double dpiScaleX = 1, dpiScaleY = 1;
+ var source = PresentationSource.FromVisual(this);
+ if (source != null)
+ {
+ dpiScaleX = source.CompositionTarget.TransformToDevice.M11;
+ dpiScaleY = source.CompositionTarget.TransformToDevice.M22;
+ }
+
+ var windowHandle = new WindowInteropHelper(this).Handle;
+ var screen = System.Windows.Forms.Screen.FromHandle(windowHandle);
+ double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY;
+ var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight -
+ SystemParameters.WindowCaptionHeight;
+ pos.X = (screenWidth - ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX) / 2;
+
+ pos.Y = screenHeight - 55 * ViewboxFloatingBarScaleTransform.ScaleY;
+
+ if (pointPPT.X != -1 || pointPPT.Y != -1)
+ {
+ pointPPT = pos;
+ }
+
+ var marginAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(0.35),
+ From = ViewboxFloatingBar.Margin,
+ To = new Thickness(pos.X, pos.Y, 0, -20)
+ };
+ marginAnimation.EasingFunction = new CircleEase();
+ ViewboxFloatingBar.BeginAnimation(MarginProperty, marginAnimation);
+ });
+
+ await Task.Delay(349);
+
+ await Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBar.Margin = new Thickness(pos.X, pos.Y, -2000, -200);
+ });
+ }
+
+ private async void CursorIcon_Click(object sender, RoutedEventArgs e) {
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender==Cursor_Icon && lastBorderMouseDownObject != Cursor_Icon) return;
+ // 隱藏高亮
+ FloatingbarSelectionBG.Visibility = Visibility.Hidden;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 0);
+
+ // 切换前自动截图保存墨迹
+ if (inkCanvas.Strokes.Count > 0 &&
+ inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ SaveScreenShot(true, $"{pptName}/{previousSlideID}_{DateTime.Now:HH-mm-ss}");
+ else SaveScreenShot(true);
+ }
+
+ if (BtnPPTSlideShowEnd.Visibility != Visibility.Visible) {
+ if (Settings.Canvas.HideStrokeWhenSelecting) {
+ inkCanvas.Visibility = Visibility.Collapsed;
+ }
+ else {
+ inkCanvas.IsHitTestVisible = false;
+ inkCanvas.Visibility = Visibility.Visible;
+ }
+ }
+ else {
+ if (Settings.PowerPointSettings.IsShowStrokeOnSelectInPowerPoint) {
+ inkCanvas.Visibility = Visibility.Visible;
+ inkCanvas.IsHitTestVisible = true;
+ }
+ else {
+ if (Settings.Canvas.HideStrokeWhenSelecting) {
+ inkCanvas.Visibility = Visibility.Collapsed;
+ }
+ else {
+ inkCanvas.IsHitTestVisible = false;
+ inkCanvas.Visibility = Visibility.Visible;
+ }
+ }
+ }
+
+ GridTransparencyFakeBackground.Opacity = 0;
+ GridTransparencyFakeBackground.Background = Brushes.Transparent;
+
+ GridBackgroundCoverHolder.Visibility = Visibility.Collapsed;
+ inkCanvas.Select(new StrokeCollection());
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+
+ if (currentMode != 0) {
+ SaveStrokes();
+ RestoreStrokes(true);
+ }
+
+ if (BtnSwitchTheme.Content.ToString() == "浅色")
+ BtnSwitch.Content = "黑板";
+ else
+ BtnSwitch.Content = "白板";
+
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ BtnHideInkCanvas.Content = "显示\n画板";
+ CheckEnableTwoFingerGestureBtnVisibility(false);
+
+
+ StackPanelCanvasControls.Visibility = Visibility.Collapsed;
+
+ if (!isFloatingBarFolded) {
+ HideSubPanels("cursor", true);
+ await Task.Delay(50);
+
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ ViewboxFloatingBarMarginAnimation(60);
+ else
+ ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ }
+
+ private void PenIcon_Click(object sender, RoutedEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == Pen_Icon && lastBorderMouseDownObject != Pen_Icon) return;
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 28);
+
+ if (Pen_Icon.Background == null || StackPanelCanvasControls.Visibility == Visibility.Collapsed) {
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+
+ GridTransparencyFakeBackground.Opacity = 1;
+ GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
+
+ inkCanvas.IsHitTestVisible = true;
+ inkCanvas.Visibility = Visibility.Visible;
+
+ GridBackgroundCoverHolder.Visibility = Visibility.Visible;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+
+ /*if (forceEraser && currentMode == 0)
+ BtnColorRed_Click(sender, null);*/
+
+ if (GridBackgroundCover.Visibility == Visibility.Collapsed) {
+ if (BtnSwitchTheme.Content.ToString() == "浅色")
+ BtnSwitch.Content = "黑板";
+ else
+ BtnSwitch.Content = "白板";
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ }
+ else {
+ BtnSwitch.Content = "屏幕";
+ StackPanelPPTButtons.Visibility = Visibility.Collapsed;
+ }
+
+ BtnHideInkCanvas.Content = "隐藏\n画板";
+
+ StackPanelCanvasControls.Visibility = Visibility.Visible;
+ //AnimationsHelper.ShowWithSlideFromLeftAndFade(StackPanelCanvasControls);
+ CheckEnableTwoFingerGestureBtnVisibility(true);
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ ColorSwitchCheck();
+ HideSubPanels("pen", true);
+ }
+ else {
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.Ink) {
+ if (PenPalette.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ }
+ else {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(PenPalette);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardPenPalette);
+ }
+ }
+ else {
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ ColorSwitchCheck();
+ HideSubPanels("pen", true);
+ }
+ }
+ }
+
+ private void ColorThemeSwitch_MouseUp(object sender, RoutedEventArgs e) {
+ isUselightThemeColor = !isUselightThemeColor;
+ if (currentMode == 0) isDesktopUselightThemeColor = isUselightThemeColor;
+ CheckColorTheme();
+ }
+
+ private void EraserIcon_Click(object sender, RoutedEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == Eraser_Icon && lastBorderMouseDownObject != Eraser_Icon) return;
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 84);
+
+ forceEraser = true;
+ forcePointEraser = true;
+ if (Settings.Canvas.EraserShapeType == 0) {
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
+ }
+ else if (Settings.Canvas.EraserShapeType == 1) {
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.7;
+ break;
+ case 1:
+ k = 0.9;
+ break;
+ case 3:
+ k = 1.2;
+ break;
+ case 4:
+ k = 1.6;
+ break;
+ }
+
+ inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
+ }
+
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
+ if (EraserSizePanel.Visibility == Visibility.Collapsed) {
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(EraserSizePanel);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardEraserSizePanel);
+ } else {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ }
+ }
+ else {
+ HideSubPanels("eraser");
+ }
+
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ drawingShapeMode = 0;
+
+ inkCanvas_EditingModeChanged(inkCanvas, null);
+ CancelSingleFingerDragMode();
+ }
+
+ private void EraserIconByStrokes_Click(object sender, RoutedEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == EraserByStrokes_Icon && lastBorderMouseDownObject != EraserByStrokes_Icon) return;
+
+ FloatingbarSelectionBG.Visibility = Visibility.Visible;
+ System.Windows.Controls.Canvas.SetLeft(FloatingbarSelectionBG, 112);
+
+ forceEraser = true;
+ forcePointEraser = false;
+
+ inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
+ drawingShapeMode = 0;
+
+ inkCanvas_EditingModeChanged(inkCanvas, null);
+ CancelSingleFingerDragMode();
+
+ HideSubPanels("eraserByStrokes");
+ }
+
+ private void CursorWithDelIcon_Click(object sender, RoutedEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == CursorWithDelFloatingBarBtn && lastBorderMouseDownObject != CursorWithDelFloatingBarBtn) return;
+
+ SymbolIconDelete_MouseUp(sender, null);
+ CursorIcon_Click(null, null);
+ }
+
+ private void SelectIcon_MouseUp(object sender, RoutedEvent e) {
+ forceEraser = true;
+ drawingShapeMode = 0;
+ inkCanvas.IsManipulationEnabled = false;
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.Select) {
+ var selectedStrokes = new StrokeCollection();
+ foreach (var stroke in inkCanvas.Strokes)
+ if (stroke.GetBounds().Width > 0 && stroke.GetBounds().Height > 0)
+ selectedStrokes.Add(stroke);
+ inkCanvas.Select(selectedStrokes);
+ }
+ else {
+ inkCanvas.EditingMode = InkCanvasEditingMode.Select;
+ }
+ }
+
+ private void DrawShapePromptToPen() {
+ if (isLongPressSelected == true) {
+ HideSubPanels("pen");
+ }
+ else {
+ if (StackPanelCanvasControls.Visibility == Visibility.Visible)
+ HideSubPanels("pen");
+ else
+ HideSubPanels("cursor");
+ }
+ }
+
+ private void CloseBordertools_MouseUp(object sender, MouseButtonEventArgs e) {
+ HideSubPanels();
+ }
+
+ #region Left Side Panel
+
+ private void BtnFingerDragMode_Click(object sender, RoutedEventArgs e) {
+ if (isSingleFingerDragMode) {
+ isSingleFingerDragMode = false;
+ BtnFingerDragMode.Content = "单指\n拖动";
+ }
+ else {
+ isSingleFingerDragMode = true;
+ BtnFingerDragMode.Content = "多指\n拖动";
+ }
+ }
+
+ private void BtnUndo_Click(object sender, RoutedEventArgs e) {
+ if (inkCanvas.GetSelectedStrokes().Count != 0) {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ inkCanvas.Select(new StrokeCollection());
+ }
+
+ var item = timeMachine.Undo();
+ ApplyHistoryToCanvas(item);
+ }
+
+ private void BtnRedo_Click(object sender, RoutedEventArgs e) {
+ if (inkCanvas.GetSelectedStrokes().Count != 0) {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ inkCanvas.Select(new StrokeCollection());
+ }
+
+ var item = timeMachine.Redo();
+ ApplyHistoryToCanvas(item);
+ }
+
+ private void Btn_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ try {
+ if (((Button)sender).IsEnabled)
+ ((UIElement)((Button)sender).Content).Opacity = 1;
+ else
+ ((UIElement)((Button)sender).Content).Opacity = 0.25;
+ }
+ catch { }
+ }
+
+ #endregion Left Side Panel
+
+ #region Right Side Panel
+
+ public static bool CloseIsFromButton = false;
+
+ public void BtnExit_Click(object sender, RoutedEventArgs e) {
+ CloseIsFromButton = true;
+ Close();
+ }
+
+ public void BtnRestart_Click(object sender, RoutedEventArgs e) {
+ Process.Start(System.Windows.Forms.Application.ExecutablePath, "-m");
+
+ CloseIsFromButton = true;
+ Application.Current.Shutdown();
+ }
+
+ private void SettingsOverlayClick(object sender, MouseButtonEventArgs e) {
+ if (isOpeningOrHidingSettingsPane == true) return;
+ BtnSettings_Click(null, null);
+ }
+
+ private bool isOpeningOrHidingSettingsPane = false;
+
+ private void BtnSettings_Click(object sender, RoutedEventArgs e) {
+ if (BorderSettings.Visibility == Visibility.Visible) {
+ HideSubPanels();
+ }
+ else {
+ BorderSettingsMask.IsHitTestVisible = true;
+ BorderSettingsMask.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
+ SettingsPanelScrollViewer.ScrollToTop();
+ var sb = new Storyboard();
+
+ // 滑动动画
+ var slideAnimation = new DoubleAnimation {
+ From = BorderSettings.RenderTransform.Value.OffsetX - 440, // 滑动距离
+ To = 0,
+ Duration = TimeSpan.FromSeconds(0.6)
+ };
+ slideAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
+ Storyboard.SetTargetProperty(slideAnimation,
+ new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
+
+ sb.Children.Add(slideAnimation);
+
+ sb.Completed += (s, _) => { isOpeningOrHidingSettingsPane = false; };
+
+ BorderSettings.Visibility = Visibility.Visible;
+ BorderSettings.RenderTransform = new TranslateTransform();
+
+ isOpeningOrHidingSettingsPane = true;
+ sb.Begin((FrameworkElement)BorderSettings);
+ }
+ }
+
+ private void BtnThickness_Click(object sender, RoutedEventArgs e) { }
+
+ private bool forceEraser = false;
+
+
+ private void BtnClear_Click(object sender, RoutedEventArgs e) {
+ forceEraser = false;
+ //BorderClearInDelete.Visibility = Visibility.Collapsed;
+
+ if (currentMode == 0) {
+ // 先回到画笔再清屏,避免 TimeMachine 的相关 bug 影响
+ if (Pen_Icon.Background == null && StackPanelCanvasControls.Visibility == Visibility.Visible)
+ PenIcon_Click(null, null);
+ }
+ else {
+ if (Pen_Icon.Background == null) PenIcon_Click(null, null);
+ }
+
+ if (inkCanvas.Strokes.Count != 0) {
+ var whiteboardIndex = CurrentWhiteboardIndex;
+ if (currentMode == 0) whiteboardIndex = 0;
+ strokeCollections[whiteboardIndex] = inkCanvas.Strokes.Clone();
+ }
+
+ ClearStrokes(false);
+ inkCanvas.Children.Clear();
+
+ CancelSingleFingerDragMode();
+
+ if (Settings.Canvas.ClearCanvasAndClearTimeMachine) timeMachine.ClearStrokeHistory();
+ }
+
+ private bool lastIsInMultiTouchMode = false;
+
+ private void CancelSingleFingerDragMode() {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+
+ if (isSingleFingerDragMode) BtnFingerDragMode_Click(BtnFingerDragMode, null);
+ isLongPressSelected = false;
+ }
+
+ private void BtnHideControl_Click(object sender, RoutedEventArgs e) {
+ if (StackPanelControl.Visibility == Visibility.Visible)
+ StackPanelControl.Visibility = Visibility.Hidden;
+ else
+ StackPanelControl.Visibility = Visibility.Visible;
+ }
+
+ private int currentMode = 0;
+
+ private void BtnSwitch_Click(object sender, RoutedEventArgs e) {
+ if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
+ if (currentMode == 0) {
+ currentMode++;
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+
+ SaveStrokes(true);
+ ClearStrokes(true);
+ RestoreStrokes();
+
+ if (BtnSwitchTheme.Content.ToString() == "浅色") {
+ BtnSwitch.Content = "黑板";
+ BtnExit.Foreground = Brushes.White;
+ }
+ else {
+ BtnSwitch.Content = "白板";
+ if (isPresentationHaveBlackSpace) {
+ BtnExit.Foreground = Brushes.White;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ }
+ else {
+ BtnExit.Foreground = Brushes.Black;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
+ }
+ }
+
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ }
+
+ Topmost = true;
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, e);
+ }
+ else {
+ switch (++currentMode % 2) {
+ case 0: //屏幕模式
+ currentMode = 0;
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+
+ SaveStrokes();
+ ClearStrokes(true);
+ RestoreStrokes(true);
+
+ if (BtnSwitchTheme.Content.ToString() == "浅色") {
+ BtnSwitch.Content = "黑板";
+ BtnExit.Foreground = Brushes.White;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.Black;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ }
+ else {
+ BtnSwitch.Content = "白板";
+ if (isPresentationHaveBlackSpace) {
+ BtnExit.Foreground = Brushes.White;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ }
+ else {
+ BtnExit.Foreground = Brushes.Black;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
+ }
+ }
+
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ Topmost = true;
+ break;
+ case 1: //黑板或白板模式
+ currentMode = 1;
+ GridBackgroundCover.Visibility = Visibility.Visible;
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardLeftSide);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardCenterSide);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BlackboardRightSide);
+
+ SaveStrokes(true);
+ ClearStrokes(true);
+ RestoreStrokes();
+
+ BtnSwitch.Content = "屏幕";
+ if (BtnSwitchTheme.Content.ToString() == "浅色") {
+ BtnExit.Foreground = Brushes.White;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.Black;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ }
+ else {
+ BtnExit.Foreground = Brushes.Black;
+ //SymbolIconBtnColorBlackContent.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
+ }
+
+ if (Settings.Canvas.UsingWhiteboard)
+ {
+ BtnColorBlack_Click(null, null);
+ }
+ else
+ {
+ BtnColorWhite_Click(null, null);
+ }
+
+ StackPanelPPTButtons.Visibility = Visibility.Collapsed;
+ Topmost = false;
+ break;
+ }
+ }
+ }
+
+ private int BoundsWidth = 5;
+
+ private void BtnHideInkCanvas_Click(object sender, RoutedEventArgs e) {
+ if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
+ GridTransparencyFakeBackground.Opacity = 1;
+ GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
+ inkCanvas.IsHitTestVisible = true;
+ inkCanvas.Visibility = Visibility.Visible;
+
+ GridBackgroundCoverHolder.Visibility = Visibility.Visible;
+
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+
+ if (GridBackgroundCover.Visibility == Visibility.Collapsed) {
+ if (BtnSwitchTheme.Content.ToString() == "浅色")
+ BtnSwitch.Content = "黑板";
+ else
+ BtnSwitch.Content = "白板";
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ }
+ else {
+ BtnSwitch.Content = "屏幕";
+ StackPanelPPTButtons.Visibility = Visibility.Collapsed;
+ }
+
+ BtnHideInkCanvas.Content = "隐藏\n画板";
+ }
+ else {
+ // Auto-clear Strokes 要等待截图完成再清理笔记
+ if (BtnPPTSlideShowEnd.Visibility != Visibility.Visible) {
+ if (isLoaded && Settings.Automation.IsAutoClearWhenExitingWritingMode)
+ if (inkCanvas.Strokes.Count > 0) {
+ if (Settings.Automation.IsAutoSaveStrokesAtClear && inkCanvas.Strokes.Count >
+ Settings.Automation.MinimumAutomationStrokeNumber)
+ SaveScreenShot(true);
+
+ //BtnClear_Click(null, null);
+ }
+
+ inkCanvas.IsHitTestVisible = true;
+ inkCanvas.Visibility = Visibility.Visible;
+ }
+ else {
+ if (isLoaded && Settings.Automation.IsAutoClearWhenExitingWritingMode &&
+ !Settings.PowerPointSettings.IsNoClearStrokeOnSelectWhenInPowerPoint)
+ if (inkCanvas.Strokes.Count > 0) {
+ if (Settings.Automation.IsAutoSaveStrokesAtClear && inkCanvas.Strokes.Count >
+ Settings.Automation.MinimumAutomationStrokeNumber)
+ SaveScreenShot(true);
+
+ //BtnClear_Click(null, null);
+ }
+
+
+ if (Settings.PowerPointSettings.IsShowStrokeOnSelectInPowerPoint) {
+ inkCanvas.Visibility = Visibility.Visible;
+ inkCanvas.IsHitTestVisible = true;
+ }
+ else {
+ inkCanvas.IsHitTestVisible = true;
+ inkCanvas.Visibility = Visibility.Visible;
+ }
+ }
+
+ GridTransparencyFakeBackground.Opacity = 0;
+ GridTransparencyFakeBackground.Background = Brushes.Transparent;
+
+ GridBackgroundCoverHolder.Visibility = Visibility.Collapsed;
+
+ if (currentMode != 0) {
+ SaveStrokes();
+ RestoreStrokes(true);
+ }
+
+ if (BtnSwitchTheme.Content.ToString() == "浅色")
+ BtnSwitch.Content = "黑板";
+ else
+ BtnSwitch.Content = "白板";
+
+ StackPanelPPTButtons.Visibility = Visibility.Visible;
+ BtnHideInkCanvas.Content = "显示\n画板";
+ }
+
+ if (GridTransparencyFakeBackground.Background == Brushes.Transparent) {
+ StackPanelCanvasControls.Visibility = Visibility.Collapsed;
+ CheckEnableTwoFingerGestureBtnVisibility(false);
+ HideSubPanels("cursor");
+ }
+ else {
+ AnimationsHelper.ShowWithSlideFromLeftAndFade(StackPanelCanvasControls);
+ CheckEnableTwoFingerGestureBtnVisibility(true);
+ }
+ }
+
+ private void BtnSwitchSide_Click(object sender, RoutedEventArgs e) {
+ if (ViewBoxStackPanelMain.HorizontalAlignment == HorizontalAlignment.Right) {
+ ViewBoxStackPanelMain.HorizontalAlignment = HorizontalAlignment.Left;
+ ViewBoxStackPanelShapes.HorizontalAlignment = HorizontalAlignment.Right;
+ }
+ else {
+ ViewBoxStackPanelMain.HorizontalAlignment = HorizontalAlignment.Right;
+ ViewBoxStackPanelShapes.HorizontalAlignment = HorizontalAlignment.Left;
+ }
+ }
+
+ private void StackPanel_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
+ if (((StackPanel)sender).Visibility == Visibility.Visible)
+ GridForLeftSideReservedSpace.Visibility = Visibility.Collapsed;
+ else
+ GridForLeftSideReservedSpace.Visibility = Visibility.Visible;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs
new file mode 100644
index 00000000..5f7660bb
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs
@@ -0,0 +1,92 @@
+using System.Windows;
+using System.Windows.Input;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private void Window_MouseWheel(object sender, MouseWheelEventArgs e) {
+ if (StackPanelPPTControls.Visibility != Visibility.Visible || currentMode != 0) return;
+ if (e.Delta >= 120)
+ BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
+ else if (e.Delta <= -120) BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
+ }
+
+ private void Main_Grid_PreviewKeyDown(object sender, KeyEventArgs e) {
+ if (StackPanelPPTControls.Visibility != Visibility.Visible || currentMode != 0) return;
+
+ if (e.Key == Key.Down || e.Key == Key.PageDown || e.Key == Key.Right || e.Key == Key.N ||
+ e.Key == Key.Space) BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
+ if (e.Key == Key.Up || e.Key == Key.PageUp || e.Key == Key.Left || e.Key == Key.P)
+ BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
+ }
+
+ private void Window_KeyDown(object sender, KeyEventArgs e) {
+ if (e.Key == Key.Escape) KeyExit(null, null);
+ }
+
+ private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
+ e.CanExecute = true;
+ }
+
+ private void HotKey_Undo(object sender, ExecutedRoutedEventArgs e) {
+ try {
+ SymbolIconUndo_MouseUp(lastBorderMouseDownObject, null);
+ }
+ catch { }
+ }
+
+ private void HotKey_Redo(object sender, ExecutedRoutedEventArgs e) {
+ try {
+ SymbolIconRedo_MouseUp(lastBorderMouseDownObject, null);
+ }
+ catch { }
+ }
+
+ private void HotKey_Clear(object sender, ExecutedRoutedEventArgs e) {
+ SymbolIconDelete_MouseUp(lastBorderMouseDownObject, null);
+ }
+
+
+ private void KeyExit(object sender, ExecutedRoutedEventArgs e) {
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null);
+ }
+
+ private void KeyChangeToDrawTool(object sender, ExecutedRoutedEventArgs e) {
+ PenIcon_Click(lastBorderMouseDownObject, null);
+ }
+
+ private void KeyChangeToQuitDrawTool(object sender, ExecutedRoutedEventArgs e) {
+ if (currentMode != 0) ImageBlackboard_MouseUp(lastBorderMouseDownObject, null);
+ CursorIcon_Click(lastBorderMouseDownObject, null);
+ }
+
+ private void KeyChangeToSelect(object sender, ExecutedRoutedEventArgs e) {
+ if (StackPanelCanvasControls.Visibility == Visibility.Visible)
+ SymbolIconSelect_MouseUp(lastBorderMouseDownObject, null);
+ }
+
+ private void KeyChangeToEraser(object sender, ExecutedRoutedEventArgs e) {
+ if (StackPanelCanvasControls.Visibility == Visibility.Visible) {
+ if (Eraser_Icon.Background != null)
+ EraserIconByStrokes_Click(lastBorderMouseDownObject, null);
+ else
+ EraserIcon_Click(lastBorderMouseDownObject, null);
+ }
+ }
+
+ private void KeyChangeToBoard(object sender, ExecutedRoutedEventArgs e) {
+ ImageBlackboard_MouseUp(lastBorderMouseDownObject, null);
+ }
+
+ private void KeyCapture(object sender, ExecutedRoutedEventArgs e) {
+ SaveScreenShotToDesktop();
+ }
+
+ private void KeyDrawLine(object sender, ExecutedRoutedEventArgs e) {
+ if (StackPanelCanvasControls.Visibility == Visibility.Visible) BtnDrawLine_Click(lastMouseDownSender, null);
+ }
+
+ private void KeyHide(object sender, ExecutedRoutedEventArgs e) {
+ SymbolIconEmoji_MouseUp(null, null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Icons.cs b/Ink Canvas/MainWindow_cs/MW_Icons.cs
new file mode 100644
index 00000000..500d74bd
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Icons.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Ink_Canvas {
+ public static class XamlGraphicsIconGeometries {
+ public static string LinedCursorIcon =
+ "F1 M24,24z M0,0z M5.72106,15.9716L3.71327,3.00395C3.6389,2.6693 3.65747,2.41831 3.76902,2.25099 3.88057,2.08366 4.0479,2 4.271,2 4.4941,2 4.71711,2.07437 4.94021,2.2231 6.72502,3.39438 9.28149,5.10481 12.6094,7.3544 15.677,9.45526 18.1125,11.1285 19.9159,12.3742 20.1204,12.5229 20.2505,12.6995 20.3062,12.904 20.362,13.1085 20.3249,13.2944 20.1947,13.4618 20.0832,13.6105 19.8973,13.6849 19.637,13.6849L13.3902,13.6849 17.6291,19.7365C17.722,19.8666 17.75,20.0153 17.7128,20.1827 17.6942,20.3314 17.6198,20.4522 17.4897,20.5452L15.5654,21.8838C15.4353,21.9768 15.2865,22.0139 15.1192,21.9953 14.9704,21.9582 14.8496,21.8745 14.7566,21.7444L10.2389,15.2745 7.58956,19.9038C7.45942,20.1269 7.30144,20.2756 7.11552,20.35 6.92961,20.4058 6.75292,20.3872 6.5856,20.2942 6.43686,20.2013 6.34392,20.0339 6.30673,19.7922L6.00007,17.8959C5.88852,17.0779,5.79543,16.4364,5.72106,15.9716z";
+
+ public static string LinedPenIcon =
+ "F1 M24,24z M0,0z M16.996,2.34419L21.6823,7.00397C21.8941,7.23343 22,7.49819 22,7.79825 22,8.09831 21.8941,8.35425 21.6823,8.56606L10.8271,19.4212 4.57877,13.1994 15.4339,2.34419C15.6457,2.11473 15.9017,2 16.2018,2 16.5195,2 16.7842,2.11473 16.996,2.34419z M9.63571,20.5862L9.50333,20.6391 2.6725,21.9894C2.47834,22.0247 2.31066,21.9718 2.16946,21.8306 2.02825,21.707 1.97529,21.5481 2.01059,21.354L3.38736,14.5232C3.38736,14.4879,3.40502,14.4349,3.44032,14.3643L9.63571,20.5862z";
+
+ public static string SolidPenIcon =
+ "F1 M24,24z M0,0z M16.996,2.34419L21.6823,7.00397C21.8941,7.23343 22,7.49819 22,7.79825 22,8.09831 21.8941,8.35425 21.6823,8.56606L10.8271,19.4212 4.57877,13.1994 15.4339,2.34419C15.6457,2.11473 15.9017,2 16.2018,2 16.5195,2 16.7842,2.11473 16.996,2.34419z M9.63571,20.5862L9.50333,20.6391 2.6725,21.9894C2.47834,22.0247 2.31066,21.9718 2.16946,21.8306 2.02825,21.707 1.97529,21.5481 2.01059,21.354L3.38736,14.5232C3.38736,14.4879,3.40502,14.4349,3.44032,14.3643L9.63571,20.5862z";
+
+ public static string LinedEraserStrokeIcon =
+ "F1 M24,24z M0,0z M19.0625,7.99501C19.2863,7.99501 19.4861,8.06695 19.662,8.21083 19.8538,8.35471 19.9897,8.53856 20.0696,8.76237 20.4054,9.94539 20.7011,11.2563 20.9569,12.6951 21.1967,14.0859 21.3646,15.4368 21.4605,16.7477L21.4845,17.2993C21.5005,17.5551 21.5084,17.9068 21.5084,18.3544 21.5084,19.2017 21.2926,19.8412 20.861,20.2728 20.4453,20.7044 19.7099,21.0482 18.6548,21.3039 18.3191,21.3679 17.7836,20.4327 17.0482,18.4983 16.5845,20.8643 16.1129,22.0313 15.6333,21.9994 13.9227,21.9674 12.468,21.8954 11.269,21.7835L10.8134,21.7356C9.83817,21.6077 8.86297,21.4398 7.88778,21.232 7.1524,21.0721 6.32109,20.8563 5.39386,20.5845 4.61051,20.3447 3.97904,20.089 3.49944,19.8172 3.01984,19.5454 2.70809,19.2337 2.56421,18.882 2.40434,18.4823 2.50827,18.0746 2.87596,17.659L3.09176,17.3952 3.18769,17.2273 3.23565,17.1074 3.37954,16.8197 3.47544,16.5559 3.6433,15.9324 3.73923,15.6207 3.85912,15.1411 4.17088,13.5824 4.57853,11.1844 4.98621,9.05013C5.03417,8.79435 5.16203,8.55455 5.36986,8.33073 5.59367,8.10692 5.8255,7.99501 6.0653,7.99501L19.0625,7.99501z M14.4823,2C14.7861,2 15.0418,2.08793 15.2496,2.26378 15.4575,2.43963 15.5614,2.64746 15.5614,2.88726L15.5614,4.99751 19.0625,4.99751C19.3343,4.99751 19.5661,5.10142 19.7579,5.30925 19.9498,5.50109 20.0457,5.73289 20.0457,6.00467 20.0457,6.27644 19.9498,6.51624 19.7579,6.72407 19.5661,6.91591 19.3343,7.01183 19.0625,7.01183L6.0653,7.01183C5.79352,7.01183 5.55372,6.91591 5.34589,6.72407 5.15405,6.51624 5.05814,6.27644 5.05814,6.00467 5.05814,5.73289 5.15405,5.50109 5.34589,5.30925 5.55372,5.10142 5.79352,4.99751 6.0653,4.99751L9.56638,4.99751 9.56638,2.88726C9.56638,2.66345 9.65432,2.47161 9.83017,2.31174 10.022,2.15187 10.2538,2.05595 10.5256,2.02398L10.6455,2 14.4823,2z";
+
+ public static string SolidEraserStrokeIcon =
+ "F1 M24,24z M0,0z M19.0625,7.99501C19.2863,7.99501 19.4861,8.06695 19.662,8.21083 19.8538,8.35471 19.9897,8.53856 20.0696,8.76237 20.4054,9.94539 20.7011,11.2563 20.9569,12.6951 21.1967,14.0859 21.3646,15.4368 21.4605,16.7477L21.4845,17.2993C21.5005,17.5551 21.5084,17.9068 21.5084,18.3544 21.5084,19.2017 21.2926,19.8412 20.861,20.2728 20.4453,20.7044 19.7099,21.0482 18.6548,21.3039 18.3191,21.3679 17.7836,20.4327 17.0482,18.4983 16.5845,20.8643 16.1129,22.0313 15.6333,21.9994 13.9227,21.9674 12.468,21.8954 11.269,21.7835L10.8134,21.7356C9.83817,21.6077 8.86297,21.4398 7.88778,21.232 7.1524,21.0721 6.32109,20.8563 5.39386,20.5845 4.61051,20.3447 3.97904,20.089 3.49944,19.8172 3.01984,19.5454 2.70809,19.2337 2.56421,18.882 2.40434,18.4823 2.50827,18.0746 2.87596,17.659L3.09176,17.3952 3.18769,17.2273 3.23565,17.1074 3.37954,16.8197 3.47544,16.5559 3.6433,15.9324 3.73923,15.6207 3.85912,15.1411 4.17088,13.5824 4.57853,11.1844 4.98621,9.05013C5.03417,8.79435 5.16203,8.55455 5.36986,8.33073 5.59367,8.10692 5.8255,7.99501 6.0653,7.99501L19.0625,7.99501z M14.4823,2C14.7861,2 15.0418,2.08793 15.2496,2.26378 15.4575,2.43963 15.5614,2.64746 15.5614,2.88726L15.5614,4.99751 19.0625,4.99751C19.3343,4.99751 19.5661,5.10142 19.7579,5.30925 19.9498,5.50109 20.0457,5.73289 20.0457,6.00467 20.0457,6.27644 19.9498,6.51624 19.7579,6.72407 19.5661,6.91591 19.3343,7.01183 19.0625,7.01183L6.0653,7.01183C5.79352,7.01183 5.55372,6.91591 5.34589,6.72407 5.15405,6.51624 5.05814,6.27644 5.05814,6.00467 5.05814,5.73289 5.15405,5.50109 5.34589,5.30925 5.55372,5.10142 5.79352,4.99751 6.0653,4.99751L9.56638,4.99751 9.56638,2.88726C9.56638,2.66345 9.65432,2.47161 9.83017,2.31174 10.022,2.15187 10.2538,2.05595 10.5256,2.02398L10.6455,2 14.4823,2z";
+
+ public static string LinedEraserCircleIcon =
+ "F1 M24,24z M0,0z M15.0665,2.29557L21.6921,8.92118C21.8892,9.11823 21.9877,9.36453 21.9877,9.6601 21.9877,9.93924 21.8892,10.1773 21.6921,10.3744L10.3621,21.6798C10.165,21.8933 9.92694,22 9.6478,22 9.36865,22 9.12235,21.8933 8.90888,21.6798L2.30789,15.0788C2.11085,14.8654 2.01233,14.619 2.01233,14.3399 2.01233,14.0608 2.11085,13.8227 2.30789,13.6256L13.6133,2.29557C13.8103,2.09852 14.0485,2 14.3276,2 14.6232,2 14.8695,2.09852 15.0665,2.29557z M8.19458,11.5813C8.09606,11.4828 7.97292,11.4335 7.82514,11.4335 7.69377,11.4335 7.57883,11.4828 7.48031,11.5813L5.28818,13.7734C5.18965,13.8719 5.14041,13.9951 5.14041,14.1429 5.14041,14.2906 5.18965,14.4138 5.28818,14.5123L9.47539,18.6995C9.59033,18.8144 9.71347,18.8719 9.84483,18.8719 9.99261,18.8719 10.1158,18.8144 10.2143,18.6995L12.4064,16.5074C12.5049,16.4089 12.5542,16.2939 12.5542,16.1626 12.5542,16.0148 12.5049,15.8916 12.4064,15.7931L8.19458,11.5813z";
+
+ public static string SolidEraserCircleIcon =
+ "F1 M24,24z M0,0z M15.0665,2.29557L21.6921,8.92118C21.8892,9.11823 21.9877,9.36453 21.9877,9.6601 21.9877,9.93924 21.8892,10.1773 21.6921,10.3744L10.3621,21.6798C10.165,21.8933 9.92694,22 9.6478,22 9.36865,22 9.12235,21.8933 8.90888,21.6798L2.30789,15.0788C2.11085,14.8654 2.01233,14.619 2.01233,14.3399 2.01233,14.0608 2.11085,13.8227 2.30789,13.6256L13.6133,2.29557C13.8103,2.09852 14.0485,2 14.3276,2 14.6232,2 14.8695,2.09852 15.0665,2.29557z M8.19458,11.5813C8.09606,11.4828 7.97292,11.4335 7.82514,11.4335 7.69377,11.4335 7.57883,11.4828 7.48031,11.5813L5.28818,13.7734C5.18965,13.8719 5.14041,13.9951 5.14041,14.1429 5.14041,14.2906 5.18965,14.4138 5.28818,14.5123L9.47539,18.6995C9.59033,18.8144 9.71347,18.8719 9.84483,18.8719 9.99261,18.8719 10.1158,18.8144 10.2143,18.6995L12.4064,16.5074C12.5049,16.4089 12.5542,16.2939 12.5542,16.1626 12.5542,16.0148 12.5049,15.8916 12.4064,15.7931L8.19458,11.5813z";
+
+ public static string LinedLassoSelectIcon =
+ "F0 M24,24z M0,0z M21.1749,3.19033C21.2959,3.31432,21.3512,3.45083,21.3512,3.62667L21.3512,15.7344 18.9141,14.0608 18.9141,5.43716 5.30084,5.43716 5.30084,19.0505 14.7641,19.0505 15.0947,21.4876 3.49029,21.4876C3.31451,21.4876 3.178,21.4323 3.05397,21.3113 2.92046,21.1636 2.86368,21.0107 2.86368,20.8334L2.86368,3.62667C2.86368,3.44751 2.92108,3.30918 3.04695,3.18331 3.17285,3.0574 3.31118,3 3.49029,3L20.697,3C20.8743,3,21.0272,3.0568,21.1749,3.19033z M15.042,13.7475L16.02,20.0637C16.0562,20.2901,16.1015,20.6026,16.1559,21.001L16.3052,21.9247C16.3234,22.0424 16.3686,22.1239 16.4411,22.1692 16.5226,22.2144 16.6086,22.2235 16.6992,22.1963 16.7897,22.1601 16.8667,22.0877 16.9301,21.979L18.2205,19.7242 20.421,22.8755C20.4663,22.9389 20.5251,22.9796 20.5976,22.9978 20.6791,23.0068 20.7515,22.9887 20.8149,22.9434L21.7522,22.2914C21.8156,22.2461 21.8518,22.1873 21.8609,22.1148 21.879,22.0333 21.8654,21.9609 21.8201,21.8975L19.7555,18.9499 22.7981,18.9499C22.9249,18.9499 23.0154,18.9137 23.0698,18.8412 23.1332,18.7597 23.1512,18.6692 23.1241,18.5696 23.0969,18.47 23.0336,18.3839 22.934,18.3115 22.0556,17.7048 20.8693,16.8898 19.3751,15.8665 17.7542,14.7708 16.509,13.9377 15.6396,13.3672 15.531,13.2947 15.4224,13.2585 15.3137,13.2585 15.205,13.2585 15.1235,13.2992 15.0692,13.3807 15.0149,13.4622 15.0058,13.5845 15.042,13.7475z";
+
+ public static string SolidLassoSelectIcon =
+ "F0 M24,24z M0,0z M21.1749,3.19033C21.2959,3.31432,21.3512,3.45083,21.3512,3.62667L21.3512,15.7344 18.9141,14.0608 18.9141,5.43716 5.30084,5.43716 5.30084,19.0505 14.7641,19.0505 15.0947,21.4876 3.49029,21.4876C3.31451,21.4876 3.178,21.4323 3.05397,21.3113 2.92046,21.1636 2.86368,21.0107 2.86368,20.8334L2.86368,3.62667C2.86368,3.44751 2.92108,3.30918 3.04695,3.18331 3.17285,3.0574 3.31118,3 3.49029,3L20.697,3C20.8743,3,21.0272,3.0568,21.1749,3.19033z M15.042,13.7475L16.02,20.0637C16.0562,20.2901,16.1015,20.6026,16.1559,21.001L16.3052,21.9247C16.3234,22.0424 16.3686,22.1239 16.4411,22.1692 16.5226,22.2144 16.6086,22.2235 16.6992,22.1963 16.7897,22.1601 16.8667,22.0877 16.9301,21.979L18.2205,19.7242 20.421,22.8755C20.4663,22.9389 20.5251,22.9796 20.5976,22.9978 20.6791,23.0068 20.7515,22.9887 20.8149,22.9434L21.7522,22.2914C21.8156,22.2461 21.8518,22.1873 21.8609,22.1148 21.879,22.0333 21.8654,21.9609 21.8201,21.8975L19.7555,18.9499 22.7981,18.9499C22.9249,18.9499 23.0154,18.9137 23.0698,18.8412 23.1332,18.7597 23.1512,18.6692 23.1241,18.5696 23.0969,18.47 23.0336,18.3839 22.934,18.3115 22.0556,17.7048 20.8693,16.8898 19.3751,15.8665 17.7542,14.7708 16.509,13.9377 15.6396,13.3672 15.531,13.2947 15.4224,13.2585 15.3137,13.2585 15.205,13.2585 15.1235,13.2992 15.0692,13.3807 15.0149,13.4622 15.0058,13.5845 15.042,13.7475z";
+
+ public static string DisabledGestureIcon =
+ "F0 M24,24z M0,0z M7.82154,10.0753L7.82154,3.74613C7.82154,3.06603 8.08946,2.40655 8.57377,1.92224 9.05808,1.43793 9.70726,1.17001 10.3977,1.17001 11.0881,1.17001 11.7372,1.43793 12.2216,1.92224 12.7059,2.40655 12.9738,3.05573 12.9738,3.74613L12.9738,6.37308C13.1415,6.33947 13.3139,6.32225 13.489,6.32225 14.1794,6.32225 14.8286,6.59016 15.3129,7.07447 15.4484,7.21001 15.567,7.35845 15.6675,7.5171 15.9551,7.40916 16.2634,7.35269 16.5803,7.35269 17.2707,7.35269 17.9199,7.62061 18.4042,8.10492 18.5461,8.24683 18.6695,8.4029 18.7729,8.57001 19.6856,8.26338 20.7674,8.45871 21.4647,9.15599 21.949,9.6403 22.2169,10.2998 22.2169,10.9799L22.2169,15.6169C22.2169,17.5438 21.4647,19.3574 20.1045,20.7176 18.7443,22.0778 16.9307,22.83 15.0038,22.83L13.149,22.83 13.1799,22.8094 12.8398,22.8094C11.7682,22.7579 10.7068,22.4694 9.75878,21.9541 8.70773,21.3874 7.81124,20.563 7.15175,19.5738L6.94566,19.2647C6.60562,18.7494 5.49273,16.8019 3.52458,13.3087 3.19484,12.7213 3.1021,12.0412 3.27727,11.3818 3.45245,10.7326 3.86463,10.1761 4.44168,9.83608 5.00842,9.49604 5.66791,9.35177 6.31709,9.43421 6.86548,9.50385 7.39181,9.7279 7.82154,10.0753z M10.037,3.38547C10.1297,3.28243 10.2637,3.23091 10.3977,3.23091 10.5316,3.23091 10.6656,3.29273 10.7583,3.38547 10.8614,3.47821 10.9129,3.61217 10.9129,3.74613L10.9129,11.4745C10.9129,12.0412 11.3766,12.5049 11.9433,12.5049 12.5101,12.5049 12.9738,12.0412 12.9738,11.4745L12.9738,8.89836C12.9738,8.7644 13.0356,8.63045 13.1283,8.53771 13.2211,8.43466 13.355,8.38314 13.489,8.38314 13.623,8.38314 13.7569,8.44497 13.8497,8.53771 13.9527,8.63045 14.0042,8.7644 14.0042,8.89836L14.0042,11.4745C14.0042,12.0412 14.4679,12.5049 15.0347,12.5049 15.6014,12.5049 16.0651,12.0412 16.0651,11.4745L16.0651,9.92881C16.0651,9.79485 16.1269,9.66089 16.2197,9.56815 16.3124,9.46511 16.4464,9.41359 16.5803,9.41359 16.7143,9.41359 16.8483,9.47541 16.941,9.56815 17.044,9.66089 17.0956,9.79485 17.0956,9.92881L17.0956,10.5869C17.0752,10.7163 17.0646,10.8477 17.0646,10.9799 17.0646,11.0661 17.0754,11.1499 17.0956,11.2301L17.0956,11.4745C17.0956,12.0412 17.5593,12.5049 18.126,12.5049 18.6928,12.5049 19.1565,12.0412 19.1565,11.4745L19.1565,10.8128C19.1834,10.7399 19.2266,10.6727 19.2801,10.6192 19.4759,10.4234 19.8159,10.4234 20.0117,10.6192 20.1148,10.712 20.1663,10.8459 20.1663,10.9799L20.1663,15.6169C20.1663,16.9977 19.6408,18.296 18.6618,19.2647 17.6829,20.2333 16.3949,20.7691 15.0141,20.7691L13.1593,20.7691C12.3143,20.7691 11.4796,20.5527 10.7274,20.1509 9.98548,19.749 9.3363,19.1616 8.8726,18.4506L8.66651,18.1415C8.35737,17.6675 7.23419,15.7096 5.31756,12.2988 5.24543,12.1752 5.23512,12.0412 5.26604,11.9073 5.30725,11.7733 5.38969,11.6703 5.50304,11.5981 5.66791,11.4951 5.874,11.4539 6.06978,11.4745 6.26557,11.5054 6.45105,11.5878 6.59531,11.7321L8.11007,13.2469C8.49419,13.631 9.10425,13.648 9.50833,13.2978 9.73651,13.1084 9.88244,12.8229 9.88244,12.5049L9.88244,3.74613C9.88244,3.61217,9.94426,3.47821,10.037,3.38547z M2.99905,6.31195L1.78313,4.65293 2.61779,4.04497C3.46275,3.4267,4.37985,2.89087,5.33817,2.46838L6.27587,2.0459 7.12084,3.93162 6.18313,4.3541C5.35878,4.72506,4.56533,5.17846,3.83372,5.71429L2.99905,6.32225 2.99905,6.31195z M18.2806,5.20935L19.1565,5.75549 20.259,4.01404 19.3831,3.4679C18.1157,2.67446,16.7452,2.0768,15.3026,1.68523L14.303,1.41731 13.7672,3.40607 14.7667,3.67399C16.0033,4.00373,17.1883,4.51895,18.2806,5.20935z";
+
+ public static string EnabledGestureIcon =
+ "F1 M24,24z M0,0z M7.29844,9.85586L7.29844,3.52668C7.29844,2.84658 7.56636,2.1871 8.05067,1.70279 8.53498,1.21848 9.18416,0.950562 9.87456,0.950562 10.565,0.950562 11.2141,1.21848 11.6984,1.70279 12.1828,2.1871 12.4507,2.83628 12.4507,3.52668L12.4507,6.15363C12.6184,6.12002 12.7908,6.10279 12.9659,6.10279 13.6563,6.10279 14.3055,6.37071 14.7898,6.85502 14.9253,6.99055 15.0439,7.139 15.1444,7.29765 15.432,7.18971 15.7403,7.13324 16.0572,7.13324 16.7476,7.13324 17.3968,7.40116 17.8811,7.88547 18.023,8.02738 18.1464,8.18344 18.2498,8.35055 19.1625,8.04393 20.2443,8.23925 20.9416,8.93654 21.4259,9.42085 21.6938,10.0803 21.6938,10.7604L21.6938,14.2958C21.1174,13.741,20.4192,13.3118,19.6432,13.0524L19.6432,10.7604C19.6432,10.6265 19.5917,10.4925 19.4886,10.3998 19.2928,10.204 18.9528,10.204 18.757,10.3998 18.7035,10.4532 18.6603,10.5204 18.6334,10.5934L18.6334,11.255C18.6334,11.8218 18.1697,12.2855 17.6029,12.2855 17.0362,12.2855 16.5725,11.8218 16.5725,11.255L16.5725,11.0106C16.5523,10.9304 16.5415,10.8466 16.5415,10.7604 16.5415,10.6283 16.5521,10.4969 16.5725,10.3674L16.5725,9.70936C16.5725,9.5754 16.5209,9.44144 16.4179,9.3487 16.3252,9.25596 16.1912,9.19413 16.0572,9.19413 15.9233,9.19413 15.7893,9.24566 15.6966,9.3487 15.6038,9.44144 15.542,9.5754 15.542,9.70936L15.542,11.255C15.542,11.8218 15.0783,12.2855 14.5116,12.2855 13.9448,12.2855 13.4811,11.8218 13.4811,11.255L13.4811,8.67891C13.4811,8.54495 13.4296,8.41099 13.3266,8.31825 13.2338,8.22551 13.0999,8.16369 12.9659,8.16369 12.8319,8.16369 12.698,8.21521 12.6052,8.31825 12.5125,8.41099 12.4507,8.54495 12.4507,8.67891L12.4507,11.255C12.4507,11.8218 11.987,12.2855 11.4202,12.2855 10.8535,12.2855 10.3898,11.8218 10.3898,11.255L10.3898,3.52668C10.3898,3.39272 10.3383,3.25876 10.2352,3.16602 10.1425,3.07328 10.0085,3.01145 9.87456,3.01145 9.7406,3.01145 9.60664,3.06298 9.5139,3.16602 9.42116,3.25876 9.35933,3.39272 9.35933,3.52668L9.35933,12.2855C9.35933,12.6034 9.21341,12.8889 8.98523,13.0783 8.58114,13.4285 7.97109,13.4115 7.58697,13.0274L6.07221,11.5127C5.92795,11.3684 5.74247,11.286 5.54668,11.255 5.3509,11.2344 5.14481,11.2756 4.97994,11.3787 4.86659,11.4508 4.78415,11.5539 4.74293,11.6878 4.71202,11.8218 4.72232,11.9557 4.79446,12.0794 6.71109,15.4902 7.83427,17.448 8.14341,17.922L8.3495,18.2312C8.8132,18.9422 9.46238,19.5295 10.2043,19.9314 10.9565,20.3333 11.7912,20.5497 12.6362,20.5497L12.9829,20.5497C13.3696,21.3681 13.9542,22.0748 14.6748,22.608 14.6102,22.6097 14.5455,22.6106 14.4807,22.6106L12.6258,22.6106 12.6568,22.59 12.3167,22.59C11.2451,22.5384 10.1837,22.2499 9.23568,21.7347 8.18463,21.1679 7.28814,20.3436 6.62865,19.3544L6.42256,19.0452C6.08251,18.53 4.96963,16.5824 3.00148,13.0892 2.67174,12.5019 2.579,11.8218 2.75417,11.1623 2.92935,10.5131 3.34153,9.95668 3.91858,9.61663 4.48532,9.27658 5.14481,9.13232 5.79399,9.21476 6.34238,9.28439 6.86871,9.50845 7.29844,9.85586z M2.47595,6.0925L1.26003,4.43348 2.09469,3.82551C2.93965,3.20725,3.85675,2.67141,4.81507,2.24893L5.75277,1.82645 6.59774,3.71216 5.66003,4.13465C4.83567,4.50561,4.04223,4.959,3.31061,5.49484L2.47595,6.1028 2.47595,6.0925z M17.7575,4.9899L18.6334,5.53604 19.7359,3.79458 18.86,3.24845C17.5926,2.455,16.2221,1.85734,14.7795,1.46577L13.7799,1.19786 13.2441,3.18662 14.2436,3.45454C15.4802,3.78428,16.6652,4.2995,17.7575,4.9899z";
+
+ public static string EnabledGestureIconBadgeCheck =
+ "M22.74,18.2234C22.74,20.8888 20.5793,23.0494 17.914,23.0494 15.2487,23.0494 13.088,20.8888 13.088,18.2234 13.088,15.5581 15.2487,13.3975 17.914,13.3975 20.5793,13.3975 22.74,15.5581 22.74,18.2234z M21.1673,15.8009C21.4651,16.0889,21.473,16.5637,21.1851,16.8614L17.5425,20.6282C17.4012,20.7743 17.2066,20.8568 17.0034,20.8568 16.8001,20.8568 16.6055,20.7743 16.4642,20.6282L14.6429,18.7448C14.355,18.447 14.3629,17.9722 14.6607,17.6843 14.9585,17.3963 15.4333,17.4043 15.7212,17.7021L17.0034,19.0279 20.1068,15.8187C20.3947,15.5209,20.8695,15.513,21.1673,15.8009z";
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Notification.cs b/Ink Canvas/MainWindow_cs/MW_Notification.cs
new file mode 100644
index 00000000..25d31510
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Notification.cs
@@ -0,0 +1,35 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Windows;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private int lastNotificationShowTime = 0;
+ private int notificationShowTime = 2500;
+
+ public static void ShowNewMessage(string notice, bool isShowImmediately = true) {
+ (Application.Current?.Windows.Cast().FirstOrDefault(window => window is MainWindow) as MainWindow)
+ ?.ShowNotification(notice, isShowImmediately);
+ }
+
+ public void ShowNotification(string notice, bool isShowImmediately = true) {
+ try {
+ lastNotificationShowTime = Environment.TickCount;
+
+ TextBlockNotice.Text = notice;
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(GridNotifications);
+
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(notificationShowTime + 300);
+ if (Environment.TickCount - lastNotificationShowTime >= notificationShowTime)
+ Application.Current.Dispatcher.Invoke(() => {
+ AnimationsHelper.HideWithSlideAndFade(GridNotifications);
+ });
+ })).Start();
+ }
+ catch { }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs
new file mode 100644
index 00000000..9dae245e
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs
@@ -0,0 +1,1095 @@
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern;
+using Microsoft.Office.Core;
+using Microsoft.Office.Interop.PowerPoint;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Timers;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Threading;
+using Application = System.Windows.Application;
+using File = System.IO.File;
+using MessageBox = System.Windows.MessageBox;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ public static Microsoft.Office.Interop.PowerPoint.Application pptApplication = null;
+ public static Presentation presentation = null;
+ public static Slides slides = null;
+ public static Slide slide = null;
+ public static int slidescount = 0;
+
+ private void BtnCheckPPT_Click(object sender, RoutedEventArgs e) {
+ try {
+ pptApplication =
+ (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("kwpp.Application");
+
+ if (pptApplication != null) {
+ //获得演示文稿对象
+ presentation = pptApplication.ActivePresentation;
+ pptApplication.SlideShowBegin += PptApplication_SlideShowBegin;
+ pptApplication.SlideShowNextSlide += PptApplication_SlideShowNextSlide;
+ pptApplication.SlideShowEnd += PptApplication_SlideShowEnd;
+ // 获得幻灯片对象集合
+ slides = presentation.Slides;
+ // 获得幻灯片的数量
+ slidescount = slides.Count;
+ memoryStreams = new MemoryStream[slidescount + 2];
+ // 获得当前选中的幻灯片
+ try {
+ // 在普通视图下这种方式可以获得当前选中的幻灯片对象
+ // 然而在阅读模式下,这种方式会出现异常
+ slide = slides[pptApplication.ActiveWindow.Selection.SlideRange.SlideNumber];
+ }
+ catch {
+ // 在阅读模式下出现异常时,通过下面的方式来获得当前选中的幻灯片对象
+ slide = pptApplication.SlideShowWindows[1].View.Slide;
+ }
+ }
+
+ if (pptApplication == null) throw new Exception();
+ StackPanelPPTControls.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ StackPanelPPTControls.Visibility = Visibility.Collapsed;
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ MessageBox.Show("未找到幻灯片");
+ }
+ }
+
+ private void ToggleSwitchSupportWPS_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+
+ Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
+
+ public static bool IsShowingRestoreHiddenSlidesWindow = false;
+ private static bool IsShowingAutoplaySlidesWindow = false;
+ private static bool hasLoggedPresentationWarning = false;
+
+
+ private void TimerCheckPPT_Elapsed(object sender, ElapsedEventArgs e) {
+ if (IsShowingRestoreHiddenSlidesWindow || IsShowingAutoplaySlidesWindow) return;
+ try
+ {
+ pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
+ }
+ catch (COMException)
+ {
+ // 创建新实例或记录错误
+ }
+
+ try {
+ var processes = Process.GetProcessesByName("wpp");
+ if (processes.Length > 0 && !isWPSSupportOn) return;
+
+ pptApplication = (Microsoft.Office.Interop.PowerPoint.Application)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("91493441-5A91-11CF-8700-00AA0060263B")));
+ new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowBegin").AddEventHandler(pptApplication, new EApplication_SlideShowBeginEventHandler(this.PptApplication_SlideShowBegin));
+ new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowEnd").AddEventHandler(pptApplication, new EApplication_SlideShowEndEventHandler(this.PptApplication_SlideShowEnd));
+ new ComAwareEventInfo(typeof(EApplication_Event), "SlideShowNextSlide").AddEventHandler(pptApplication, new EApplication_SlideShowNextSlideEventHandler(this.PptApplication_SlideShowNextSlide));
+
+ pptApplication =
+ (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
+ if (pptApplication == null || pptApplication.Presentations.Count == 0)
+ {
+ if (!hasLoggedPresentationWarning)
+ {
+ LogHelper.WriteLogToFile("No active presentation found", LogHelper.LogType.Warning);
+ hasLoggedPresentationWarning = true;
+ }
+ return;
+ }
+
+ if (pptApplication != null) {
+ timerCheckPPT.Stop();
+ //获得演示文稿对象
+ presentation = pptApplication.ActivePresentation;
+
+ // 获得幻灯片对象集合
+ slides = presentation.Slides;
+
+ // 获得幻灯片的数量
+ slidescount = slides.Count;
+ memoryStreams = new MemoryStream[slidescount + 2];
+ // 获得当前选中的幻灯片
+ try {
+ // 在普通视图下这种方式可以获得当前选中的幻灯片对象
+ // 然而在阅读模式下,这种方式会出现异常
+ slide = slides[pptApplication.ActiveWindow.Selection.SlideRange.SlideNumber];
+ }
+ catch {
+ // 在阅读模式下出现异常时,通过下面的方式来获得当前选中的幻灯片对象
+ slide = pptApplication.SlideShowWindows[1].View.Slide;
+ }
+
+ pptApplication.PresentationOpen += PptApplication_PresentationOpen;
+ pptApplication.PresentationClose += PptApplication_PresentationClose;
+ pptApplication.SlideShowBegin += PptApplication_SlideShowBegin;
+ pptApplication.SlideShowNextSlide += PptApplication_SlideShowNextSlide;
+ pptApplication.SlideShowEnd += PptApplication_SlideShowEnd;
+ }
+
+ if (pptApplication == null) return;
+
+ // 此处是已经开启了
+ Application.Current.Dispatcher.Invoke(() => {
+ PptApplication_PresentationOpen(null);
+ });
+
+ //如果检测到已经开始放映,则立即进入画板模式
+ if (pptApplication.SlideShowWindows.Count >= 1) {
+ Application.Current.Dispatcher.Invoke(() => {
+ PptApplication_SlideShowBegin(pptApplication.SlideShowWindows[1]);
+ });
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ Application.Current.Dispatcher.Invoke(() => {
+ BtnPPTSlideShow.Visibility = Visibility.Collapsed;
+ timerCheckPPT.Start();
+ });
+ }
+ }
+
+ private void PptApplication_PresentationOpen(Presentation Pres) {
+ // 跳转到上次播放页
+ Application.Current.Dispatcher.BeginInvoke(new Action(() => {
+ try {
+ if (!Settings.PowerPointSettings.IsNotifyPreviousPage) return;
+
+ var folderPath = Settings.Automation.AutoSavedStrokesLocation +
+ @"\Auto Saved - Presentations\" + presentation.Name + "_" +
+ presentation.Slides.Count;
+
+ if (!File.Exists(folderPath + "/Position")) return;
+ if (!int.TryParse(File.ReadAllText(folderPath + "/Position"), out var page)) return;
+ if (page <= 0) return;
+
+ new YesOrNoNotificationWindow($"上次播放到了第 {page} 页, 是否立即跳转", () => {
+ if (pptApplication.SlideShowWindows.Count >= 1)
+ // 如果已经播放了的话, 跳转
+ presentation.SlideShowWindow.View.GotoSlide(page);
+ else
+ presentation.Windows[1].View.GotoSlide(page);
+ }).ShowDialog();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }), DispatcherPriority.Normal);
+
+
+ //检查是否有隐藏幻灯片
+ if (Settings.PowerPointSettings.IsNotifyHiddenPage) {
+ var isHaveHiddenSlide = false;
+ foreach (Slide slide in slides)
+ if (slide.SlideShowTransition.Hidden == Microsoft.Office.Core.MsoTriState.msoTrue) {
+ isHaveHiddenSlide = true;
+ break;
+ }
+
+ Application.Current.Dispatcher.BeginInvoke(new Action(() => {
+ if (isHaveHiddenSlide && !IsShowingRestoreHiddenSlidesWindow) {
+ IsShowingRestoreHiddenSlidesWindow = true;
+ new YesOrNoNotificationWindow("检测到此演示文档中包含隐藏的幻灯片,是否取消隐藏?",
+ () => {
+ foreach (Slide slide in slides)
+ if (slide.SlideShowTransition.Hidden ==
+ Microsoft.Office.Core.MsoTriState.msoTrue)
+ slide.SlideShowTransition.Hidden =
+ Microsoft.Office.Core.MsoTriState.msoFalse;
+ IsShowingRestoreHiddenSlidesWindow = false;
+ }, () => { IsShowingRestoreHiddenSlidesWindow = false; },
+ () => { IsShowingRestoreHiddenSlidesWindow = false; }).ShowDialog();
+ }
+
+ BtnPPTSlideShow.Visibility = Visibility.Visible;
+ }), DispatcherPriority.Normal);
+ }
+
+ //检测是否有自动播放
+ if (Settings.PowerPointSettings.IsNotifyAutoPlayPresentation
+ && BtnPPTSlideShowEnd.Visibility != Visibility.Visible) {
+ bool hasSlideTimings = false;
+ foreach (Slide slide in presentation.Slides) {
+ if (slide.SlideShowTransition.AdvanceOnTime == MsoTriState.msoTrue &&
+ slide.SlideShowTransition.AdvanceTime > 0) {
+ hasSlideTimings = true;
+ break;
+ }
+ }
+
+ if (hasSlideTimings) {
+ Application.Current.Dispatcher.BeginInvoke((Action)(() => {
+ if (hasSlideTimings && !IsShowingAutoplaySlidesWindow) {
+ IsShowingAutoplaySlidesWindow = true;
+ new YesOrNoNotificationWindow("检测到此演示文档中自动播放或排练计时已经启用,可能导致幻灯片自动翻页,是否取消?",
+ () => {
+ presentation.SlideShowSettings.AdvanceMode =
+ PpSlideShowAdvanceMode.ppSlideShowManualAdvance;
+ IsShowingAutoplaySlidesWindow = false;
+ }, () => { IsShowingAutoplaySlidesWindow = false; },
+ () => { IsShowingAutoplaySlidesWindow = false; }).ShowDialog();
+ }
+ }));
+ presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowManualAdvance;
+ }
+ }
+ }
+
+ private void PptApplication_PresentationClose(Presentation Pres) {
+ try {
+ pptApplication.PresentationOpen -= PptApplication_PresentationOpen;
+ pptApplication.PresentationClose -= PptApplication_PresentationClose;
+ pptApplication.SlideShowBegin -= PptApplication_SlideShowBegin;
+ pptApplication.SlideShowNextSlide -= PptApplication_SlideShowNextSlide;
+ pptApplication.SlideShowEnd -= PptApplication_SlideShowEnd;
+
+ // 释放COM对象
+ if (slide != null) {
+ Marshal.ReleaseComObject(slide);
+ slide = null;
+ }
+
+ if (slides != null) {
+ Marshal.ReleaseComObject(slides);
+ slides = null;
+ }
+
+ if (presentation != null) {
+ Marshal.ReleaseComObject(presentation);
+ presentation = null;
+ }
+
+ if (pptApplication != null) {
+ Marshal.ReleaseComObject(pptApplication);
+ pptApplication = null;
+ }
+
+ timerCheckPPT.Start();
+
+ Application.Current.Dispatcher.Invoke(() => {
+ BtnPPTSlideShow.Visibility = Visibility.Collapsed;
+ BtnPPTSlideShowEnd.Visibility = Visibility.Collapsed;
+ });
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private bool isPresentationHaveBlackSpace = false;
+ private string pptName = null;
+
+ private void UpdatePPTBtnStyleSettingsStatus() {
+ try {
+ var sopt = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ char[] soptc = sopt.ToCharArray();
+ if (soptc[0] == '2')
+ {
+ PPTLSPageButton.Visibility = Visibility.Visible;
+ PPTRSPageButton.Visibility = Visibility.Visible;
+ }
+ else
+ {
+ PPTLSPageButton.Visibility = Visibility.Collapsed;
+ PPTRSPageButton.Visibility = Visibility.Collapsed;
+ }
+ if (soptc[2] == '2')
+ {
+ // 这里先堆一点屎山,没空用Resources了
+ PPTBtnLSBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTBtnRSBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTBtnLSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
+ PPTBtnRSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
+ PPTLSPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTRSPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTLSNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTRSNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTLSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTLSPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRSPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTLSNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRSNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ TextBlock.SetForeground(PPTLSPageButton, new SolidColorBrush(Colors.White));
+ TextBlock.SetForeground(PPTRSPageButton, new SolidColorBrush(Colors.White));
+ }
+ else
+ {
+ PPTBtnLSBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ PPTBtnRSBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ PPTBtnLSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ PPTBtnRSBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ PPTLSPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTRSPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTLSNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTRSNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTLSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRSPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTLSPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRSPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTLSNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRSNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ TextBlock.SetForeground(PPTLSPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
+ TextBlock.SetForeground(PPTRSPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
+ }
+ if (soptc[1] == '2')
+ {
+ PPTBtnLSBorder.Opacity = 0.5;
+ PPTBtnRSBorder.Opacity = 0.5;
+ }
+ else
+ {
+ PPTBtnLSBorder.Opacity = 1;
+ PPTBtnRSBorder.Opacity = 1;
+ }
+
+ var bopt = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ char[] boptc = bopt.ToCharArray();
+ if (boptc[0] == '2')
+ {
+ PPTLBPageButton.Visibility = Visibility.Visible;
+ PPTRBPageButton.Visibility = Visibility.Visible;
+ }
+ else
+ {
+ PPTLBPageButton.Visibility = Visibility.Collapsed;
+ PPTRBPageButton.Visibility = Visibility.Collapsed;
+ }
+ if (boptc[2] == '2')
+ {
+ // 这里先堆一点屎山,没空用Resources了
+ PPTBtnLBBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTBtnRBBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTBtnLBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
+ PPTBtnRBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(82, 82, 91));
+ PPTLBPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTRBPreviousButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTLBNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTRBNextButtonGeometry.Brush = new SolidColorBrush(Colors.White);
+ PPTLBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTLBPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRBPageButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTLBNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ PPTRBNextButtonFeedbackBorder.Background = new SolidColorBrush(Colors.White);
+ TextBlock.SetForeground(PPTLBPageButton, new SolidColorBrush(Colors.White));
+ TextBlock.SetForeground(PPTRBPageButton, new SolidColorBrush(Colors.White));
+ }
+ else
+ {
+ PPTBtnLBBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ PPTBtnRBBorder.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
+ PPTBtnLBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ PPTBtnRBBorder.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
+ PPTLBPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTRBPreviousButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTLBNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTRBNextButtonGeometry.Brush = new SolidColorBrush(Color.FromRgb(39, 39, 42));
+ PPTLBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRBPreviousButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTLBPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRBPageButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTLBNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ PPTRBNextButtonFeedbackBorder.Background = new SolidColorBrush(Color.FromRgb(24, 24, 27));
+ TextBlock.SetForeground(PPTLBPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
+ TextBlock.SetForeground(PPTRBPageButton, new SolidColorBrush(Color.FromRgb(24, 24, 27)));
+ }
+ if (boptc[1] == '2')
+ {
+ PPTBtnLBBorder.Opacity = 0.5;
+ PPTBtnRBBorder.Opacity = 0.5;
+ }
+ else
+ {
+ PPTBtnLBBorder.Opacity = 1;
+ PPTBtnRBBorder.Opacity = 1;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void UpdatePPTBtnDisplaySettingsStatus() {
+ try {
+ if (!Settings.PowerPointSettings.ShowPPTButton || BtnPPTSlideShowEnd.Visibility != Visibility.Visible)
+ {
+ 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;
+ RightSidePanelForPPTNavigation.Margin = new Thickness(0, 0, 0, rsp*2);
+
+ 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);
+ else RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ if (doptc[2] == '2') AnimationsHelper.ShowWithFadeIn(LeftSidePanelForPPTNavigation);
+ else LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ if (doptc[3] == '2') AnimationsHelper.ShowWithFadeIn(RightSidePanelForPPTNavigation);
+ else RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private async void PptApplication_SlideShowBegin(SlideShowWindow Wn) {
+ try {
+ if (Settings.Automation.IsAutoFoldInPPTSlideShow && !isFloatingBarFolded)
+ await FoldFloatingBar(new object());
+ else if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
+
+ isStopInkReplay = true;
+
+ LogHelper.WriteLogToFile("PowerPoint Application Slide Show Begin", LogHelper.LogType.Event);
+
+ await Application.Current.Dispatcher.InvokeAsync(() => {
+
+ //调整颜色
+ var screenRatio = SystemParameters.PrimaryScreenWidth / SystemParameters.PrimaryScreenHeight;
+ if (Math.Abs(screenRatio - 16.0 / 9) <= -0.01) {
+ if (Wn.Presentation.PageSetup.SlideWidth / Wn.Presentation.PageSetup.SlideHeight < 1.65) {
+ isPresentationHaveBlackSpace = true;
+
+ if (BtnSwitchTheme.Content.ToString() == "深色") {
+ //Light
+ BtnExit.Foreground = Brushes.White;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
+ } else {
+ //Dark
+ }
+ }
+ } else if (screenRatio == -256 / 135) { }
+
+ lastDesktopInkColor = 1;
+
+ slidescount = Wn.Presentation.Slides.Count;
+ previousSlideID = 0;
+ memoryStreams = new MemoryStream[slidescount + 2];
+
+ pptName = Wn.Presentation.Name;
+ LogHelper.NewLog("Name: " + Wn.Presentation.Name);
+ LogHelper.NewLog("Slides Count: " + slidescount.ToString());
+
+ //检查是否有已有墨迹,并加载
+ if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint)
+ if (Directory.Exists(Settings.Automation.AutoSavedStrokesLocation +
+ @"\Auto Saved - Presentations\" + Wn.Presentation.Name + "_" +
+ Wn.Presentation.Slides.Count)) {
+ LogHelper.WriteLogToFile("Found saved strokes", LogHelper.LogType.Trace);
+ var files = new DirectoryInfo(Settings.Automation.AutoSavedStrokesLocation +
+ @"\Auto Saved - Presentations\" + Wn.Presentation.Name + "_" +
+ Wn.Presentation.Slides.Count).GetFiles();
+ var count = 0;
+ foreach (var file in files)
+ if (file.Name != "Position") {
+ var i = -1;
+ try {
+ i = int.Parse(Path.GetFileNameWithoutExtension(file.Name));
+ memoryStreams[i] = new MemoryStream(File.ReadAllBytes(file.FullName));
+ memoryStreams[i].Position = 0;
+ count++;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(
+ $"Failed to load strokes on Slide {i}\n{ex.ToString()}",
+ LogHelper.LogType.Error);
+ }
+ }
+
+ LogHelper.WriteLogToFile($"Loaded {count.ToString()} saved strokes");
+ }
+
+ StackPanelPPTControls.Visibility = Visibility.Visible;
+ UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnStyleSettingsStatus();
+
+ BtnPPTSlideShow.Visibility = Visibility.Collapsed;
+ BtnPPTSlideShowEnd.Visibility = Visibility.Visible;
+ ViewBoxStackPanelMain.Margin = new Thickness(10, 10, 10, 10);
+ ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue;
+
+ if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
+ !Settings.Automation.IsAutoFoldInPPTSlideShow &&
+ GridTransparencyFakeBackground.Background == Brushes.Transparent && !isFloatingBarFolded) {
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+ }
+
+ if (currentMode != 0)
+ {
+ ImageBlackboard_MouseUp(null,null);
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+ }
+
+ BorderFloatingBarMainControls.Visibility = Visibility.Visible;
+
+ if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
+ !Settings.Automation.IsAutoFoldInPPTSlideShow)
+ BtnColorRed_Click(null, null);
+
+ isEnteredSlideShowEndEvent = false;
+ PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}";
+ PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}";
+ LogHelper.NewLog("PowerPoint Slide Show Loading process complete");
+
+ if (!isFloatingBarFolded) {
+ new Thread(new ThreadStart(() => {
+ Thread.Sleep(100);
+ Application.Current.Dispatcher.Invoke(() => {
+ ViewboxFloatingBarMarginAnimation(60);
+ });
+ })).Start();
+ }
+ });
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private bool isEnteredSlideShowEndEvent = false; //防止重复调用本函数导致墨迹保存失效
+
+ private async void PptApplication_SlideShowEnd(Presentation Pres) {
+ try {
+ if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
+
+ LogHelper.WriteLogToFile(string.Format("PowerPoint Slide Show End"), LogHelper.LogType.Event);
+ if (isEnteredSlideShowEndEvent) {
+ LogHelper.WriteLogToFile("Detected previous entrance, returning");
+ return;
+ }
+
+ isEnteredSlideShowEndEvent = true;
+ if (Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint) {
+ var folderPath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - Presentations\" +
+ Pres.Name + "_" + Pres.Slides.Count;
+ if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
+ try {
+ File.WriteAllText(folderPath + "/Position", previousSlideID.ToString());
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ for (var i = 1; i <= Pres.Slides.Count; i++)
+ if (memoryStreams[i] != null)
+ try {
+ if (memoryStreams[i].Length > 8) {
+ var srcBuf = new byte[memoryStreams[i].Length];
+ memoryStreams[i].Position = 0;
+ var byteLength = memoryStreams[i].Read(srcBuf, 0, srcBuf.Length);
+ File.WriteAllBytes(folderPath + @"\" + i.ToString("0000") + ".icstk", srcBuf);
+ LogHelper.WriteLogToFile(string.Format(
+ "Saved strokes for Slide {0}, size={1}, byteLength={2}", i.ToString(),
+ memoryStreams[i].Length, byteLength));
+ } else {
+ if (File.Exists(folderPath + @"\" + i.ToString("0000") + ".icstk"))
+ File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk");
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(
+ $"Failed to save strokes for Slide {i}\n{ex.ToString()}",
+ LogHelper.LogType.Error);
+ if (File.Exists(folderPath + @"\" + i.ToString("0000") + ".icstk"))
+ File.Delete(folderPath + @"\" + i.ToString("0000") + ".icstk");
+ }
+ }
+
+ await Application.Current.Dispatcher.InvokeAsync(() => {
+ try {
+ isPresentationHaveBlackSpace = false;
+
+ if (BtnSwitchTheme.Content.ToString() == "深色") {
+ //Light
+ BtnExit.Foreground = Brushes.Black;
+ ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
+ } else {
+ //Dark
+ }
+
+ BtnPPTSlideShow.Visibility = Visibility.Visible;
+ BtnPPTSlideShowEnd.Visibility = Visibility.Collapsed;
+ StackPanelPPTControls.Visibility = Visibility.Collapsed;
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+
+ ViewBoxStackPanelMain.Margin = new Thickness(10, 10, 10, 55);
+
+ if (currentMode != 0) {
+ CloseWhiteboardImmediately();
+ currentMode = 0;
+ }
+
+ ClearStrokes(true);
+
+ if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
+ BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
+
+ ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ });
+
+ await Task.Delay(150);
+
+ Application.Current.Dispatcher.InvokeAsync(() => {
+ ViewboxFloatingBarMarginAnimation(100, true);
+ });
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private int previousSlideID = 0;
+ private MemoryStream[] memoryStreams = new MemoryStream[50];
+
+ private void PptApplication_SlideShowNextSlide(SlideShowWindow Wn) {
+ try {
+ LogHelper.WriteLogToFile($"PowerPoint Next Slide (Slide {Wn.View.CurrentShowPosition})",
+ LogHelper.LogType.Event);
+ if (Wn.View.CurrentShowPosition == previousSlideID) return;
+
+ Application.Current.Dispatcher.Invoke(() => {
+ try {
+ var ms = new MemoryStream();
+ inkCanvas.Strokes.Save(ms);
+ ms.Position = 0;
+ memoryStreams[previousSlideID] = ms;
+
+ if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && !_isPptClickingBtnTurned)
+ SaveScreenShot(true, Wn.Presentation.Name + "/" + Wn.View.CurrentShowPosition);
+ _isPptClickingBtnTurned = false;
+
+ ClearStrokes(true);
+ timeMachine.ClearStrokeHistory();
+
+ if (memoryStreams[Wn.View.CurrentShowPosition] != null &&
+ memoryStreams[Wn.View.CurrentShowPosition].Length > 0) {
+ memoryStreams[Wn.View.CurrentShowPosition].Position = 0;
+ inkCanvas.Strokes.Add(new StrokeCollection(memoryStreams[Wn.View.CurrentShowPosition]));
+ }
+
+ PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}";
+ PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}";
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ });
+
+ previousSlideID = Wn.View.CurrentShowPosition;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private bool _isPptClickingBtnTurned = false;
+
+ private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
+ try {
+ if (currentMode == 1) {
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+ currentMode = 0;
+ }
+
+ _isPptClickingBtnTurned = true;
+
+ if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
+ SaveScreenShot(true,
+ pptApplication.SlideShowWindows[1].Presentation.Name + "/" +
+ pptApplication.SlideShowWindows[1].View.CurrentShowPosition);
+
+ new Thread(new ThreadStart(() => {
+ try {
+ pptApplication.SlideShowWindows[1].Activate();
+ pptApplication.SlideShowWindows[1].View.Previous();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ Application.Current.Dispatcher.Invoke(() => {
+ StackPanelPPTControls.Visibility = Visibility.Collapsed;
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ });
+ }
+ })).Start();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) {
+ try {
+ if (currentMode == 1) {
+ GridBackgroundCover.Visibility = Visibility.Collapsed;
+ AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
+ AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
+ currentMode = 0;
+ }
+
+ _isPptClickingBtnTurned = true;
+ if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
+ SaveScreenShot(true,
+ pptApplication.SlideShowWindows[1].Presentation.Name + "/" +
+ pptApplication.SlideShowWindows[1].View.CurrentShowPosition);
+
+ new Thread(new ThreadStart(() => {
+ try {
+ pptApplication.SlideShowWindows[1].Activate();
+ pptApplication.SlideShowWindows[1].View.Next();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ Application.Current.Dispatcher.Invoke(() => {
+ StackPanelPPTControls.Visibility = Visibility.Collapsed;
+ LeftBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightBottomPanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
+ });
+ }
+ })).Start();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ lastBorderMouseDownObject = sender;
+ if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
+
+ if (sender == PPTLSPageButton)
+ {
+ PPTLSPageButtonFeedbackBorder.Opacity = 0.15;
+ }
+ else if (sender == PPTRSPageButton)
+ {
+ PPTRSPageButtonFeedbackBorder.Opacity = 0.15;
+ }
+ else if (sender == PPTLBPageButton)
+ {
+ PPTLBPageButtonFeedbackBorder.Opacity = 0.15;
+ }
+ else if (sender == PPTRBPageButton)
+ {
+ PPTRBPageButtonFeedbackBorder.Opacity = 0.15;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
+ {
+ try
+ {
+ lastBorderMouseDownObject = null;
+ if (sender == PPTLSPageButton)
+ {
+ PPTLSPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRSPageButton)
+ {
+ PPTRSPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTLBPageButton)
+ {
+ PPTLBPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBPageButton)
+ {
+ PPTRBPageButtonFeedbackBorder.Opacity = 0;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private async void PPTNavigationBtn_MouseUp(object sender, MouseButtonEventArgs e) {
+ try {
+ if (lastBorderMouseDownObject != sender) return;
+
+ if (sender == PPTLSPageButton)
+ {
+ PPTLSPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRSPageButton)
+ {
+ PPTRSPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTLBPageButton)
+ {
+ PPTLBPageButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBPageButton)
+ {
+ PPTRBPageButtonFeedbackBorder.Opacity = 0;
+ }
+
+ if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
+
+ GridTransparencyFakeBackground.Opacity = 1;
+ GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
+ CursorIcon_Click(null, null);
+
+ try {
+ pptApplication.SlideShowWindows[1].SlideNavigation.Visible = true;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ // 控制居中
+ if (!isFloatingBarFolded) {
+ await Task.Delay(100);
+ ViewboxFloatingBarMarginAnimation(60);
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) {
+ try {
+ new Thread(new ThreadStart(() => {
+ try {
+ presentation.SlideShowSettings.Run();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ })).Start();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) {
+ try {
+ Application.Current.Dispatcher.Invoke(() => {
+ try {
+ var ms = new MemoryStream();
+ inkCanvas.Strokes.Save(ms);
+ ms.Position = 0;
+ memoryStreams[pptApplication.SlideShowWindows[1].View.CurrentShowPosition] = ms;
+ timeMachine.ClearStrokeHistory();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ });
+
+ new Thread(new ThreadStart(() => {
+ try {
+ pptApplication.SlideShowWindows[1].View.Exit();
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ })).Start();
+
+ HideSubPanels("cursor");
+ await Task.Delay(150);
+ ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void GridPPTControlPrevious_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ try {
+ lastBorderMouseDownObject = sender;
+ if (sender == PPTLSPreviousButtonBorder) {
+ PPTLSPreviousButtonFeedbackBorder.Opacity = 0.15;
+ } else if (sender == PPTRSPreviousButtonBorder) {
+ PPTRSPreviousButtonFeedbackBorder.Opacity = 0.15;
+ } else if (sender == PPTLBPreviousButtonBorder)
+ {
+ PPTLBPreviousButtonFeedbackBorder.Opacity = 0.15;
+ }
+ else if (sender == PPTRBPreviousButtonBorder)
+ {
+ PPTRBPreviousButtonFeedbackBorder.Opacity = 0.15;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void GridPPTControlPrevious_MouseLeave(object sender, MouseEventArgs e)
+ {
+ try {
+ lastBorderMouseDownObject = null;
+ if (sender == PPTLSPreviousButtonBorder) {
+ PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTRSPreviousButtonBorder) {
+ PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTLBPreviousButtonBorder)
+ {
+ PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBPreviousButtonBorder)
+ {
+ PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void GridPPTControlPrevious_MouseUp(object sender, MouseButtonEventArgs e) {
+ try {
+ if (lastBorderMouseDownObject != sender) return;
+ if (sender == PPTLSPreviousButtonBorder) {
+ PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTRSPreviousButtonBorder) {
+ PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTLBPreviousButtonBorder)
+ {
+ PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBPreviousButtonBorder)
+ {
+ PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
+ }
+ BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+
+ private void GridPPTControlNext_MouseDown(object sender, MouseButtonEventArgs e) {
+ try {
+ lastBorderMouseDownObject = sender;
+ if (sender == PPTLSNextButtonBorder) {
+ PPTLSNextButtonFeedbackBorder.Opacity = 0.15;
+ } else if (sender == PPTRSNextButtonBorder) {
+ PPTRSNextButtonFeedbackBorder.Opacity = 0.15;
+ } else if (sender == PPTLBNextButtonBorder)
+ {
+ PPTLBNextButtonFeedbackBorder.Opacity = 0.15;
+ }
+ else if (sender == PPTRBNextButtonBorder)
+ {
+ PPTRBNextButtonFeedbackBorder.Opacity = 0.15;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void GridPPTControlNext_MouseLeave(object sender, MouseEventArgs e)
+ {
+ try {
+ lastBorderMouseDownObject = null;
+ if (sender == PPTLSNextButtonBorder) {
+ PPTLSNextButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTRSNextButtonBorder) {
+ PPTRSNextButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTLBNextButtonBorder)
+ {
+ PPTLBNextButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBNextButtonBorder)
+ {
+ PPTRBNextButtonFeedbackBorder.Opacity = 0;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void GridPPTControlNext_MouseUp(object sender, MouseButtonEventArgs e) {
+ try {
+ if (lastBorderMouseDownObject != sender) return;
+ if (sender == PPTLSNextButtonBorder) {
+ PPTLSNextButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTRSNextButtonBorder) {
+ PPTRSNextButtonFeedbackBorder.Opacity = 0;
+ } else if (sender == PPTLBNextButtonBorder)
+ {
+ PPTLBNextButtonFeedbackBorder.Opacity = 0;
+ }
+ else if (sender == PPTRBNextButtonBorder)
+ {
+ PPTRBNextButtonFeedbackBorder.Opacity = 0;
+ }
+ BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void ImagePPTControlEnd_MouseUp(object sender, MouseButtonEventArgs e) {
+ try {
+ BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null);
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_PageListView.cs b/Ink Canvas/MainWindow_cs/MW_PageListView.cs
new file mode 100644
index 00000000..81acfb62
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_PageListView.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Forms;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using Ink_Canvas.Helpers;
+
+namespace Ink_Canvas
+{
+ public partial class MainWindow : Window
+ {
+ private class PageListViewItem
+ {
+ public int Index { get; set; }
+ public StrokeCollection Strokes { get; set; }
+ }
+
+ ObservableCollection blackBoardSidePageListViewObservableCollection = new ObservableCollection();
+
+ ///
+ /// 刷新白板的缩略图页面列表。
+ ///
+ private void RefreshBlackBoardSidePageListView()
+ {
+ if (blackBoardSidePageListViewObservableCollection.Count == WhiteboardTotalCount) {
+ foreach (int index in Enumerable.Range(1, WhiteboardTotalCount))
+ {
+ var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
+ st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
+ var pitem = new PageListViewItem()
+ {
+ Index = index,
+ Strokes = st,
+ };
+ blackBoardSidePageListViewObservableCollection[index-1] = pitem;
+ }
+ } else {
+ blackBoardSidePageListViewObservableCollection.Clear();
+ foreach (int index in Enumerable.Range(1, WhiteboardTotalCount)) {
+ var st = ApplyHistoriesToNewStrokeCollection(TimeMachineHistories[index]);
+ st.Clip(new Rect(0,0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
+ var pitem = new PageListViewItem()
+ {
+ Index = index,
+ Strokes = st,
+ };
+ blackBoardSidePageListViewObservableCollection.Add(pitem);
+ }
+ }
+
+ var _st = inkCanvas.Strokes.Clone();
+ _st.Clip(new Rect(0, 0, (int)inkCanvas.ActualWidth, (int)inkCanvas.ActualHeight));
+ var _pitem = new PageListViewItem()
+ {
+ Index = CurrentWhiteboardIndex,
+ Strokes = _st,
+ };
+ blackBoardSidePageListViewObservableCollection[CurrentWhiteboardIndex - 1] = _pitem;
+
+ BlackBoardLeftSidePageListView.SelectedIndex = CurrentWhiteboardIndex -1;
+ BlackBoardRightSidePageListView.SelectedIndex = CurrentWhiteboardIndex -1;
+ }
+
+ public static void ScrollViewToVerticalTop(FrameworkElement element, ScrollViewer scrollViewer)
+ {
+ var scrollViewerOffset = scrollViewer.VerticalOffset;
+ var point = new Point(0, scrollViewerOffset);
+ var tarPos = element.TransformToVisual(scrollViewer).Transform(point);
+ scrollViewer.ScrollToVerticalOffset(tarPos.Y);
+ }
+
+
+ private void BlackBoardLeftSidePageListView_OnMouseUp(object sender, MouseButtonEventArgs e) {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
+ var item = BlackBoardLeftSidePageListView.SelectedItem;
+ var index = BlackBoardLeftSidePageListView.SelectedIndex;
+ if (item != null)
+ {
+ SaveStrokes();
+ ClearStrokes(true);
+ CurrentWhiteboardIndex= index+1;
+ RestoreStrokes();
+ UpdateIndexInfoDisplay();
+ BlackBoardLeftSidePageListView.SelectedIndex = index;
+ }
+ }
+
+ private void BlackBoardRightSidePageListView_OnMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
+ var item = BlackBoardRightSidePageListView.SelectedItem;
+ var index = BlackBoardRightSidePageListView.SelectedIndex;
+ if (item != null)
+ {
+ SaveStrokes();
+ ClearStrokes(true);
+ CurrentWhiteboardIndex = index + 1;
+ RestoreStrokes();
+ UpdateIndexInfoDisplay();
+ BlackBoardRightSidePageListView.SelectedIndex = index;
+ }
+ }
+
+ }
+}
diff --git a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs
new file mode 100644
index 00000000..5980144b
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs
@@ -0,0 +1,88 @@
+using Ink_Canvas.Helpers;
+using Microsoft.Win32;
+using System;
+using System.IO;
+using System.Windows;
+using System.Windows.Ink;
+using System.Windows.Input;
+using File = System.IO.File;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private void SymbolIconSaveStrokes_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender || inkCanvas.Visibility != Visibility.Visible) return;
+
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ GridNotifications.Visibility = Visibility.Collapsed;
+
+ SaveInkCanvasStrokes(true, true);
+ }
+
+ private void SaveInkCanvasStrokes(bool newNotice = true, bool saveByUser = false) {
+ try {
+ var savePath = Settings.Automation.AutoSavedStrokesLocation
+ + (saveByUser ? @"\User Saved - " : @"\Auto Saved - ")
+ + (currentMode == 0 ? "Annotation Strokes" : "BlackBoard Strokes");
+ if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);
+ string savePathWithName;
+ if (currentMode != 0) // 黑板模式下
+ savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + " Page-" +
+ CurrentWhiteboardIndex + " StrokesCount-" + inkCanvas.Strokes.Count + ".icstk";
+ else
+ //savePathWithName = savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".icstk";
+ savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + ".icstk";
+ var fs = new FileStream(savePathWithName, FileMode.Create);
+ inkCanvas.Strokes.Save(fs);
+ if (newNotice) ShowNotification("墨迹成功保存至 " + savePathWithName);
+ }
+ catch (Exception ex) {
+ ShowNotification("墨迹保存失败");
+ LogHelper.WriteLogToFile("墨迹保存失败 | " + ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+
+ private void SymbolIconOpenStrokes_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+
+ var openFileDialog = new OpenFileDialog();
+ openFileDialog.InitialDirectory = Settings.Automation.AutoSavedStrokesLocation;
+ openFileDialog.Title = "打开墨迹文件";
+ openFileDialog.Filter = "Ink Canvas Strokes File (*.icstk)|*.icstk";
+ if (openFileDialog.ShowDialog() != true) return;
+ LogHelper.WriteLogToFile($"Strokes Insert: Name: {openFileDialog.FileName}",
+ LogHelper.LogType.Event);
+ try {
+ var fileStreamHasNoStroke = false;
+ using (var fs = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read)) {
+ var strokes = new StrokeCollection(fs);
+ fileStreamHasNoStroke = strokes.Count == 0;
+ if (!fileStreamHasNoStroke) {
+ ClearStrokes(true);
+ timeMachine.ClearStrokeHistory();
+ inkCanvas.Strokes.Add(strokes);
+ LogHelper.NewLog($"Strokes Insert: Strokes Count: {inkCanvas.Strokes.Count.ToString()}");
+ }
+ }
+
+ if (fileStreamHasNoStroke)
+ using (var ms = new MemoryStream(File.ReadAllBytes(openFileDialog.FileName))) {
+ ms.Seek(0, SeekOrigin.Begin);
+ var strokes = new StrokeCollection(ms);
+ ClearStrokes(true);
+ timeMachine.ClearStrokeHistory();
+ inkCanvas.Strokes.Add(strokes);
+ LogHelper.NewLog($"Strokes Insert (2): Strokes Count: {strokes.Count.ToString()}");
+ }
+
+ if (inkCanvas.Visibility != Visibility.Visible) SymbolIconCursor_Click(sender, null);
+ }
+ catch {
+ ShowNotification("墨迹打开失败");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs
new file mode 100644
index 00000000..d9896065
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Windows;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private void SaveScreenShot(bool isHideNotification, string fileName = null) {
+ var savePath = Settings.Automation.IsSaveScreenshotsInDateFolders
+ ? GetDateFolderPath(fileName)
+ : GetDefaultFolderPath();
+
+ CaptureAndSaveScreenshot(savePath, isHideNotification);
+
+ if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
+ SaveInkCanvasStrokes(false, false);
+ }
+
+ private void SaveScreenShotToDesktop() {
+ var desktopPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
+ $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
+
+ CaptureAndSaveScreenshot(desktopPath, false);
+
+ if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
+ SaveInkCanvasStrokes(false, false);
+ }
+
+ // 提取公共的截图和保存逻辑
+ private void CaptureAndSaveScreenshot(string savePath, bool isHideNotification) {
+ var rc = System.Windows.Forms.SystemInformation.VirtualScreen;
+
+ using (var bitmap = new System.Drawing.Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb))
+ using (var memoryGraphics = System.Drawing.Graphics.FromImage(bitmap)) {
+ memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, System.Drawing.CopyPixelOperation.SourceCopy);
+
+ // 确保目录存在
+ var directory = Path.GetDirectoryName(savePath);
+ if (!Directory.Exists(directory)) {
+ Directory.CreateDirectory(directory);
+ }
+
+ bitmap.Save(savePath, ImageFormat.Png);
+ }
+
+ if (!isHideNotification) {
+ ShowNotification($"截图成功保存至 {savePath}");
+ }
+ }
+
+ // 获取日期文件夹路径
+ private string GetDateFolderPath(string fileName) {
+ if (string.IsNullOrWhiteSpace(fileName)) {
+ fileName = DateTime.Now.ToString("HH-mm-ss");
+ }
+
+ var basePath = Settings.Automation.AutoSavedStrokesLocation;
+ var dateFolder = DateTime.Now.ToString("yyyyMMdd");
+
+ return Path.Combine(
+ basePath,
+ "Auto Saved - Screenshots",
+ dateFolder,
+ $"{fileName}.png");
+ }
+
+ // 获取默认文件夹路径
+ private string GetDefaultFolderPath() {
+ var basePath = Settings.Automation.AutoSavedStrokesLocation;
+ var screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots");
+
+ if (!Directory.Exists(screenshotsFolder)) {
+ Directory.CreateDirectory(screenshotsFolder);
+ }
+
+ return Path.Combine(
+ screenshotsFolder,
+ $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs
new file mode 100644
index 00000000..b5cc24bd
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs
@@ -0,0 +1,408 @@
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using Point = System.Windows.Point;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region Floating Control
+
+ private object lastBorderMouseDownObject;
+
+ private void Border_MouseDown(object sender, MouseButtonEventArgs e) {
+ lastBorderMouseDownObject = sender;
+ }
+
+ private bool isStrokeSelectionCloneOn = false;
+
+ private void BorderStrokeSelectionClone_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ if (isStrokeSelectionCloneOn) {
+ BorderStrokeSelectionClone.Background = Brushes.Transparent;
+
+ isStrokeSelectionCloneOn = false;
+ }
+ else {
+ BorderStrokeSelectionClone.Background = new SolidColorBrush(StringToColor("#FF1ED760"));
+
+ isStrokeSelectionCloneOn = true;
+ }
+ }
+
+ private void BorderStrokeSelectionCloneToNewBoard_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ var strokes = inkCanvas.GetSelectedStrokes();
+ inkCanvas.Select(new StrokeCollection());
+ strokes = strokes.Clone();
+ BtnWhiteBoardAdd_Click(null, null);
+ inkCanvas.Strokes.Add(strokes);
+ }
+
+ private void BorderStrokeSelectionDelete_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+ SymbolIconDelete_MouseUp(sender, e);
+ }
+
+ private void GridPenWidthDecrease_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+ ChangeStrokeThickness(0.8);
+ }
+
+ private void GridPenWidthIncrease_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+ ChangeStrokeThickness(1.25);
+ }
+
+ private void ChangeStrokeThickness(double multipler) {
+ foreach (var stroke in inkCanvas.GetSelectedStrokes()) {
+ var newWidth = stroke.DrawingAttributes.Width * multipler;
+ var newHeight = stroke.DrawingAttributes.Height * multipler;
+ if (!(newWidth >= DrawingAttributes.MinWidth) || !(newWidth <= DrawingAttributes.MaxWidth)
+ || !(newHeight >= DrawingAttributes.MinHeight) ||
+ !(newHeight <= DrawingAttributes.MaxHeight)) continue;
+ stroke.DrawingAttributes.Width = newWidth;
+ stroke.DrawingAttributes.Height = newHeight;
+ }
+ if (DrawingAttributesHistory.Count > 0)
+ {
+
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ }
+
+ private void GridPenWidthRestore_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ foreach (var stroke in inkCanvas.GetSelectedStrokes()) {
+ stroke.DrawingAttributes.Width = inkCanvas.DefaultDrawingAttributes.Width;
+ stroke.DrawingAttributes.Height = inkCanvas.DefaultDrawingAttributes.Height;
+ }
+ }
+
+ private void ImageFlipHorizontal_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ var m = new Matrix();
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
+ inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ // Update matrix to reflect translation/rotation
+ m.ScaleAt(-1, 1, center.X, center.Y); // 缩放
+
+ var targetStrokes = inkCanvas.GetSelectedStrokes();
+ foreach (var stroke in targetStrokes) stroke.Transform(m, false);
+
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ //var collecion = new StrokeCollection();
+ //foreach (var item in DrawingAttributesHistory)
+ //{
+ // collecion.Add(item.Key);
+ //}
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+
+ //updateBorderStrokeSelectionControlLocation();
+ }
+
+ private void ImageFlipVertical_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ var m = new Matrix();
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
+ inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ // Update matrix to reflect translation/rotation
+ m.ScaleAt(1, -1, center.X, center.Y); // 缩放
+
+ var targetStrokes = inkCanvas.GetSelectedStrokes();
+ foreach (var stroke in targetStrokes) stroke.Transform(m, false);
+
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ }
+
+ private void ImageRotate45_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ var m = new Matrix();
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
+ inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ // Update matrix to reflect translation/rotation
+ m.RotateAt(45, center.X, center.Y); // 旋转
+
+ var targetStrokes = inkCanvas.GetSelectedStrokes();
+ foreach (var stroke in targetStrokes) stroke.Transform(m, false);
+
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ }
+
+ private void ImageRotate90_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ var m = new Matrix();
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
+ inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ // Update matrix to reflect translation/rotation
+ m.RotateAt(90, center.X, center.Y); // 旋转
+
+ var targetStrokes = inkCanvas.GetSelectedStrokes();
+ foreach (var stroke in targetStrokes) stroke.Transform(m, false);
+
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ var collecion = new StrokeCollection();
+ foreach (var item in DrawingAttributesHistory)
+ {
+ collecion.Add(item.Key);
+ }
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ }
+
+ #endregion
+
+ private bool isGridInkCanvasSelectionCoverMouseDown = false;
+ private StrokeCollection StrokesSelectionClone = new StrokeCollection();
+
+ private void GridInkCanvasSelectionCover_MouseDown(object sender, MouseButtonEventArgs e) {
+ isGridInkCanvasSelectionCoverMouseDown = true;
+ }
+
+ private void GridInkCanvasSelectionCover_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (!isGridInkCanvasSelectionCoverMouseDown) return;
+ isGridInkCanvasSelectionCoverMouseDown = false;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ }
+
+ private void BtnSelect_Click(object sender, RoutedEventArgs e) {
+ forceEraser = true;
+ drawingShapeMode = 0;
+ inkCanvas.IsManipulationEnabled = false;
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.Select) {
+ if (inkCanvas.GetSelectedStrokes().Count == inkCanvas.Strokes.Count) {
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Select;
+ }
+ else {
+ var selectedStrokes = new StrokeCollection();
+ foreach (var stroke in inkCanvas.Strokes)
+ if (stroke.GetBounds().Width > 0 && stroke.GetBounds().Height > 0)
+ selectedStrokes.Add(stroke);
+ inkCanvas.Select(selectedStrokes);
+ }
+ }
+ else {
+ inkCanvas.EditingMode = InkCanvasEditingMode.Select;
+ }
+ }
+
+ private double BorderStrokeSelectionControlWidth = 490.0;
+ private double BorderStrokeSelectionControlHeight = 80.0;
+ private bool isProgramChangeStrokeSelection = false;
+
+ private void inkCanvas_SelectionChanged(object sender, EventArgs e) {
+ if (isProgramChangeStrokeSelection) return;
+ if (inkCanvas.GetSelectedStrokes().Count == 0) {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ }
+ else {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
+ BorderStrokeSelectionClone.Background = Brushes.Transparent;
+ isStrokeSelectionCloneOn = false;
+ updateBorderStrokeSelectionControlLocation();
+ }
+ }
+
+ private void updateBorderStrokeSelectionControlLocation() {
+ var borderLeft = (inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Right -
+ BorderStrokeSelectionControlWidth) / 2;
+ var borderTop = inkCanvas.GetSelectionBounds().Bottom + 1;
+ if (borderLeft < 0) borderLeft = 0;
+ if (borderTop < 0) borderTop = 0;
+ if (Width - borderLeft < BorderStrokeSelectionControlWidth || double.IsNaN(borderLeft))
+ borderLeft = Width - BorderStrokeSelectionControlWidth;
+ if (Height - borderTop < BorderStrokeSelectionControlHeight || double.IsNaN(borderTop))
+ borderTop = Height - BorderStrokeSelectionControlHeight;
+
+ if (borderTop > 60) borderTop -= 60;
+ BorderStrokeSelectionControl.Margin = new Thickness(borderLeft, borderTop, 0, 0);
+ }
+
+ private void GridInkCanvasSelectionCover_ManipulationStarting(object sender, ManipulationStartingEventArgs e) {
+ e.Mode = ManipulationModes.All;
+ }
+
+ private void GridInkCanvasSelectionCover_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
+ if (StrokeManipulationHistory?.Count > 0)
+ {
+ timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
+ foreach (var item in StrokeManipulationHistory)
+ {
+ StrokeInitialHistory[item.Key] = item.Value.Item2;
+ }
+ StrokeManipulationHistory = null;
+ }
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+ }
+
+ private void GridInkCanvasSelectionCover_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
+ try {
+ if (dec.Count >= 1) {
+ var md = e.DeltaManipulation;
+ var trans = md.Translation; // 获得位移矢量
+ var rotate = md.Rotation; // 获得旋转角度
+ var scale = md.Scale; // 获得缩放倍数
+
+ var m = new Matrix();
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = new Point(inkCanvas.GetSelectionBounds().Left + inkCanvas.GetSelectionBounds().Width / 2,
+ inkCanvas.GetSelectionBounds().Top + inkCanvas.GetSelectionBounds().Height / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ // Update matrix to reflect translation/rotation
+ m.Translate(trans.X, trans.Y); // 移动
+ m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
+
+ var strokes = inkCanvas.GetSelectedStrokes();
+ if (StrokesSelectionClone.Count != 0)
+ strokes = StrokesSelectionClone;
+ else if (Settings.Gesture.IsEnableTwoFingerRotationOnSelection)
+ m.RotateAt(rotate, center.X, center.Y); // 旋转
+ foreach (var stroke in strokes) {
+ stroke.Transform(m, false);
+
+ try {
+ stroke.DrawingAttributes.Width *= md.Scale.X;
+ stroke.DrawingAttributes.Height *= md.Scale.Y;
+ }
+ catch { }
+ }
+
+ updateBorderStrokeSelectionControlLocation();
+ }
+ }
+ catch { }
+ }
+
+ private void GridInkCanvasSelectionCover_TouchDown(object sender, TouchEventArgs e) { }
+
+ private void GridInkCanvasSelectionCover_TouchUp(object sender, TouchEventArgs e) { }
+
+ private Point lastTouchPointOnGridInkCanvasCover = new Point(0, 0);
+
+ private void GridInkCanvasSelectionCover_PreviewTouchDown(object sender, TouchEventArgs e) {
+ dec.Add(e.TouchDevice.Id);
+ //设备1个的时候,记录中心点
+ if (dec.Count == 1) {
+ var touchPoint = e.GetTouchPoint(null);
+ centerPoint = touchPoint.Position;
+ lastTouchPointOnGridInkCanvasCover = touchPoint.Position;
+
+ if (isStrokeSelectionCloneOn) {
+ var strokes = inkCanvas.GetSelectedStrokes();
+ isProgramChangeStrokeSelection = true;
+ inkCanvas.Select(new StrokeCollection());
+ StrokesSelectionClone = strokes.Clone();
+ inkCanvas.Select(strokes);
+ isProgramChangeStrokeSelection = false;
+ inkCanvas.Strokes.Add(StrokesSelectionClone);
+ }
+ }
+ }
+
+ private void GridInkCanvasSelectionCover_PreviewTouchUp(object sender, TouchEventArgs e) {
+ dec.Remove(e.TouchDevice.Id);
+ if (dec.Count >= 1) return;
+ isProgramChangeStrokeSelection = false;
+ if (lastTouchPointOnGridInkCanvasCover == e.GetTouchPoint(null).Position) {
+ if (!(lastTouchPointOnGridInkCanvasCover.X < inkCanvas.GetSelectionBounds().Left) &&
+ !(lastTouchPointOnGridInkCanvasCover.Y < inkCanvas.GetSelectionBounds().Top) &&
+ !(lastTouchPointOnGridInkCanvasCover.X > inkCanvas.GetSelectionBounds().Right) &&
+ !(lastTouchPointOnGridInkCanvasCover.Y > inkCanvas.GetSelectionBounds().Bottom)) return;
+ inkCanvas.Select(new StrokeCollection());
+ StrokesSelectionClone = new StrokeCollection();
+ }
+ else if (inkCanvas.GetSelectedStrokes().Count == 0) {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ StrokesSelectionClone = new StrokeCollection();
+ }
+ else {
+ GridInkCanvasSelectionCover.Visibility = Visibility.Visible;
+ StrokesSelectionClone = new StrokeCollection();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs
new file mode 100644
index 00000000..77cc8cc7
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs
@@ -0,0 +1,1704 @@
+using Ink_Canvas.Helpers;
+using Newtonsoft.Json;
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using File = System.IO.File;
+using System.Windows.Media;
+using System.Windows.Ink;
+using System.Windows.Media.Imaging;
+using System.Windows.Interop;
+using Hardcodet.Wpf.TaskbarNotification;
+using OSVersionExtension;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region Behavior
+
+ private void ToggleSwitchIsAutoUpdate_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Startup.IsAutoUpdate = ToggleSwitchIsAutoUpdate.IsOn;
+ ToggleSwitchIsAutoUpdateWithSilence.Visibility =
+ ToggleSwitchIsAutoUpdate.IsOn ? Visibility.Visible : Visibility.Collapsed;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsAutoUpdateWithSilence_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Startup.IsAutoUpdateWithSilence = ToggleSwitchIsAutoUpdateWithSilence.IsOn;
+ AutoUpdateTimePeriodBlock.Visibility =
+ Settings.Startup.IsAutoUpdateWithSilence ? Visibility.Visible : Visibility.Collapsed;
+ SaveSettingsToFile();
+ }
+
+ private void AutoUpdateWithSilenceStartTimeComboBox_SelectionChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Startup.AutoUpdateWithSilenceStartTime =
+ (string)AutoUpdateWithSilenceStartTimeComboBox.SelectedItem;
+ SaveSettingsToFile();
+ }
+
+ private void AutoUpdateWithSilenceEndTimeComboBox_SelectionChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Startup.AutoUpdateWithSilenceEndTime = (string)AutoUpdateWithSilenceEndTimeComboBox.SelectedItem;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchRunAtStartup_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ if (ToggleSwitchRunAtStartup.IsOn) {
+ StartAutomaticallyDel("InkCanvas");
+ StartAutomaticallyCreate("Ink Canvas Annotation");
+ } else {
+ StartAutomaticallyDel("InkCanvas");
+ StartAutomaticallyDel("Ink Canvas Annotation");
+ }
+ }
+
+ private void ToggleSwitchFoldAtStartup_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Startup.IsFoldAtStartup = ToggleSwitchFoldAtStartup.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchSupportPowerPoint_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+
+ Settings.PowerPointSettings.PowerPointSupport = ToggleSwitchSupportPowerPoint.IsOn;
+ SaveSettingsToFile();
+
+ if (Settings.PowerPointSettings.PowerPointSupport)
+ timerCheckPPT.Start();
+ else
+ timerCheckPPT.Stop();
+ }
+
+ private void ToggleSwitchShowCanvasAtNewSlideShow_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+
+ Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow = ToggleSwitchShowCanvasAtNewSlideShow.IsOn;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Startup
+
+ private void ToggleSwitchEnableNibMode_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ if (sender == ToggleSwitchEnableNibMode)
+ BoardToggleSwitchEnableNibMode.IsOn = ToggleSwitchEnableNibMode.IsOn;
+ else
+ ToggleSwitchEnableNibMode.IsOn = BoardToggleSwitchEnableNibMode.IsOn;
+ Settings.Startup.IsEnableNibMode = ToggleSwitchEnableNibMode.IsOn;
+
+ if (Settings.Startup.IsEnableNibMode)
+ BoundsWidth = Settings.Advanced.NibModeBoundsWidth;
+ else
+ BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Appearance
+
+ private void ToggleSwitchEnableDisPlayNibModeToggle_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.IsEnableDisPlayNibModeToggler = ToggleSwitchEnableDisPlayNibModeToggle.IsOn;
+ SaveSettingsToFile();
+ if (!ToggleSwitchEnableDisPlayNibModeToggle.IsOn) {
+ NibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
+ BoardNibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
+ } else {
+ NibModeSimpleStackPanel.Visibility = Visibility.Visible;
+ BoardNibModeSimpleStackPanel.Visibility = Visibility.Visible;
+ }
+ }
+
+ //private void ToggleSwitchIsColorfulViewboxFloatingBar_Toggled(object sender, RoutedEventArgs e) {
+ // if (!isLoaded) return;
+ // Settings.Appearance.IsColorfulViewboxFloatingBar = ToggleSwitchColorfulViewboxFloatingBar.IsOn;
+ // SaveSettingsToFile();
+ //}
+
+ private void ToggleSwitchEnableQuickPanel_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.IsShowQuickPanel = ToggleSwitchEnableQuickPanel.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ViewboxFloatingBarScaleTransformValueSlider_ValueChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.ViewboxFloatingBarScaleTransformValue =
+ ViewboxFloatingBarScaleTransformValueSlider.Value;
+ SaveSettingsToFile();
+ var val = ViewboxFloatingBarScaleTransformValueSlider.Value;
+ ViewboxFloatingBarScaleTransform.ScaleX =
+ val > 0.5 && val < 1.25 ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
+ ViewboxFloatingBarScaleTransform.ScaleY =
+ val > 0.5 && val < 1.25 ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
+ // auto align
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ ViewboxFloatingBarMarginAnimation(60);
+ else
+ ViewboxFloatingBarMarginAnimation(100, true);
+ }
+
+ private void ViewboxFloatingBarOpacityValueSlider_ValueChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.ViewboxFloatingBarOpacityValue = ViewboxFloatingBarOpacityValueSlider.Value;
+ SaveSettingsToFile();
+ ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue;
+ }
+
+ private void ViewboxFloatingBarOpacityInPPTValueSlider_ValueChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue = ViewboxFloatingBarOpacityInPPTValueSlider.Value;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTrayIcon_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.EnableTrayIcon = ToggleSwitchEnableTrayIcon.IsOn;
+ ICCTrayIconExampleImage.Visibility = Settings.Appearance.EnableTrayIcon ? Visibility.Visible : Visibility.Collapsed;
+ var _taskbar = (TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"];
+ _taskbar.Visibility = ToggleSwitchEnableTrayIcon.IsOn? Visibility.Visible : Visibility.Collapsed;
+ SaveSettingsToFile();
+ }
+
+ private void ComboBoxUnFoldBtnImg_SelectionChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.UnFoldButtonImageType = ComboBoxUnFoldBtnImg.SelectedIndex;
+ SaveSettingsToFile();
+ if (ComboBoxUnFoldBtnImg.SelectedIndex == 0) {
+ RightUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
+ RightUnFoldBtnImgChevron.Width = 14;
+ RightUnFoldBtnImgChevron.Height = 14;
+ RightUnFoldBtnImgChevron.RenderTransform = new RotateTransform(180);
+ LeftUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
+ LeftUnFoldBtnImgChevron.Width = 14;
+ LeftUnFoldBtnImgChevron.Height = 14;
+ LeftUnFoldBtnImgChevron.RenderTransform = null;
+ } else if (ComboBoxUnFoldBtnImg.SelectedIndex == 1) {
+ RightUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
+ RightUnFoldBtnImgChevron.Width = 18;
+ RightUnFoldBtnImgChevron.Height = 18;
+ RightUnFoldBtnImgChevron.RenderTransform = null;
+ LeftUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
+ LeftUnFoldBtnImgChevron.Width = 18;
+ LeftUnFoldBtnImgChevron.Height = 18;
+ LeftUnFoldBtnImgChevron.RenderTransform = null;
+ }
+ }
+
+ private void ComboBoxChickenSoupSource_SelectionChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.ChickenSoupSource = ComboBoxChickenSoupSource.SelectedIndex;
+ SaveSettingsToFile();
+ if (Settings.Appearance.ChickenSoupSource == 0) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.OSUPlayerYuLu.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.OSUPlayerYuLu[randChickenSoupIndex];
+ } else if (Settings.Appearance.ChickenSoupSource == 1) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.MingYanJingJu.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.MingYanJingJu[randChickenSoupIndex];
+ } else if (Settings.Appearance.ChickenSoupSource == 2) {
+ int randChickenSoupIndex = new Random().Next(ChickenSoup.GaoKaoPhrases.Length);
+ BlackBoardWaterMark.Text = ChickenSoup.GaoKaoPhrases[randChickenSoupIndex];
+ }
+ }
+
+ private void ToggleSwitchEnableViewboxBlackBoardScaleTransform_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.EnableViewboxBlackBoardScaleTransform =
+ ToggleSwitchEnableViewboxBlackBoardScaleTransform.IsOn;
+ SaveSettingsToFile();
+ LoadSettings();
+ }
+
+ public void ComboBoxFloatingBarImg_SelectionChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.FloatingBarImg = ComboBoxFloatingBarImg.SelectedIndex;
+ if (ComboBoxFloatingBarImg.SelectedIndex == 0) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(0.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 1) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/Icons-png/icc-transparent-dark-small.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(1.2);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 2) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandoujiyanhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 3) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanshounvhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 4) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanciya.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 5) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanneikuhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 6) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandogeyuanliangwo.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 7) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/tiebahuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1);
+ }
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTimeDisplayInWhiteboardMode_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.EnableTimeDisplayInWhiteboardMode = ToggleSwitchEnableTimeDisplayInWhiteboardMode.IsOn;
+ if (currentMode == 1) {
+ if (ToggleSwitchEnableTimeDisplayInWhiteboardMode.IsOn) {
+ WaterMarkTime.Visibility = Visibility.Visible;
+ WaterMarkDate.Visibility = Visibility.Visible;
+ } else {
+ WaterMarkTime.Visibility = Visibility.Collapsed;
+ WaterMarkDate.Visibility = Visibility.Collapsed;
+ }
+ }
+
+ SaveSettingsToFile();
+ LoadSettings();
+ }
+
+ private void ToggleSwitchEnableChickenSoupInWhiteboardMode_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Appearance.EnableChickenSoupInWhiteboardMode = ToggleSwitchEnableChickenSoupInWhiteboardMode.IsOn;
+ if (currentMode == 1) {
+ if (ToggleSwitchEnableTimeDisplayInWhiteboardMode.IsOn) {
+ BlackBoardWaterMark.Visibility = Visibility.Visible;
+ } else {
+ BlackBoardWaterMark.Visibility = Visibility.Collapsed;
+ }
+ }
+
+ SaveSettingsToFile();
+ LoadSettings();
+ }
+
+ //[Obsolete]
+ //private void ToggleSwitchShowButtonPPTNavigation_OnToggled(object sender, RoutedEventArgs e) {
+ // if (!isLoaded) return;
+ // Settings.PowerPointSettings.IsShowPPTNavigation = ToggleSwitchShowButtonPPTNavigation.IsOn;
+ // var vis = Settings.PowerPointSettings.IsShowPPTNavigation ? Visibility.Visible : Visibility.Collapsed;
+ // PPTLBPageButton.Visibility = vis;
+ // PPTRBPageButton.Visibility = vis;
+ // PPTLSPageButton.Visibility = vis;
+ // PPTRSPageButton.Visibility = vis;
+ // SaveSettingsToFile();
+ //}
+
+ //[Obsolete]
+ //private void ToggleSwitchShowBottomPPTNavigationPanel_OnToggled(object sender, RoutedEventArgs e) {
+ // if (!isLoaded) return;
+ // Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel = ToggleSwitchShowBottomPPTNavigationPanel.IsOn;
+ // if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible)
+ // //BottomViewboxPPTSidesControl.Visibility = Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel
+ // // ? Visibility.Visible
+ // // : Visibility.Collapsed;
+ // SaveSettingsToFile();
+ //}
+
+ //[Obsolete]
+ //private void ToggleSwitchShowSidePPTNavigationPanel_OnToggled(object sender, RoutedEventArgs e) {
+ // if (!isLoaded) return;
+ // Settings.PowerPointSettings.IsShowSidePPTNavigationPanel = ToggleSwitchShowSidePPTNavigationPanel.IsOn;
+ // if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
+ // LeftSidePanelForPPTNavigation.Visibility = Settings.PowerPointSettings.IsShowSidePPTNavigationPanel
+ // ? Visibility.Visible
+ // : Visibility.Collapsed;
+ // RightSidePanelForPPTNavigation.Visibility = Settings.PowerPointSettings.IsShowSidePPTNavigationPanel
+ // ? Visibility.Visible
+ // : Visibility.Collapsed;
+ // }
+
+ // SaveSettingsToFile();
+ //}
+
+ private void ToggleSwitchShowPPTButton_OnToggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.ShowPPTButton = ToggleSwitchShowPPTButton.IsOn;
+ SaveSettingsToFile();
+ UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void ToggleSwitchEnablePPTButtonPageClickable_OnToggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.EnablePPTButtonPageClickable = ToggleSwitchEnablePPTButtonPageClickable.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void CheckboxEnableLBPPTButton_IsCheckChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ char[] c = str.ToCharArray();
+ c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxEnableRBPPTButton_IsCheckChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ char[] c = str.ToCharArray();
+ c[1] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxEnableLSPPTButton_IsCheckChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ char[] c = str.ToCharArray();
+ c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxEnableRSPPTButton_IsCheckChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ char[] c = str.ToCharArray();
+ c[3] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTButtonsDisplayOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxSPPTDisplayPage_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxSPPTHalfOpacity_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[1] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxSPPTBlackBackground_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTSButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxBPPTDisplayPage_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[0] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxBPPTHalfOpacity_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[1] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void CheckboxBPPTBlackBackground_IsCheckChange(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ var str = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ char[] c = str.ToCharArray();
+ c[2] = (bool)((CheckBox)sender).IsChecked ? '2' : '1';
+ Settings.PowerPointSettings.PPTBButtonsOption = int.Parse(new string(c));
+ SaveSettingsToFile();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnStyleSettingsStatus();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTButtonLeftPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.PPTLSButtonPosition = (int)PPTButtonLeftPositionValueSlider.Value;
+ UpdatePPTBtnSlidersStatus();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ SliderDelayAction.DebounceAction(2000, null, SaveSettingsToFile);
+ UpdatePPTBtnPreview();
+ }
+
+ private void UpdatePPTBtnSlidersStatus() {
+ if (PPTButtonLeftPositionValueSlider.Value <= -500 || PPTButtonLeftPositionValueSlider.Value >= 500) {
+ if (PPTButtonLeftPositionValueSlider.Value >= 500) {
+ PPTBtnLSPlusBtn.IsEnabled = false;
+ PPTBtnLSPlusBtn.Opacity = 0.5;
+ PPTButtonLeftPositionValueSlider.Value = 500;
+ } else if (PPTButtonLeftPositionValueSlider.Value <= -500) {
+ PPTBtnLSMinusBtn.IsEnabled = false;
+ PPTBtnLSMinusBtn.Opacity = 0.5;
+ PPTButtonLeftPositionValueSlider.Value = -500;
+ }
+ }
+ else
+ {
+ PPTBtnLSPlusBtn.IsEnabled = true;
+ PPTBtnLSPlusBtn.Opacity = 1;
+ PPTBtnLSMinusBtn.IsEnabled = true;
+ PPTBtnLSMinusBtn.Opacity = 1;
+ }
+
+ if (PPTButtonRightPositionValueSlider.Value <= -500 || PPTButtonRightPositionValueSlider.Value >= 500)
+ {
+ if (PPTButtonRightPositionValueSlider.Value >= 500)
+ {
+ PPTBtnRSPlusBtn.IsEnabled = false;
+ PPTBtnRSPlusBtn.Opacity = 0.5;
+ PPTButtonRightPositionValueSlider.Value = 500;
+ }
+ else if (PPTButtonRightPositionValueSlider.Value <= -500)
+ {
+ PPTBtnRSMinusBtn.IsEnabled = false;
+ PPTBtnRSMinusBtn.Opacity = 0.5;
+ PPTButtonRightPositionValueSlider.Value = -500;
+ }
+ }
+ else
+ {
+ PPTBtnRSPlusBtn.IsEnabled = true;
+ PPTBtnRSPlusBtn.Opacity = 1;
+ PPTBtnRSMinusBtn.IsEnabled = true;
+ PPTBtnRSMinusBtn.Opacity = 1;
+ }
+ }
+
+ private void PPTBtnLSPlusBtn_Clicked(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ PPTButtonLeftPositionValueSlider.Value++;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTLSButtonPosition = (int)PPTButtonLeftPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnLSMinusBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonLeftPositionValueSlider.Value--;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTLSButtonPosition = (int)PPTButtonLeftPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnLSSyncBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonRightPositionValueSlider.Value = PPTButtonLeftPositionValueSlider.Value;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTRSButtonPosition = (int)PPTButtonLeftPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnLSResetBtn_Clicked(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ PPTButtonLeftPositionValueSlider.Value = 0;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTLSButtonPosition = 0;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnRSPlusBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonRightPositionValueSlider.Value++;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTRSButtonPosition = (int)PPTButtonRightPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnRSMinusBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonRightPositionValueSlider.Value--;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTRSButtonPosition = (int)PPTButtonRightPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnRSSyncBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonLeftPositionValueSlider.Value = PPTButtonRightPositionValueSlider.Value;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTLSButtonPosition = (int)PPTButtonRightPositionValueSlider.Value;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private void PPTBtnRSResetBtn_Clicked(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ PPTButtonRightPositionValueSlider.Value = 0;
+ UpdatePPTBtnSlidersStatus();
+ Settings.PowerPointSettings.PPTRSButtonPosition = 0;
+ SaveSettingsToFile();
+ UpdatePPTBtnPreview();
+ }
+
+ private DelayAction SliderDelayAction = new DelayAction();
+
+ private void PPTButtonRightPositionValueSlider_ValueChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.PPTRSButtonPosition = (int)PPTButtonRightPositionValueSlider.Value;
+ UpdatePPTBtnSlidersStatus();
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) UpdatePPTBtnDisplaySettingsStatus();
+ SliderDelayAction.DebounceAction(2000,null, SaveSettingsToFile);
+ UpdatePPTBtnPreview();
+ }
+
+ private void UpdatePPTBtnPreview() {
+ //new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
+ var bopt = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ char[] boptc = bopt.ToCharArray();
+ if (boptc[1] == '2') {
+ PPTBtnPreviewLB.Opacity = 0.5;
+ PPTBtnPreviewRB.Opacity = 0.5;
+ } else {
+ PPTBtnPreviewLB.Opacity = 1;
+ PPTBtnPreviewRB.Opacity = 1;
+ }
+
+ if (boptc[2] == '2') {
+ PPTBtnPreviewLB.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/bottombar-dark.png"));
+ PPTBtnPreviewRB.Source = new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/bottombar-dark.png"));
+ } else {
+ PPTBtnPreviewLB.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/bottombar-white.png"));
+ PPTBtnPreviewRB.Source = new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/bottombar-white.png"));
+ }
+
+ var sopt = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ char[] soptc = sopt.ToCharArray();
+ if (soptc[1] == '2')
+ {
+ PPTBtnPreviewLS.Opacity = 0.5;
+ PPTBtnPreviewRS.Opacity = 0.5;
+ }
+ else
+ {
+ PPTBtnPreviewLS.Opacity = 1;
+ PPTBtnPreviewRS.Opacity = 1;
+ }
+
+ if (soptc[2] == '2')
+ {
+ PPTBtnPreviewLS.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/sidebar-dark.png"));
+ PPTBtnPreviewRS.Source = new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/sidebar-dark.png"));
+ }
+ else
+ {
+ PPTBtnPreviewLS.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/sidebar-white.png"));
+ PPTBtnPreviewRS.Source = new BitmapImage(
+ new Uri("pack://application:,,,/Resources/PresentationExample/sidebar-white.png"));
+ }
+
+ var dopt = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ char[] doptc = dopt.ToCharArray();
+
+ if (Settings.PowerPointSettings.ShowPPTButton) {
+ PPTBtnPreviewLB.Visibility = doptc[0] == '2' ? Visibility.Visible : Visibility.Collapsed;
+ PPTBtnPreviewRB.Visibility = doptc[1] == '2' ? Visibility.Visible : Visibility.Collapsed;
+ PPTBtnPreviewLS.Visibility = doptc[2] == '2' ? Visibility.Visible : Visibility.Collapsed;
+ PPTBtnPreviewRS.Visibility = doptc[3] == '2' ? Visibility.Visible : Visibility.Collapsed;
+ } else {
+ PPTBtnPreviewLB.Visibility = Visibility.Collapsed;
+ PPTBtnPreviewRB.Visibility = Visibility.Collapsed;
+ PPTBtnPreviewLS.Visibility = Visibility.Collapsed;
+ PPTBtnPreviewRS.Visibility = Visibility.Collapsed;
+ }
+
+ PPTBtnPreviewRSTransform.Y = -(Settings.PowerPointSettings.PPTRSButtonPosition * 0.5);
+ PPTBtnPreviewLSTransform.Y = -(Settings.PowerPointSettings.PPTLSButtonPosition * 0.5);
+ }
+
+ private void ToggleSwitchShowCursor_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+
+ Settings.Canvas.IsShowCursor = ToggleSwitchShowCursor.IsOn;
+ inkCanvas_EditingModeChanged(inkCanvas, null);
+
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Canvas
+
+ private void ComboBoxPenStyle_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (!isLoaded) return;
+ if (sender == ComboBoxPenStyle) {
+ Settings.Canvas.InkStyle = ComboBoxPenStyle.SelectedIndex;
+ BoardComboBoxPenStyle.SelectedIndex = ComboBoxPenStyle.SelectedIndex;
+ } else {
+ Settings.Canvas.InkStyle = BoardComboBoxPenStyle.SelectedIndex;
+ ComboBoxPenStyle.SelectedIndex = BoardComboBoxPenStyle.SelectedIndex;
+ }
+
+ SaveSettingsToFile();
+ }
+
+ private void ComboBoxEraserSize_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.EraserSize = ComboBoxEraserSize.SelectedIndex;
+ SaveSettingsToFile();
+ }
+
+ private void ComboBoxEraserSizeFloatingBar_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (!isLoaded) return;
+
+ ComboBox s = (ComboBox)sender;
+ Settings.Canvas.EraserSize = s.SelectedIndex;
+ if (s == ComboBoxEraserSizeFloatingBar) {
+ BoardComboBoxEraserSize.SelectedIndex = s.SelectedIndex;
+ ComboBoxEraserSize.SelectedIndex = s.SelectedIndex;
+ } else if (s == BoardComboBoxEraserSize) {
+ ComboBoxEraserSizeFloatingBar.SelectedIndex = s.SelectedIndex;
+ ComboBoxEraserSize.SelectedIndex = s.SelectedIndex;
+ }
+ if (Settings.Canvas.EraserShapeType == 0) {
+ double k = 1;
+ switch (s.SelectedIndex) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
+ } else if (Settings.Canvas.EraserShapeType == 1) {
+ double k = 1;
+ switch (s.SelectedIndex) {
+ case 0:
+ k = 0.7;
+ break;
+ case 1:
+ k = 0.9;
+ break;
+ case 3:
+ k = 1.2;
+ break;
+ case 4:
+ k = 1.6;
+ break;
+ }
+
+ inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
+ }
+
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ SaveSettingsToFile();
+ }
+
+ private void SwitchToCircleEraser(object sender, MouseButtonEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.EraserShapeType = 0;
+ SaveSettingsToFile();
+ CheckEraserTypeTab();
+ double k = 1;
+ switch (ComboBoxEraserSizeFloatingBar.SelectedIndex) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ }
+
+ private void SwitchToRectangleEraser(object sender, MouseButtonEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.EraserShapeType = 1;
+ SaveSettingsToFile();
+ CheckEraserTypeTab();
+ double k = 1;
+ switch (ComboBoxEraserSizeFloatingBar.SelectedIndex) {
+ case 0:
+ k = 0.7;
+ break;
+ case 1:
+ k = 0.9;
+ break;
+ case 3:
+ k = 1.2;
+ break;
+ case 4:
+ k = 1.6;
+ break;
+ }
+
+ inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ }
+
+
+ private void InkWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value;
+ if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value;
+ drawingAttributes.Height = ((Slider)sender).Value / 2;
+ drawingAttributes.Width = ((Slider)sender).Value / 2;
+ Settings.Canvas.InkWidth = ((Slider)sender).Value / 2;
+ SaveSettingsToFile();
+ }
+
+ private void HighlighterWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ // if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value;
+ // if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value;
+ drawingAttributes.Height = ((Slider)sender).Value;
+ drawingAttributes.Width = ((Slider)sender).Value / 2;
+ Settings.Canvas.HighlighterWidth = ((Slider)sender).Value;
+ SaveSettingsToFile();
+ }
+
+ private void InkAlphaSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ // if (sender == BoardInkWidthSlider) InkWidthSlider.Value = ((Slider)sender).Value;
+ // if (sender == InkWidthSlider) BoardInkWidthSlider.Value = ((Slider)sender).Value;
+ var NowR = drawingAttributes.Color.R;
+ var NowG = drawingAttributes.Color.G;
+ var NowB = drawingAttributes.Color.B;
+ // Trace.WriteLine(BitConverter.GetBytes(((Slider)sender).Value));
+ drawingAttributes.Color = Color.FromArgb((byte)((Slider)sender).Value, NowR, NowG, NowB);
+ // drawingAttributes.Width = ((Slider)sender).Value / 2;
+ // Settings.Canvas.InkAlpha = ((Slider)sender).Value;
+ // SaveSettingsToFile();
+ }
+
+ private void ComboBoxHyperbolaAsymptoteOption_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.HyperbolaAsymptoteOption =
+ (OptionalOperation)ComboBoxHyperbolaAsymptoteOption.SelectedIndex;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Automation
+
+ private void StartOrStoptimerCheckAutoFold() {
+ if (Settings.Automation.IsEnableAutoFold)
+ timerCheckAutoFold.Start();
+ else
+ timerCheckAutoFold.Stop();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiNote_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiNote = ToggleSwitchAutoFoldInEasiNote.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiNoteIgnoreDesktopAnno_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno =
+ ToggleSwitchAutoFoldInEasiNoteIgnoreDesktopAnno.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiCamera_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiCamera = ToggleSwitchAutoFoldInEasiCamera.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiNote3_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiNote3 = ToggleSwitchAutoFoldInEasiNote3.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiNote3C_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiNote3C = ToggleSwitchAutoFoldInEasiNote3C.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInEasiNote5C_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInEasiNote5C = ToggleSwitchAutoFoldInEasiNote5C.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInSeewoPincoTeacher_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInSeewoPincoTeacher = ToggleSwitchAutoFoldInSeewoPincoTeacher.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInHiteTouchPro_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInHiteTouchPro = ToggleSwitchAutoFoldInHiteTouchPro.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInHiteLightBoard_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInHiteLightBoard = ToggleSwitchAutoFoldInHiteLightBoard.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInHiteCamera_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInHiteCamera = ToggleSwitchAutoFoldInHiteCamera.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInWxBoardMain_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInWxBoardMain = ToggleSwitchAutoFoldInWxBoardMain.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInOldZyBoard_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInOldZyBoard = ToggleSwitchAutoFoldInOldZyBoard.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInMSWhiteboard_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInMSWhiteboard = ToggleSwitchAutoFoldInMSWhiteboard.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInAdmoxWhiteboard_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInAdmoxWhiteboard = ToggleSwitchAutoFoldInAdmoxWhiteboard.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInAdmoxBooth_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInAdmoxBooth = ToggleSwitchAutoFoldInAdmoxBooth.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInQPoint_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInQPoint = ToggleSwitchAutoFoldInQPoint.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInYiYunVisualPresenter_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInYiYunVisualPresenter = ToggleSwitchAutoFoldInYiYunVisualPresenter.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInMaxHubWhiteboard_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInMaxHubWhiteboard = ToggleSwitchAutoFoldInMaxHubWhiteboard.IsOn;
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoFoldInPPTSlideShow_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoFoldInPPTSlideShow = ToggleSwitchAutoFoldInPPTSlideShow.IsOn;
+ if (Settings.Automation.IsAutoFoldInPPTSlideShow)
+ {
+ SettingsPPTInkingAndAutoFoldExplictBorder.Visibility = Visibility.Visible;
+ SettingsShowCanvasAtNewSlideShowStackPanel.Opacity = 0.5;
+ SettingsShowCanvasAtNewSlideShowStackPanel.IsHitTestVisible = false;
+ } else {
+ SettingsPPTInkingAndAutoFoldExplictBorder.Visibility = Visibility.Collapsed;
+ SettingsShowCanvasAtNewSlideShowStackPanel.Opacity = 1;
+ SettingsShowCanvasAtNewSlideShowStackPanel.IsHitTestVisible = true;
+ }
+ SaveSettingsToFile();
+ StartOrStoptimerCheckAutoFold();
+ }
+
+ private void ToggleSwitchAutoKillPptService_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillPptService = ToggleSwitchAutoKillPptService.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 ToggleSwitchAutoKillEasiNote_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillEasiNote = ToggleSwitchAutoKillEasiNote.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 ToggleSwitchAutoKillHiteAnnotation_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillHiteAnnotation = ToggleSwitchAutoKillHiteAnnotation.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 ToggleSwitchAutoKillVComYouJiao_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillVComYouJiao = ToggleSwitchAutoKillVComYouJiao.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 ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation.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 ToggleSwitchAutoKillInkCanvas_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillInkCanvas = ToggleSwitchAutoKillInkCanvas.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 ToggleSwitchAutoKillICA_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoKillICA = ToggleSwitchAutoKillICA.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;
+ Settings.Automation.IsSaveScreenshotsInDateFolders = ToggleSwitchSaveScreenshotsInDateFolders.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoSaveStrokesAtScreenshot_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoSaveStrokesAtScreenshot = ToggleSwitchAutoSaveStrokesAtScreenshot.IsOn;
+ ToggleSwitchAutoSaveStrokesAtClear.Header =
+ ToggleSwitchAutoSaveStrokesAtScreenshot.IsOn ? "清屏时自动截图并保存墨迹" : "清屏时自动截图";
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoSaveStrokesAtClear_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.IsAutoSaveStrokesAtClear = ToggleSwitchAutoSaveStrokesAtClear.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchHideStrokeWhenSelecting_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.HideStrokeWhenSelecting = ToggleSwitchHideStrokeWhenSelecting.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchClearCanvasAndClearTimeMachine_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Canvas.ClearCanvasAndClearTimeMachine = ToggleSwitchClearCanvasAndClearTimeMachine.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchFitToCurve_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ drawingAttributes.FitToCurve = ToggleSwitchFitToCurve.IsOn;
+ Settings.Canvas.FitToCurve = ToggleSwitchFitToCurve.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoSaveStrokesInPowerPoint_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = ToggleSwitchAutoSaveStrokesInPowerPoint.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchNotifyPreviousPage_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsNotifyPreviousPage = ToggleSwitchNotifyPreviousPage.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchNotifyHiddenPage_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsNotifyHiddenPage = ToggleSwitchNotifyHiddenPage.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchNotifyAutoPlayPresentation_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsNotifyAutoPlayPresentation = ToggleSwitchNotifyAutoPlayPresentation.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void SideControlMinimumAutomationSlider_ValueChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.MinimumAutomationStrokeNumber = (int)SideControlMinimumAutomationSlider.Value;
+ SaveSettingsToFile();
+ }
+
+ private void AutoSavedStrokesLocationTextBox_TextChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.AutoSavedStrokesLocation = AutoSavedStrokesLocation.Text;
+ SaveSettingsToFile();
+ }
+
+ private void AutoSavedStrokesLocationButton_Click(object sender, RoutedEventArgs e) {
+ var folderBrowser = new System.Windows.Forms.FolderBrowserDialog();
+ folderBrowser.ShowDialog();
+ if (folderBrowser.SelectedPath.Length > 0) AutoSavedStrokesLocation.Text = folderBrowser.SelectedPath;
+ }
+
+ private void SetAutoSavedStrokesLocationToDiskDButton_Click(object sender, RoutedEventArgs e) {
+ AutoSavedStrokesLocation.Text = @"D:\Ink Canvas";
+ }
+
+ private void SetAutoSavedStrokesLocationToDocumentFolderButton_Click(object sender, RoutedEventArgs e) {
+ AutoSavedStrokesLocation.Text =
+ Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Ink Canvas";
+ }
+
+ private void ToggleSwitchAutoDelSavedFiles_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.AutoDelSavedFiles = ToggleSwitchAutoDelSavedFiles.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void
+ ComboBoxAutoDelSavedFilesDaysThreshold_SelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Automation.AutoDelSavedFilesDaysThreshold =
+ int.Parse(((ComboBoxItem)ComboBoxAutoDelSavedFilesDaysThreshold.SelectedItem).Content.ToString());
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoSaveScreenShotInPowerPoint_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint =
+ ToggleSwitchAutoSaveScreenShotInPowerPoint.IsOn;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Gesture
+
+ private void ToggleSwitchEnableFingerGestureSlideShowControl_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl =
+ ToggleSwitchEnableFingerGestureSlideShowControl.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchAutoSwitchTwoFingerGesture_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Gesture.AutoSwitchTwoFingerGesture = ToggleSwitchAutoSwitchTwoFingerGesture.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTwoFingerZoom_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ if (sender == ToggleSwitchEnableTwoFingerZoom)
+ BoardToggleSwitchEnableTwoFingerZoom.IsOn = ToggleSwitchEnableTwoFingerZoom.IsOn;
+ else
+ ToggleSwitchEnableTwoFingerZoom.IsOn = BoardToggleSwitchEnableTwoFingerZoom.IsOn;
+ Settings.Gesture.IsEnableTwoFingerZoom = ToggleSwitchEnableTwoFingerZoom.IsOn;
+ CheckEnableTwoFingerGestureBtnColorPrompt();
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableMultiTouchMode_Toggled(object sender, RoutedEventArgs e) {
+ //if (!isLoaded) return;
+ if (sender == ToggleSwitchEnableMultiTouchMode)
+ BoardToggleSwitchEnableMultiTouchMode.IsOn = ToggleSwitchEnableMultiTouchMode.IsOn;
+ else
+ ToggleSwitchEnableMultiTouchMode.IsOn = BoardToggleSwitchEnableMultiTouchMode.IsOn;
+ if (ToggleSwitchEnableMultiTouchMode.IsOn) {
+ if (!isInMultiTouchMode) {
+ inkCanvas.StylusDown += MainWindow_StylusDown;
+ inkCanvas.StylusMove += MainWindow_StylusMove;
+ inkCanvas.StylusUp += MainWindow_StylusUp;
+ inkCanvas.TouchDown += MainWindow_TouchDown;
+ inkCanvas.TouchDown -= Main_Grid_TouchDown;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.Children.Clear();
+ isInMultiTouchMode = true;
+ }
+ } else {
+ if (isInMultiTouchMode) {
+ inkCanvas.StylusDown -= MainWindow_StylusDown;
+ inkCanvas.StylusMove -= MainWindow_StylusMove;
+ inkCanvas.StylusUp -= MainWindow_StylusUp;
+ inkCanvas.TouchDown -= MainWindow_TouchDown;
+ inkCanvas.TouchDown += Main_Grid_TouchDown;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.Children.Clear();
+ isInMultiTouchMode = false;
+ }
+ }
+
+ Settings.Gesture.IsEnableMultiTouchMode = ToggleSwitchEnableMultiTouchMode.IsOn;
+ CheckEnableTwoFingerGestureBtnColorPrompt();
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTwoFingerTranslate_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ if (sender == ToggleSwitchEnableTwoFingerTranslate)
+ BoardToggleSwitchEnableTwoFingerTranslate.IsOn = ToggleSwitchEnableTwoFingerTranslate.IsOn;
+ else
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = BoardToggleSwitchEnableTwoFingerTranslate.IsOn;
+ Settings.Gesture.IsEnableTwoFingerTranslate = ToggleSwitchEnableTwoFingerTranslate.IsOn;
+ CheckEnableTwoFingerGestureBtnColorPrompt();
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTwoFingerRotation_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+
+ if (sender == ToggleSwitchEnableTwoFingerRotation)
+ BoardToggleSwitchEnableTwoFingerRotation.IsOn = ToggleSwitchEnableTwoFingerRotation.IsOn;
+ else
+ ToggleSwitchEnableTwoFingerRotation.IsOn = BoardToggleSwitchEnableTwoFingerRotation.IsOn;
+ Settings.Gesture.IsEnableTwoFingerRotation = ToggleSwitchEnableTwoFingerRotation.IsOn;
+ Settings.Gesture.IsEnableTwoFingerRotationOnSelection = ToggleSwitchEnableTwoFingerRotationOnSelection.IsOn;
+ CheckEnableTwoFingerGestureBtnColorPrompt();
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableTwoFingerGestureInPresentationMode_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode =
+ ToggleSwitchEnableTwoFingerGestureInPresentationMode.IsOn;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Reset
+
+ public static void SetSettingsToRecommendation() {
+ var AutoDelSavedFilesDays = Settings.Automation.AutoDelSavedFiles;
+ var AutoDelSavedFilesDaysThreshold = Settings.Automation.AutoDelSavedFilesDaysThreshold;
+ Settings = new Settings();
+ Settings.Advanced.IsSpecialScreen = true;
+ Settings.Advanced.IsQuadIR = false;
+ Settings.Advanced.TouchMultiplier = 0.3;
+ Settings.Advanced.NibModeBoundsWidth = 5;
+ Settings.Advanced.FingerModeBoundsWidth = 20;
+ Settings.Advanced.EraserBindTouchMultiplier = true;
+ Settings.Advanced.IsLogEnabled = true;
+ Settings.Advanced.IsSecondConfirmWhenShutdownApp = false;
+ Settings.Advanced.IsEnableEdgeGestureUtil = false;
+ Settings.Advanced.EdgeGestureUtilOnlyAffectBlackboardMode = false;
+ Settings.Advanced.IsEnableFullScreenHelper = false;
+ Settings.Advanced.IsEnableForceFullScreen = false;
+ Settings.Advanced.IsEnableDPIChangeDetection = false;
+ Settings.Advanced.IsEnableResolutionChangeDetection = false;
+
+ Settings.Appearance.IsEnableDisPlayNibModeToggler = false;
+ Settings.Appearance.IsColorfulViewboxFloatingBar = false;
+ Settings.Appearance.ViewboxFloatingBarScaleTransformValue = 1;
+ Settings.Appearance.EnableViewboxBlackBoardScaleTransform = false;
+ Settings.Appearance.IsTransparentButtonBackground = true;
+ Settings.Appearance.IsShowExitButton = true;
+ Settings.Appearance.IsShowEraserButton = true;
+ Settings.Appearance.IsShowHideControlButton = false;
+ Settings.Appearance.IsShowLRSwitchButton = false;
+ Settings.Appearance.IsShowModeFingerToggleSwitch = true;
+ Settings.Appearance.IsShowQuickPanel = true;
+ Settings.Appearance.Theme = 0;
+ Settings.Appearance.EnableChickenSoupInWhiteboardMode = true;
+ Settings.Appearance.EnableTimeDisplayInWhiteboardMode = true;
+ Settings.Appearance.ChickenSoupSource = 1;
+ Settings.Appearance.ViewboxFloatingBarOpacityValue = 1.0;
+ Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue = 1.0;
+ Settings.Appearance.EnableTrayIcon = true;
+
+ Settings.Automation.IsAutoFoldInEasiNote = true;
+ Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno = true;
+ Settings.Automation.IsAutoFoldInEasiCamera = true;
+ Settings.Automation.IsAutoFoldInEasiNote3C = false;
+ Settings.Automation.IsAutoFoldInEasiNote3 = false;
+ Settings.Automation.IsAutoFoldInEasiNote5C = true;
+ Settings.Automation.IsAutoFoldInSeewoPincoTeacher = false;
+ Settings.Automation.IsAutoFoldInHiteTouchPro = false;
+ Settings.Automation.IsAutoFoldInHiteCamera = false;
+ Settings.Automation.IsAutoFoldInWxBoardMain = false;
+ Settings.Automation.IsAutoFoldInOldZyBoard = false;
+ Settings.Automation.IsAutoFoldInMSWhiteboard = false;
+ Settings.Automation.IsAutoFoldInAdmoxWhiteboard = false;
+ Settings.Automation.IsAutoFoldInAdmoxBooth = false;
+ Settings.Automation.IsAutoFoldInQPoint = false;
+ Settings.Automation.IsAutoFoldInYiYunVisualPresenter = false;
+ Settings.Automation.IsAutoFoldInMaxHubWhiteboard = false;
+ Settings.Automation.IsAutoFoldInPPTSlideShow = false;
+ Settings.Automation.IsAutoKillPptService = false;
+ Settings.Automation.IsAutoKillEasiNote = false;
+ Settings.Automation.IsAutoKillVComYouJiao = false;
+ Settings.Automation.IsAutoKillInkCanvas = false;
+ Settings.Automation.IsAutoKillICA = false;
+ Settings.Automation.IsAutoKillIDT = true;
+ Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation = false;
+ Settings.Automation.IsSaveScreenshotsInDateFolders = false;
+ Settings.Automation.IsAutoSaveStrokesAtScreenshot = true;
+ Settings.Automation.IsAutoSaveStrokesAtClear = true;
+ Settings.Automation.IsAutoClearWhenExitingWritingMode = false;
+ Settings.Automation.MinimumAutomationStrokeNumber = 0;
+ Settings.Automation.AutoDelSavedFiles = AutoDelSavedFilesDays;
+ Settings.Automation.AutoDelSavedFilesDaysThreshold = AutoDelSavedFilesDaysThreshold;
+
+ //Settings.PowerPointSettings.IsShowPPTNavigation = true;
+ //Settings.PowerPointSettings.IsShowBottomPPTNavigationPanel = false;
+ //Settings.PowerPointSettings.IsShowSidePPTNavigationPanel = true;
+ Settings.PowerPointSettings.PowerPointSupport = true;
+ Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow = false;
+ Settings.PowerPointSettings.IsNoClearStrokeOnSelectWhenInPowerPoint = true;
+ Settings.PowerPointSettings.IsShowStrokeOnSelectInPowerPoint = false;
+ Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = true;
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint = true;
+ Settings.PowerPointSettings.IsNotifyPreviousPage = false;
+ Settings.PowerPointSettings.IsNotifyHiddenPage = false;
+ Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode = false;
+ Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl = false;
+ Settings.PowerPointSettings.IsSupportWPS = true;
+
+ Settings.Canvas.InkWidth = 2.5;
+ Settings.Canvas.IsShowCursor = false;
+ Settings.Canvas.InkStyle = 0;
+ Settings.Canvas.HighlighterWidth = 20;
+ Settings.Canvas.EraserSize = 1;
+ Settings.Canvas.EraserType = 0;
+ Settings.Canvas.EraserShapeType = 1;
+ Settings.Canvas.HideStrokeWhenSelecting = false;
+ Settings.Canvas.ClearCanvasAndClearTimeMachine = false;
+ Settings.Canvas.FitToCurve = true;
+ Settings.Canvas.UsingWhiteboard = false;
+ Settings.Canvas.HyperbolaAsymptoteOption = 0;
+
+ Settings.Gesture.AutoSwitchTwoFingerGesture = true;
+ Settings.Gesture.IsEnableTwoFingerTranslate = true;
+ Settings.Gesture.IsEnableTwoFingerZoom = false;
+ Settings.Gesture.IsEnableTwoFingerRotation = false;
+ Settings.Gesture.IsEnableTwoFingerRotationOnSelection = false;
+
+ Settings.InkToShape.IsInkToShapeEnabled = true;
+ Settings.InkToShape.IsInkToShapeNoFakePressureRectangle = false;
+ Settings.InkToShape.IsInkToShapeNoFakePressureTriangle = false;
+ Settings.InkToShape.IsInkToShapeTriangle = true;
+ Settings.InkToShape.IsInkToShapeRectangle = true;
+ Settings.InkToShape.IsInkToShapeRounded = true;
+
+
+ Settings.Startup.IsEnableNibMode = false;
+ Settings.Startup.IsAutoUpdate = true;
+ Settings.Startup.IsAutoUpdateWithSilence = true;
+ Settings.Startup.AutoUpdateWithSilenceStartTime = "18:20";
+ Settings.Startup.AutoUpdateWithSilenceEndTime = "07:40";
+ Settings.Startup.IsFoldAtStartup = false;
+ }
+
+ private void BtnResetToSuggestion_Click(object sender, RoutedEventArgs e) {
+ try {
+ isLoaded = false;
+ SetSettingsToRecommendation();
+ SaveSettingsToFile();
+ LoadSettings();
+ isLoaded = true;
+
+ ToggleSwitchRunAtStartup.IsOn = true;
+ }
+ catch { }
+
+ ShowNotification("设置已重置为默认推荐设置~");
+ }
+
+ private async void SpecialVersionResetToSuggestion_Click() {
+ await Task.Delay(1000);
+ try {
+ isLoaded = false;
+ SetSettingsToRecommendation();
+ Settings.Automation.AutoDelSavedFiles = true;
+ Settings.Automation.AutoDelSavedFilesDaysThreshold = 15;
+ SetAutoSavedStrokesLocationToDiskDButton_Click(null, null);
+ SaveSettingsToFile();
+ LoadSettings();
+ isLoaded = true;
+ }
+ catch { }
+ }
+
+ #endregion
+
+ #region Ink To Shape
+
+ private void ToggleSwitchEnableInkToShape_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeEnabled = ToggleSwitchEnableInkToShape.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableInkToShapeNoFakePressureTriangle_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeNoFakePressureTriangle =
+ ToggleSwitchEnableInkToShapeNoFakePressureTriangle.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEnableInkToShapeNoFakePressureRectangle_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeNoFakePressureRectangle =
+ ToggleSwitchEnableInkToShapeNoFakePressureRectangle.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeTriangle = (bool)ToggleCheckboxEnableInkToShapeTriangle.IsChecked;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeRectangle = (bool)ToggleCheckboxEnableInkToShapeRectangle.IsChecked;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleCheckboxEnableInkToShapeRounded_CheckedChanged(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.InkToShape.IsInkToShapeRounded = (bool)ToggleCheckboxEnableInkToShapeRounded.IsChecked;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region Advanced
+
+ private void ToggleSwitchIsSpecialScreen_OnToggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsSpecialScreen = ToggleSwitchIsSpecialScreen.IsOn;
+ TouchMultiplierSlider.Visibility =
+ ToggleSwitchIsSpecialScreen.IsOn ? Visibility.Visible : Visibility.Collapsed;
+ SaveSettingsToFile();
+ }
+
+ private void TouchMultiplierSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.TouchMultiplier = e.NewValue;
+ SaveSettingsToFile();
+ }
+
+ private void BorderCalculateMultiplier_TouchDown(object sender, TouchEventArgs e) {
+ var args = e.GetTouchPoint(null).Bounds;
+ double value;
+ if (!Settings.Advanced.IsQuadIR) value = args.Width;
+ else value = Math.Sqrt(args.Width * args.Height); //四边红外
+
+ TextBlockShowCalculatedMultiplier.Text = (5 / (value * 1.1)).ToString();
+ }
+
+ private void ToggleSwitchIsEnableFullScreenHelper_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsEnableFullScreenHelper = ToggleSwitchIsEnableFullScreenHelper.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsEnableEdgeGestureUtil_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsEnableEdgeGestureUtil = ToggleSwitchIsEnableEdgeGestureUtil.IsOn;
+ if (OSVersion.GetOperatingSystem() >= OSVersionExtension.OperatingSystem.Windows10) EdgeGestureUtil.DisableEdgeGestures(new WindowInteropHelper(this).Handle, ToggleSwitchIsEnableEdgeGestureUtil.IsOn);
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsEnableForceFullScreen_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsEnableForceFullScreen = ToggleSwitchIsEnableForceFullScreen.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsEnableDPIChangeDetection_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Advanced.IsEnableDPIChangeDetection = ToggleSwitchIsEnableDPIChangeDetection.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsEnableResolutionChangeDetection_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.Advanced.IsEnableResolutionChangeDetection = ToggleSwitchIsEnableResolutionChangeDetection.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchEraserBindTouchMultiplier_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.EraserBindTouchMultiplier = ToggleSwitchEraserBindTouchMultiplier.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void NibModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.NibModeBoundsWidth = (int)e.NewValue;
+
+ if (Settings.Startup.IsEnableNibMode)
+ BoundsWidth = Settings.Advanced.NibModeBoundsWidth;
+ else
+ BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
+
+ SaveSettingsToFile();
+ }
+
+ private void FingerModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.FingerModeBoundsWidth = (int)e.NewValue;
+
+ if (Settings.Startup.IsEnableNibMode)
+ BoundsWidth = Settings.Advanced.NibModeBoundsWidth;
+ else
+ BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
+
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsQuadIR_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsQuadIR = ToggleSwitchIsQuadIR.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsLogEnabled_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsLogEnabled = ToggleSwitchIsLogEnabled.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void ToggleSwitchIsSecondConfimeWhenShutdownApp_Toggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.Advanced.IsSecondConfirmWhenShutdownApp = ToggleSwitchIsSecondConfimeWhenShutdownApp.IsOn;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ #region RandSettings
+
+ private void ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled(object sender, RoutedEventArgs e) {
+ if (!isLoaded) return;
+ Settings.RandSettings.DisplayRandWindowNamesInputBtn = ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn;
+ SaveSettingsToFile();
+ }
+
+ private void RandWindowOnceCloseLatencySlider_ValueChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.RandSettings.RandWindowOnceCloseLatency = RandWindowOnceCloseLatencySlider.Value;
+ SaveSettingsToFile();
+ }
+
+ private void RandWindowOnceMaxStudentsSlider_ValueChanged(object sender, RoutedEventArgs e)
+ {
+ if (!isLoaded) return;
+ Settings.RandSettings.RandWindowOnceMaxStudents = (int)RandWindowOnceMaxStudentsSlider.Value;
+ SaveSettingsToFile();
+ }
+
+ #endregion
+
+ public static void SaveSettingsToFile() {
+ var text = JsonConvert.SerializeObject(Settings, Formatting.Indented);
+ try {
+ File.WriteAllText(App.RootPath + settingsFileName, text);
+ }
+ catch { }
+ }
+
+ private void SCManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e) {
+ e.Handled = true;
+ }
+
+ private void HyperlinkSourceToICCRepository_Click(object sender, RoutedEventArgs e) {
+ Process.Start("https://gitea.bliemhax.com/kriastans/InkCanvasForClass");
+ HideSubPanels();
+ }
+
+ private void HyperlinkSourceToPresentRepository_Click(object sender, RoutedEventArgs e) {
+ Process.Start("https://github.com/ChangSakura/Ink-Canvas");
+ HideSubPanels();
+ }
+
+ private void HyperlinkSourceToOringinalRepository_Click(object sender, RoutedEventArgs e) {
+ Process.Start("https://github.com/WXRIW/Ink-Canvas");
+ HideSubPanels();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
new file mode 100644
index 00000000..42c3ecc1
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs
@@ -0,0 +1,670 @@
+using Hardcodet.Wpf.TaskbarNotification;
+using Ink_Canvas.Helpers;
+using Newtonsoft.Json;
+using OSVersionExtension;
+using System;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+using File = System.IO.File;
+using OperatingSystem = OSVersionExtension.OperatingSystem;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : System.Windows.Window {
+ private void LoadSettings(bool isStartup = false) {
+ AppVersionTextBlock.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ try {
+ if (File.Exists(App.RootPath + settingsFileName)) {
+ try {
+ string text = File.ReadAllText(App.RootPath + settingsFileName);
+ Settings = JsonConvert.DeserializeObject(text);
+ }
+ catch { }
+ } else {
+ BtnResetToSuggestion_Click(null, null);
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ // Startup
+ if (isStartup) {
+ CursorIcon_Click(null, null);
+ }
+
+ try {
+ if (File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup) +
+ "\\Ink Canvas Annotation.lnk")) {
+ ToggleSwitchRunAtStartup.IsOn = true;
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+
+ if (Settings.Startup != null) {
+ if (isStartup) {
+ if (Settings.Automation.AutoDelSavedFiles) {
+ DelAutoSavedFiles.DeleteFilesOlder(Settings.Automation.AutoSavedStrokesLocation,
+ Settings.Automation.AutoDelSavedFilesDaysThreshold);
+ }
+
+ if (Settings.Startup.IsFoldAtStartup) {
+ FoldFloatingBar_MouseUp(Fold_Icon, null);
+ }
+ }
+
+ if (Settings.Startup.IsEnableNibMode) {
+ ToggleSwitchEnableNibMode.IsOn = true;
+ BoardToggleSwitchEnableNibMode.IsOn = true;
+ BoundsWidth = Settings.Advanced.NibModeBoundsWidth;
+ } else {
+ ToggleSwitchEnableNibMode.IsOn = false;
+ BoardToggleSwitchEnableNibMode.IsOn = false;
+ BoundsWidth = Settings.Advanced.FingerModeBoundsWidth;
+ }
+
+ if (Settings.Startup.IsAutoUpdate) {
+ ToggleSwitchIsAutoUpdate.IsOn = true;
+ AutoUpdate();
+ }
+
+ // ToggleSwitchIsAutoUpdateWithSilence.Visibility = Settings.Startup.IsAutoUpdate ? Visibility.Visible : Visibility.Collapsed;
+ if (Settings.Startup.IsAutoUpdateWithSilence) {
+ ToggleSwitchIsAutoUpdateWithSilence.IsOn = true;
+ }
+
+ AutoUpdateTimePeriodBlock.Visibility = Settings.Startup.IsAutoUpdateWithSilence
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+
+ AutoUpdateWithSilenceTimeComboBox.InitializeAutoUpdateWithSilenceTimeComboBoxOptions(
+ AutoUpdateWithSilenceStartTimeComboBox, AutoUpdateWithSilenceEndTimeComboBox);
+ AutoUpdateWithSilenceStartTimeComboBox.SelectedItem = Settings.Startup.AutoUpdateWithSilenceStartTime;
+ AutoUpdateWithSilenceEndTimeComboBox.SelectedItem = Settings.Startup.AutoUpdateWithSilenceEndTime;
+
+ ToggleSwitchFoldAtStartup.IsOn = Settings.Startup.IsFoldAtStartup;
+ } else {
+ Settings.Startup = new Startup();
+ }
+
+ // Appearance
+ if (Settings.Appearance != null) {
+ if (!Settings.Appearance.IsEnableDisPlayNibModeToggler) {
+ NibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
+ BoardNibModeSimpleStackPanel.Visibility = Visibility.Collapsed;
+ } else {
+ NibModeSimpleStackPanel.Visibility = Visibility.Visible;
+ BoardNibModeSimpleStackPanel.Visibility = Visibility.Visible;
+ }
+
+ //if (Settings.Appearance.IsColorfulViewboxFloatingBar) // 浮动工具栏背景色
+ //{
+ // LinearGradientBrush gradientBrush = new LinearGradientBrush();
+ // gradientBrush.StartPoint = new Point(0, 0);
+ // gradientBrush.EndPoint = new Point(1, 1);
+ // GradientStop blueStop = new GradientStop(Color.FromArgb(0x95, 0x80, 0xB0, 0xFF), 0);
+ // GradientStop greenStop = new GradientStop(Color.FromArgb(0x95, 0xC0, 0xFF, 0xC0), 1);
+ // gradientBrush.GradientStops.Add(blueStop);
+ // gradientBrush.GradientStops.Add(greenStop);
+ // EnableTwoFingerGestureBorder.Background = gradientBrush;
+ // BorderFloatingBarMainControls.Background = gradientBrush;
+ // BorderFloatingBarMoveControls.Background = gradientBrush;
+ // BorderFloatingBarExitPPTBtn.Background = gradientBrush;
+
+ // ToggleSwitchColorfulViewboxFloatingBar.IsOn = true;
+ //} else {
+ // EnableTwoFingerGestureBorder.Background = (Brush)FindResource("FloatBarBackground");
+ // BorderFloatingBarMainControls.Background = (Brush)FindResource("FloatBarBackground");
+ // BorderFloatingBarMoveControls.Background = (Brush)FindResource("FloatBarBackground");
+ // BorderFloatingBarExitPPTBtn.Background = (Brush)FindResource("FloatBarBackground");
+
+ // ToggleSwitchColorfulViewboxFloatingBar.IsOn = false;
+ //}
+
+ if (Settings.Appearance.ViewboxFloatingBarScaleTransformValue != 0) // 浮动工具栏 UI 缩放 85%
+ {
+ double val = Settings.Appearance.ViewboxFloatingBarScaleTransformValue;
+ ViewboxFloatingBarScaleTransform.ScaleX =
+ (val > 0.5 && val < 1.25) ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
+ ViewboxFloatingBarScaleTransform.ScaleY =
+ (val > 0.5 && val < 1.25) ? val : val <= 0.5 ? 0.5 : val >= 1.25 ? 1.25 : 1;
+ ViewboxFloatingBarScaleTransformValueSlider.Value = val;
+ }
+
+ ComboBoxUnFoldBtnImg.SelectedIndex = Settings.Appearance.UnFoldButtonImageType;
+ switch (Settings.Appearance.UnFoldButtonImageType) {
+ case 0:
+ RightUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
+ RightUnFoldBtnImgChevron.Width = 14;
+ RightUnFoldBtnImgChevron.Height = 14;
+ RightUnFoldBtnImgChevron.RenderTransform = new RotateTransform(180);
+ LeftUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/unfold-chevron.png"));
+ LeftUnFoldBtnImgChevron.Width = 14;
+ LeftUnFoldBtnImgChevron.Height = 14;
+ LeftUnFoldBtnImgChevron.RenderTransform = null;
+ break;
+ case 1:
+ RightUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
+ RightUnFoldBtnImgChevron.Width = 18;
+ RightUnFoldBtnImgChevron.Height = 18;
+ RightUnFoldBtnImgChevron.RenderTransform = null;
+ LeftUnFoldBtnImgChevron.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/new-icons/pen-white.png"));
+ LeftUnFoldBtnImgChevron.Width = 18;
+ LeftUnFoldBtnImgChevron.Height = 18;
+ LeftUnFoldBtnImgChevron.RenderTransform = null;
+ break;
+ }
+
+ ComboBoxChickenSoupSource.SelectedIndex = Settings.Appearance.ChickenSoupSource;
+
+ ToggleSwitchEnableQuickPanel.IsOn = Settings.Appearance.IsShowQuickPanel;
+
+ ToggleSwitchEnableTrayIcon.IsOn = Settings.Appearance.EnableTrayIcon;
+ ICCTrayIconExampleImage.Visibility =
+ Settings.Appearance.EnableTrayIcon ? Visibility.Visible : Visibility.Collapsed;
+ var _taskbar = (TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"];
+ _taskbar.Visibility = Settings.Appearance.EnableTrayIcon ? Visibility.Visible : Visibility.Collapsed;
+
+ ViewboxFloatingBar.Opacity = Settings.Appearance.ViewboxFloatingBarOpacityValue;
+
+ if (Settings.Appearance.EnableViewboxBlackBoardScaleTransform) // 画板 UI 缩放 80%
+ {
+ //ViewboxBlackboardLeftSideScaleTransform.ScaleX = 0.8;
+ //ViewboxBlackboardLeftSideScaleTransform.ScaleY = 0.8;
+ ViewboxBlackboardCenterSideScaleTransform.ScaleX = 0.8;
+ ViewboxBlackboardCenterSideScaleTransform.ScaleY = 0.8;
+ //ViewboxBlackboardRightSideScaleTransform.ScaleX = 0.8;
+ //ViewboxBlackboardRightSideScaleTransform.ScaleY = 0.8;
+
+ ToggleSwitchEnableViewboxBlackBoardScaleTransform.IsOn = true;
+ } else {
+ //ViewboxBlackboardLeftSideScaleTransform.ScaleX = 1;
+ //ViewboxBlackboardLeftSideScaleTransform.ScaleY = 1;
+ ViewboxBlackboardCenterSideScaleTransform.ScaleX = 1;
+ ViewboxBlackboardCenterSideScaleTransform.ScaleY = 1;
+ //ViewboxBlackboardRightSideScaleTransform.ScaleX = 1;
+ //ViewboxBlackboardRightSideScaleTransform.ScaleY = 1;
+
+ ToggleSwitchEnableViewboxBlackBoardScaleTransform.IsOn = false;
+ }
+
+ if (Settings.Appearance.IsTransparentButtonBackground) {
+ BtnExit.Background = new SolidColorBrush(StringToColor("#7F909090"));
+ } else {
+ //Light
+ BtnExit.Background = BtnSwitchTheme.Content.ToString() == "深色"
+ ? new SolidColorBrush(StringToColor("#FFCCCCCC"))
+ :
+ //Dark
+ new SolidColorBrush(StringToColor("#FF555555"));
+ }
+
+ ComboBoxFloatingBarImg.SelectedIndex = Settings.Appearance.FloatingBarImg;
+ if (ComboBoxFloatingBarImg.SelectedIndex == 0) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/icc.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(0.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 1) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(
+ new Uri("pack://application:,,,/Resources/Icons-png/icc-transparent-dark-small.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(1.2);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 2) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandoujiyanhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 3) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanshounvhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 4) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanciya.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 5) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuanneikuhuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 6) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/kuandogeyuanliangwo.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1.5);
+ } else if (ComboBoxFloatingBarImg.SelectedIndex == 7) {
+ FloatingbarHeadIconImg.Source =
+ new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/tiebahuaji.png"));
+ FloatingbarHeadIconImg.Margin = new Thickness(2, 2, 2, 1);
+ }
+
+ ToggleSwitchEnableTimeDisplayInWhiteboardMode.IsOn =
+ Settings.Appearance.EnableTimeDisplayInWhiteboardMode;
+
+ ToggleSwitchEnableChickenSoupInWhiteboardMode.IsOn =
+ Settings.Appearance.EnableChickenSoupInWhiteboardMode;
+
+ SystemEvents_UserPreferenceChanged(null, null);
+ } else {
+ Settings.Appearance = new Appearance();
+ }
+
+ // PowerPointSettings
+ if (Settings.PowerPointSettings != null) {
+
+
+ if (Settings.PowerPointSettings.PowerPointSupport) {
+ ToggleSwitchSupportPowerPoint.IsOn = true;
+ timerCheckPPT.Start();
+ } else {
+ ToggleSwitchSupportPowerPoint.IsOn = false;
+ timerCheckPPT.Stop();
+ }
+
+ ToggleSwitchShowCanvasAtNewSlideShow.IsOn = Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow;
+
+ ToggleSwitchEnableTwoFingerGestureInPresentationMode.IsOn =
+ Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode;
+
+ ToggleSwitchEnableFingerGestureSlideShowControl.IsOn =
+ Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl;
+
+ ToggleSwitchAutoSaveStrokesInPowerPoint.IsOn =
+ Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
+
+ ToggleSwitchNotifyPreviousPage.IsOn = Settings.PowerPointSettings.IsNotifyPreviousPage;
+
+ // -- new --
+ ToggleSwitchShowPPTButton.IsOn = Settings.PowerPointSettings.ShowPPTButton;
+
+ ToggleSwitchEnablePPTButtonPageClickable.IsOn =
+ Settings.PowerPointSettings.EnablePPTButtonPageClickable;
+
+ var dops = Settings.PowerPointSettings.PPTButtonsDisplayOption.ToString();
+ var dopsc = dops.ToCharArray();
+ if ((dopsc[0] == '1' || dopsc[0] == '2') && (dopsc[1] == '1' || dopsc[1] == '2') &&
+ (dopsc[2] == '1' || dopsc[2] == '2') && (dopsc[3] == '1' || dopsc[3] == '2')) {
+ CheckboxEnableLBPPTButton.IsChecked = dopsc[0] == '2';
+ CheckboxEnableRBPPTButton.IsChecked = dopsc[1] == '2';
+ CheckboxEnableLSPPTButton.IsChecked = dopsc[2] == '2';
+ CheckboxEnableRSPPTButton.IsChecked = dopsc[3] == '2';
+ } else {
+ Settings.PowerPointSettings.PPTButtonsDisplayOption = 2222;
+ CheckboxEnableLBPPTButton.IsChecked = true;
+ CheckboxEnableRBPPTButton.IsChecked = true;
+ CheckboxEnableLSPPTButton.IsChecked = true;
+ CheckboxEnableRSPPTButton.IsChecked = true;
+ SaveSettingsToFile();
+ }
+
+ var sops = Settings.PowerPointSettings.PPTSButtonsOption.ToString();
+ var sopsc = sops.ToCharArray();
+ if ((sopsc[0] == '1' || sopsc[0] == '2') && (sopsc[1] == '1' || sopsc[1] == '2') &&
+ (sopsc[2] == '1' || sopsc[2] == '2'))
+ {
+ CheckboxSPPTDisplayPage.IsChecked = sopsc[0] == '2';
+ CheckboxSPPTHalfOpacity.IsChecked = sopsc[1] == '2';
+ CheckboxSPPTBlackBackground.IsChecked = sopsc[2] == '2';
+ }
+ else
+ {
+ Settings.PowerPointSettings.PPTSButtonsOption = 221;
+ CheckboxSPPTDisplayPage.IsChecked = true;
+ CheckboxSPPTHalfOpacity.IsChecked = true;
+ CheckboxSPPTBlackBackground.IsChecked = false;
+ SaveSettingsToFile();
+ }
+
+ var bops = Settings.PowerPointSettings.PPTBButtonsOption.ToString();
+ var bopsc = bops.ToCharArray();
+ if ((bopsc[0] == '1' || bopsc[0] == '2') && (bopsc[1] == '1' || bopsc[1] == '2') &&
+ (bopsc[2] == '1' || bopsc[2] == '2'))
+ {
+ CheckboxBPPTDisplayPage.IsChecked = bopsc[0] == '2';
+ CheckboxBPPTHalfOpacity.IsChecked = bopsc[1] == '2';
+ CheckboxBPPTBlackBackground.IsChecked = bopsc[2] == '2';
+ }
+ else
+ {
+ Settings.PowerPointSettings.PPTBButtonsOption = 121;
+ CheckboxBPPTDisplayPage.IsChecked = false;
+ CheckboxBPPTHalfOpacity.IsChecked = true;
+ CheckboxBPPTBlackBackground.IsChecked = false;
+ SaveSettingsToFile();
+ }
+
+ PPTButtonLeftPositionValueSlider.Value = Settings.PowerPointSettings.PPTLSButtonPosition;
+
+ PPTButtonRightPositionValueSlider.Value = Settings.PowerPointSettings.PPTRSButtonPosition;
+
+ UpdatePPTBtnSlidersStatus();
+
+ UpdatePPTBtnPreview();
+
+ // -- new --
+
+ ToggleSwitchNotifyHiddenPage.IsOn = Settings.PowerPointSettings.IsNotifyHiddenPage;
+
+ ToggleSwitchNotifyAutoPlayPresentation.IsOn = Settings.PowerPointSettings.IsNotifyAutoPlayPresentation;
+
+ ToggleSwitchSupportWPS.IsOn = Settings.PowerPointSettings.IsSupportWPS;
+
+ ToggleSwitchAutoSaveScreenShotInPowerPoint.IsOn =
+ Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint;
+ } else {
+ Settings.PowerPointSettings = new PowerPointSettings();
+ }
+
+ // Gesture
+ if (Settings.Gesture != null) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = Settings.Gesture.IsEnableMultiTouchMode;
+
+ ToggleSwitchEnableTwoFingerZoom.IsOn = Settings.Gesture.IsEnableTwoFingerZoom;
+ BoardToggleSwitchEnableTwoFingerZoom.IsOn = Settings.Gesture.IsEnableTwoFingerZoom;
+
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = Settings.Gesture.IsEnableTwoFingerTranslate;
+ BoardToggleSwitchEnableTwoFingerTranslate.IsOn = Settings.Gesture.IsEnableTwoFingerTranslate;
+
+ ToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
+ BoardToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
+
+ ToggleSwitchAutoSwitchTwoFingerGesture.IsOn = Settings.Gesture.AutoSwitchTwoFingerGesture;
+
+ ToggleSwitchEnableTwoFingerRotation.IsOn = Settings.Gesture.IsEnableTwoFingerRotation;
+
+ ToggleSwitchEnableTwoFingerRotationOnSelection.IsOn =
+ Settings.Gesture.IsEnableTwoFingerRotationOnSelection;
+
+ if (Settings.Gesture.AutoSwitchTwoFingerGesture) {
+ if (Topmost) {
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = false;
+ BoardToggleSwitchEnableTwoFingerTranslate.IsOn = false;
+ Settings.Gesture.IsEnableTwoFingerTranslate = false;
+ if (!isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ } else {
+ ToggleSwitchEnableTwoFingerTranslate.IsOn = true;
+ BoardToggleSwitchEnableTwoFingerTranslate.IsOn = true;
+ Settings.Gesture.IsEnableTwoFingerTranslate = true;
+ if (isInMultiTouchMode) ToggleSwitchEnableMultiTouchMode.IsOn = false;
+ }
+ }
+
+ CheckEnableTwoFingerGestureBtnColorPrompt();
+ } else {
+ Settings.Gesture = new Gesture();
+ }
+
+ // Canvas
+ if (Settings.Canvas != null) {
+ drawingAttributes.Height = Settings.Canvas.InkWidth;
+ drawingAttributes.Width = Settings.Canvas.InkWidth;
+
+ InkWidthSlider.Value = Settings.Canvas.InkWidth * 2;
+ HighlighterWidthSlider.Value = Settings.Canvas.HighlighterWidth;
+
+ ComboBoxHyperbolaAsymptoteOption.SelectedIndex = (int)Settings.Canvas.HyperbolaAsymptoteOption;
+
+ if (Settings.Canvas.UsingWhiteboard) {
+ GridBackgroundCover.Background = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ isUselightThemeColor = false;
+ } else {
+ GridBackgroundCover.Background = new SolidColorBrush(Color.FromRgb(22, 41, 36));
+ WaterMarkTime.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ WaterMarkDate.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ BlackBoardWaterMark.Foreground = new SolidColorBrush(Color.FromRgb(234, 235, 237));
+ isUselightThemeColor = true;
+ }
+
+ if (Settings.Canvas.IsShowCursor) {
+ ToggleSwitchShowCursor.IsOn = true;
+ inkCanvas.ForceCursor = true;
+ } else {
+ ToggleSwitchShowCursor.IsOn = false;
+ inkCanvas.ForceCursor = false;
+ }
+
+ ComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
+ BoardComboBoxPenStyle.SelectedIndex = Settings.Canvas.InkStyle;
+
+ ComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize;
+ ComboBoxEraserSizeFloatingBar.SelectedIndex = Settings.Canvas.EraserSize;
+ BoardComboBoxEraserSize.SelectedIndex = Settings.Canvas.EraserSize;
+
+ ToggleSwitchClearCanvasAndClearTimeMachine.IsOn =
+ Settings.Canvas.ClearCanvasAndClearTimeMachine == true;
+
+ switch (Settings.Canvas.EraserShapeType) {
+ case 0: {
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(k * 90, k * 90);
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ break;
+ }
+ case 1: {
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.7;
+ break;
+ case 1:
+ k = 0.9;
+ break;
+ case 3:
+ k = 1.2;
+ break;
+ case 4:
+ k = 1.6;
+ break;
+ }
+
+ inkCanvas.EraserShape = new RectangleStylusShape(k * 90 * 0.6, k * 90);
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ break;
+ }
+ }
+
+ CheckEraserTypeTab();
+
+ ToggleSwitchHideStrokeWhenSelecting.IsOn = Settings.Canvas.HideStrokeWhenSelecting;
+
+ if (Settings.Canvas.FitToCurve) {
+ ToggleSwitchFitToCurve.IsOn = true;
+ drawingAttributes.FitToCurve = true;
+ } else {
+ ToggleSwitchFitToCurve.IsOn = false;
+ drawingAttributes.FitToCurve = false;
+ }
+ } else {
+ Settings.Canvas = new Canvas();
+ }
+
+ // Advanced
+ if (Settings.Advanced != null) {
+ TouchMultiplierSlider.Value = Settings.Advanced.TouchMultiplier;
+ FingerModeBoundsWidthSlider.Value = Settings.Advanced.FingerModeBoundsWidth;
+ NibModeBoundsWidthSlider.Value = Settings.Advanced.NibModeBoundsWidth;
+ ToggleSwitchIsLogEnabled.IsOn = Settings.Advanced.IsLogEnabled;
+
+ ToggleSwitchIsSecondConfimeWhenShutdownApp.IsOn = Settings.Advanced.IsSecondConfirmWhenShutdownApp;
+
+ ToggleSwitchEraserBindTouchMultiplier.IsOn = Settings.Advanced.EraserBindTouchMultiplier;
+
+ ToggleSwitchIsSpecialScreen.IsOn = Settings.Advanced.IsSpecialScreen;
+
+ TouchMultiplierSlider.Visibility =
+ ToggleSwitchIsSpecialScreen.IsOn ? Visibility.Visible : Visibility.Collapsed;
+
+ ToggleSwitchIsQuadIR.IsOn = Settings.Advanced.IsQuadIR;
+
+ ToggleSwitchIsEnableFullScreenHelper.IsOn = Settings.Advanced.IsEnableFullScreenHelper;
+ if (Settings.Advanced.IsEnableFullScreenHelper) {
+ FullScreenHelper.MarkFullscreenWindowTaskbarList(new WindowInteropHelper(this).Handle, true);
+ }
+
+ ToggleSwitchIsEnableEdgeGestureUtil.IsOn = Settings.Advanced.IsEnableEdgeGestureUtil;
+ if (Settings.Advanced.IsEnableEdgeGestureUtil) {
+ if (OSVersion.GetOperatingSystem() >= OperatingSystem.Windows10)
+ EdgeGestureUtil.DisableEdgeGestures(new WindowInteropHelper(this).Handle, true);
+ }
+
+ ToggleSwitchIsEnableForceFullScreen.IsOn = Settings.Advanced.IsEnableForceFullScreen;
+
+ ToggleSwitchIsEnableDPIChangeDetection.IsOn = Settings.Advanced.IsEnableDPIChangeDetection;
+
+ ToggleSwitchIsEnableResolutionChangeDetection.IsOn =
+ Settings.Advanced.IsEnableResolutionChangeDetection;
+ } else {
+ Settings.Advanced = new Advanced();
+ }
+
+ // InkToShape
+ if (Settings.InkToShape != null) {
+ ToggleSwitchEnableInkToShape.IsOn = Settings.InkToShape.IsInkToShapeEnabled;
+
+ ToggleSwitchEnableInkToShapeNoFakePressureRectangle.IsOn =
+ Settings.InkToShape.IsInkToShapeNoFakePressureRectangle;
+
+ ToggleSwitchEnableInkToShapeNoFakePressureTriangle.IsOn =
+ Settings.InkToShape.IsInkToShapeNoFakePressureTriangle;
+
+ ToggleCheckboxEnableInkToShapeTriangle.IsChecked = Settings.InkToShape.IsInkToShapeTriangle;
+
+ ToggleCheckboxEnableInkToShapeRectangle.IsChecked = Settings.InkToShape.IsInkToShapeRectangle;
+
+ ToggleCheckboxEnableInkToShapeRounded.IsChecked = Settings.InkToShape.IsInkToShapeRounded;
+ } else {
+ Settings.InkToShape = new InkToShape();
+ }
+
+ // RandSettings
+ if (Settings.RandSettings != null) { } else {
+ Settings.RandSettings = new RandSettings();
+ ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = Settings.RandSettings.DisplayRandWindowNamesInputBtn;
+ RandWindowOnceCloseLatencySlider.Value = Settings.RandSettings.RandWindowOnceCloseLatency;
+ RandWindowOnceMaxStudentsSlider.Value = Settings.RandSettings.RandWindowOnceMaxStudents;
+ }
+
+ // Automation
+ if (Settings.Automation != null) {
+ StartOrStoptimerCheckAutoFold();
+ ToggleSwitchAutoFoldInEasiNote.IsOn = Settings.Automation.IsAutoFoldInEasiNote;
+
+ ToggleSwitchAutoFoldInEasiCamera.IsOn = Settings.Automation.IsAutoFoldInEasiCamera;
+
+ ToggleSwitchAutoFoldInEasiNote3C.IsOn = Settings.Automation.IsAutoFoldInEasiNote3C;
+
+ ToggleSwitchAutoFoldInEasiNote3.IsOn = Settings.Automation.IsAutoFoldInEasiNote3;
+
+ ToggleSwitchAutoFoldInEasiNote5C.IsOn = Settings.Automation.IsAutoFoldInEasiNote5C;
+
+ ToggleSwitchAutoFoldInSeewoPincoTeacher.IsOn = Settings.Automation.IsAutoFoldInSeewoPincoTeacher;
+
+ ToggleSwitchAutoFoldInHiteTouchPro.IsOn = Settings.Automation.IsAutoFoldInHiteTouchPro;
+
+ ToggleSwitchAutoFoldInHiteLightBoard.IsOn = Settings.Automation.IsAutoFoldInHiteLightBoard;
+
+ ToggleSwitchAutoFoldInHiteCamera.IsOn = Settings.Automation.IsAutoFoldInHiteCamera;
+
+ ToggleSwitchAutoFoldInWxBoardMain.IsOn = Settings.Automation.IsAutoFoldInWxBoardMain;
+
+ ToggleSwitchAutoFoldInOldZyBoard.IsOn = Settings.Automation.IsAutoFoldInOldZyBoard;
+
+ ToggleSwitchAutoFoldInMSWhiteboard.IsOn = Settings.Automation.IsAutoFoldInMSWhiteboard;
+
+ ToggleSwitchAutoFoldInAdmoxWhiteboard.IsOn = Settings.Automation.IsAutoFoldInAdmoxWhiteboard;
+
+ ToggleSwitchAutoFoldInAdmoxBooth.IsOn = Settings.Automation.IsAutoFoldInAdmoxBooth;
+
+ ToggleSwitchAutoFoldInQPoint.IsOn = Settings.Automation.IsAutoFoldInQPoint;
+
+ ToggleSwitchAutoFoldInYiYunVisualPresenter.IsOn = Settings.Automation.IsAutoFoldInYiYunVisualPresenter;
+
+ ToggleSwitchAutoFoldInMaxHubWhiteboard.IsOn = Settings.Automation.IsAutoFoldInMaxHubWhiteboard;
+
+ SettingsPPTInkingAndAutoFoldExplictBorder.Visibility = Visibility.Collapsed;
+ if (Settings.Automation.IsAutoFoldInPPTSlideShow) {
+ SettingsPPTInkingAndAutoFoldExplictBorder.Visibility = Visibility.Visible;
+ SettingsShowCanvasAtNewSlideShowStackPanel.Opacity = 0.5;
+ SettingsShowCanvasAtNewSlideShowStackPanel.IsHitTestVisible = false;
+ }
+
+ ToggleSwitchAutoFoldInPPTSlideShow.IsOn = Settings.Automation.IsAutoFoldInPPTSlideShow;
+
+ 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();
+ }
+
+ ToggleSwitchAutoKillEasiNote.IsOn = Settings.Automation.IsAutoKillEasiNote;
+
+ ToggleSwitchAutoKillHiteAnnotation.IsOn = Settings.Automation.IsAutoKillHiteAnnotation;
+
+ ToggleSwitchAutoKillPptService.IsOn = Settings.Automation.IsAutoKillPptService;
+
+ ToggleSwitchAutoKillVComYouJiao.IsOn = Settings.Automation.IsAutoKillVComYouJiao;
+
+ ToggleSwitchAutoKillInkCanvas.IsOn = Settings.Automation.IsAutoKillInkCanvas;
+
+ ToggleSwitchAutoKillICA.IsOn = Settings.Automation.IsAutoKillICA;
+
+ ToggleSwitchAutoKillIDT.IsOn = Settings.Automation.IsAutoKillIDT;
+
+ ToggleSwitchAutoKillSeewoLauncher2DesktopAnnotation.IsOn =
+ Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation;
+
+ ToggleSwitchAutoSaveStrokesAtClear.IsOn = Settings.Automation.IsAutoSaveStrokesAtClear;
+
+ ToggleSwitchSaveScreenshotsInDateFolders.IsOn = Settings.Automation.IsSaveScreenshotsInDateFolders;
+
+ ToggleSwitchAutoSaveStrokesAtScreenshot.IsOn = Settings.Automation.IsAutoSaveStrokesAtScreenshot;
+
+ SideControlMinimumAutomationSlider.Value = Settings.Automation.MinimumAutomationStrokeNumber;
+
+ AutoSavedStrokesLocation.Text = Settings.Automation.AutoSavedStrokesLocation;
+ ToggleSwitchAutoDelSavedFiles.IsOn = Settings.Automation.AutoDelSavedFiles;
+ ComboBoxAutoDelSavedFilesDaysThreshold.Text =
+ Settings.Automation.AutoDelSavedFilesDaysThreshold.ToString();
+ } else {
+ Settings.Automation = new Automation();
+ }
+
+ // auto align
+ if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) {
+ ViewboxFloatingBarMarginAnimation(60);
+ } else {
+ ViewboxFloatingBarMarginAnimation(100, true);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs
new file mode 100644
index 00000000..f964ed5e
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs
@@ -0,0 +1,1616 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using MessageBox = System.Windows.MessageBox;
+using Point = System.Windows.Point;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region Floating Bar Control
+
+ private void ImageDrawShape_MouseUp(object sender, MouseButtonEventArgs e) {
+
+ if (lastBorderMouseDownObject != null && lastBorderMouseDownObject is Panel)
+ ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
+ if (sender == ShapeDrawFloatingBarBtn && lastBorderMouseDownObject != ShapeDrawFloatingBarBtn) return;
+
+ // FloatingBarIcons_MouseUp_New(sender);
+ if (BorderDrawShape.Visibility == Visibility.Visible) {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderDrawShape);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ }
+ else {
+ AnimationsHelper.HideWithSlideAndFade(EraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(PenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardPenPalette);
+ AnimationsHelper.HideWithSlideAndFade(BoardEraserSizePanel);
+ AnimationsHelper.HideWithSlideAndFade(BorderTools);
+ AnimationsHelper.HideWithSlideAndFade(BoardBorderTools);
+ AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder);
+ AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BorderDrawShape);
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardBorderDrawShape);
+ }
+ }
+
+ #endregion Floating Bar Control
+
+ private int drawingShapeMode = 0;
+ private bool isLongPressSelected = false; // 用于存是否是“选中”状态,便于后期抬笔后不做切换到笔的处理
+
+ #region Buttons
+
+ private void SymbolIconPinBorderDrawShape_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (lastBorderMouseDownObject != sender) return;
+
+ ToggleSwitchDrawShapeBorderAutoHide.IsOn = !ToggleSwitchDrawShapeBorderAutoHide.IsOn;
+
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn)
+ ((iNKORE.UI.WPF.Modern.Controls.SymbolIcon)sender).Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Pin;
+ else
+ ((iNKORE.UI.WPF.Modern.Controls.SymbolIcon)sender).Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.UnPin;
+ }
+
+ private object lastMouseDownSender = null;
+ private DateTime lastMouseDownTime = DateTime.MinValue;
+
+ private async void Image_MouseDown(object sender, MouseButtonEventArgs e) {
+ lastMouseDownSender = sender;
+ lastMouseDownTime = DateTime.Now;
+
+ await Task.Delay(500);
+
+ if (lastMouseDownSender == sender) {
+ lastMouseDownSender = null;
+ var dA = new DoubleAnimation(1, 0.3, new Duration(TimeSpan.FromMilliseconds(100)));
+ ((UIElement)sender).BeginAnimation(OpacityProperty, dA);
+
+ forceEraser = true;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ if (sender == ImageDrawLine || sender == BoardImageDrawLine)
+ drawingShapeMode = 1;
+ else if (sender == ImageDrawDashedLine || sender == BoardImageDrawDashedLine)
+ drawingShapeMode = 8;
+ else if (sender == ImageDrawDotLine || sender == BoardImageDrawDotLine)
+ drawingShapeMode = 18;
+ else if (sender == ImageDrawArrow || sender == BoardImageDrawArrow)
+ drawingShapeMode = 2;
+ else if (sender == ImageDrawParallelLine || sender == BoardImageDrawParallelLine) drawingShapeMode = 15;
+ isLongPressSelected = true;
+ if (isSingleFingerDragMode) BtnFingerDragMode_Click(BtnFingerDragMode, null);
+ }
+ }
+
+ private void BtnPen_Click(object sender, RoutedEventArgs e) {
+ forceEraser = false;
+ drawingShapeMode = 0;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ isLongPressSelected = false;
+ }
+
+ private Task CheckIsDrawingShapesInMultiTouchMode() {
+ if (isInMultiTouchMode) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = false;
+ lastIsInMultiTouchMode = true;
+ }
+
+ return Task.FromResult(true);
+ }
+
+ private async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ if (lastMouseDownSender == sender) {
+ forceEraser = true;
+ drawingShapeMode = 1;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ }
+
+ lastMouseDownSender = null;
+ if (isLongPressSelected) {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+ var dA = new DoubleAnimation(1, 1, new Duration(TimeSpan.FromMilliseconds(0)));
+ ImageDrawLine.BeginAnimation(OpacityProperty, dA);
+ }
+
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawDashedLine_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ if (lastMouseDownSender == sender) {
+ forceEraser = true;
+ drawingShapeMode = 8;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ }
+
+ lastMouseDownSender = null;
+ if (isLongPressSelected) {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+ var dA = new DoubleAnimation(1, 1, new Duration(TimeSpan.FromMilliseconds(0)));
+ ImageDrawDashedLine.BeginAnimation(OpacityProperty, dA);
+ }
+
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawDotLine_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ if (lastMouseDownSender == sender) {
+ forceEraser = true;
+ drawingShapeMode = 18;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ }
+
+ lastMouseDownSender = null;
+ if (isLongPressSelected) {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+ var dA = new DoubleAnimation(1, 1, new Duration(TimeSpan.FromMilliseconds(0)));
+ ImageDrawDotLine.BeginAnimation(OpacityProperty, dA);
+ }
+
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawArrow_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ if (lastMouseDownSender == sender) {
+ forceEraser = true;
+ drawingShapeMode = 2;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ }
+
+ lastMouseDownSender = null;
+ if (isLongPressSelected) {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+ var dA = new DoubleAnimation(1, 1, new Duration(TimeSpan.FromMilliseconds(0)));
+ ImageDrawArrow.BeginAnimation(OpacityProperty, dA);
+ }
+
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawParallelLine_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ if (lastMouseDownSender == sender) {
+ forceEraser = true;
+ drawingShapeMode = 15;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ }
+
+ lastMouseDownSender = null;
+ if (isLongPressSelected) {
+ if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape();
+ var dA = new DoubleAnimation(1, 1, new Duration(TimeSpan.FromMilliseconds(0)));
+ ImageDrawParallelLine.BeginAnimation(OpacityProperty, dA);
+ }
+
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCoordinate1_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 11;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCoordinate2_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 12;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCoordinate3_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 13;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCoordinate4_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 14;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCoordinate5_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 17;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawRectangle_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 3;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawRectangleCenter_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 19;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawEllipse_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 4;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCircle_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 5;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCenterEllipse_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 16;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCenterEllipseWithFocalPoint_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 23;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawDashedCircle_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 10;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawHyperbola_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 24;
+ drawMultiStepShapeCurrentStep = 0;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawHyperbolaWithFocalPoint_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 25;
+ drawMultiStepShapeCurrentStep = 0;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawParabola1_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 20;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawParabolaWithFocalPoint_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 22;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawParabola2_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 21;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCylinder_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 6;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCone_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 7;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ private async void BtnDrawCuboid_Click(object sender, MouseButtonEventArgs e) {
+ await CheckIsDrawingShapesInMultiTouchMode();
+ forceEraser = true;
+ drawingShapeMode = 9;
+ isFirstTouchCuboid = true;
+ CuboidFrontRectIniP = new Point();
+ CuboidFrontRectEndP = new Point();
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.IsManipulationEnabled = true;
+ CancelSingleFingerDragMode();
+ DrawShapePromptToPen();
+ }
+
+ #endregion
+
+ private void inkCanvas_TouchMove(object sender, TouchEventArgs e) {
+ if (isSingleFingerDragMode) return;
+ if (drawingShapeMode != 0) {
+ if (isLastTouchEraser) return;
+ //EraserContainer.Background = null;
+ //ImageEraser.Visibility = Visibility.Visible;
+ if (isWaitUntilNextTouchDown) return;
+ if (dec.Count > 1) {
+ isWaitUntilNextTouchDown = true;
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ return;
+ }
+
+ if (inkCanvas.EditingMode != InkCanvasEditingMode.None)
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ }
+
+ MouseTouchMove(e.GetTouchPoint(inkCanvas).Position);
+ }
+
+ private int drawMultiStepShapeCurrentStep = 0; //多笔完成的图形 当前所处在的笔画
+
+ private StrokeCollection drawMultiStepShapeSpecialStrokeCollection = new StrokeCollection(); //多笔完成的图形 当前所处在的笔画
+
+ //double drawMultiStepShapeSpecialParameter1 = 0.0; //多笔完成的图形 特殊参数 通常用于表示a
+ //double drawMultiStepShapeSpecialParameter2 = 0.0; //多笔完成的图形 特殊参数 通常用于表示b
+ private double drawMultiStepShapeSpecialParameter3 = 0.0; //多笔完成的图形 特殊参数 通常用于表示k
+
+ #region 形状绘制主函数
+
+ private void MouseTouchMove(Point endP) {
+ if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false;
+ ViewboxFloatingBar.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+ List pointList;
+ StylusPointCollection point;
+ Stroke stroke;
+ var strokes = new StrokeCollection();
+ var newIniP = iniP;
+ switch (drawingShapeMode) {
+ case 1:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ pointList = new List {
+ new Point(iniP.X, iniP.Y),
+ new Point(endP.X, endP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 8:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ strokes.Add(GenerateDashedLineStrokeCollection(iniP, endP));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 18:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ strokes.Add(GenerateDotLineStrokeCollection(iniP, endP));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 2:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ double w = 15, h = 10;
+ var theta = Math.Atan2(iniP.Y - endP.Y, iniP.X - endP.X);
+ var sint = Math.Sin(theta);
+ var cost = Math.Cos(theta);
+
+ pointList = new List {
+ new Point(iniP.X, iniP.Y),
+ new Point(endP.X, endP.Y),
+ new Point(endP.X + (w * cost - h * sint), endP.Y + (w * sint + h * cost)),
+ new Point(endP.X, endP.Y),
+ new Point(endP.X + (w * cost + h * sint), endP.Y - (h * cost - w * sint))
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 15:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ var d = GetDistance(iniP, endP);
+ if (d == 0) return;
+ var sinTheta = (iniP.Y - endP.Y) / d;
+ var cosTheta = (endP.X - iniP.X) / d;
+ var tanTheta = Math.Abs(sinTheta / cosTheta);
+ double x = 25;
+ if (Math.Abs(tanTheta) < 1.0 / 12) {
+ sinTheta = 0;
+ cosTheta = 1;
+ endP.Y = iniP.Y;
+ }
+
+ if (tanTheta < 0.63 && tanTheta > 0.52) //30
+ {
+ sinTheta = sinTheta / Math.Abs(sinTheta) * 0.5;
+ cosTheta = cosTheta / Math.Abs(cosTheta) * 0.866;
+ endP.Y = iniP.Y - d * sinTheta;
+ endP.X = iniP.X + d * cosTheta;
+ }
+
+ if (tanTheta < 1.08 && tanTheta > 0.92) //45
+ {
+ sinTheta = sinTheta / Math.Abs(sinTheta) * 0.707;
+ cosTheta = cosTheta / Math.Abs(cosTheta) * 0.707;
+ endP.Y = iniP.Y - d * sinTheta;
+ endP.X = iniP.X + d * cosTheta;
+ }
+
+ if (tanTheta < 1.95 && tanTheta > 1.63) //60
+ {
+ sinTheta = sinTheta / Math.Abs(sinTheta) * 0.866;
+ cosTheta = cosTheta / Math.Abs(cosTheta) * 0.5;
+ endP.Y = iniP.Y - d * sinTheta;
+ endP.X = iniP.X + d * cosTheta;
+ }
+
+ if (Math.Abs(cosTheta / sinTheta) < 1.0 / 12) {
+ endP.X = iniP.X;
+ sinTheta = 1;
+ cosTheta = 0;
+ }
+
+ strokes.Add(GenerateLineStroke(new Point(iniP.X - 3 * x * sinTheta, iniP.Y - 3 * x * cosTheta),
+ new Point(endP.X - 3 * x * sinTheta, endP.Y - 3 * x * cosTheta)));
+ strokes.Add(GenerateLineStroke(new Point(iniP.X - x * sinTheta, iniP.Y - x * cosTheta),
+ new Point(endP.X - x * sinTheta, endP.Y - x * cosTheta)));
+ strokes.Add(GenerateLineStroke(new Point(iniP.X + x * sinTheta, iniP.Y + x * cosTheta),
+ new Point(endP.X + x * sinTheta, endP.Y + x * cosTheta)));
+ strokes.Add(GenerateLineStroke(new Point(iniP.X + 3 * x * sinTheta, iniP.Y + 3 * x * cosTheta),
+ new Point(endP.X + 3 * x * sinTheta, endP.Y + 3 * x * cosTheta)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 11:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ strokes.Add(GenerateArrowLineStroke(new Point(2 * iniP.X - (endP.X - 20), iniP.Y),
+ new Point(endP.X, iniP.Y)));
+ strokes.Add(GenerateArrowLineStroke(new Point(iniP.X, 2 * iniP.Y - (endP.Y + 20)),
+ new Point(iniP.X, endP.Y)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 12:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ if (Math.Abs(iniP.X - endP.X) < 0.01) return;
+ strokes.Add(GenerateArrowLineStroke(
+ new Point(iniP.X + (iniP.X - endP.X) / Math.Abs(iniP.X - endP.X) * 25, iniP.Y),
+ new Point(endP.X, iniP.Y)));
+ strokes.Add(GenerateArrowLineStroke(new Point(iniP.X, 2 * iniP.Y - (endP.Y + 20)),
+ new Point(iniP.X, endP.Y)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 13:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ if (Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ strokes.Add(GenerateArrowLineStroke(new Point(2 * iniP.X - (endP.X - 20), iniP.Y),
+ new Point(endP.X, iniP.Y)));
+ strokes.Add(GenerateArrowLineStroke(
+ new Point(iniP.X, iniP.Y + (iniP.Y - endP.Y) / Math.Abs(iniP.Y - endP.Y) * 25),
+ new Point(iniP.X, endP.Y)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 14:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ if (Math.Abs(iniP.X - endP.X) < 0.01 || Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ strokes.Add(GenerateArrowLineStroke(
+ new Point(iniP.X + (iniP.X - endP.X) / Math.Abs(iniP.X - endP.X) * 25, iniP.Y),
+ new Point(endP.X, iniP.Y)));
+ strokes.Add(GenerateArrowLineStroke(
+ new Point(iniP.X, iniP.Y + (iniP.Y - endP.Y) / Math.Abs(iniP.Y - endP.Y) * 25),
+ new Point(iniP.X, endP.Y)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 17:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ strokes.Add(GenerateArrowLineStroke(new Point(iniP.X, iniP.Y),
+ new Point(iniP.X + Math.Abs(endP.X - iniP.X), iniP.Y)));
+ strokes.Add(GenerateArrowLineStroke(new Point(iniP.X, iniP.Y),
+ new Point(iniP.X, iniP.Y - Math.Abs(endP.Y - iniP.Y))));
+ d = (Math.Abs(iniP.X - endP.X) + Math.Abs(iniP.Y - endP.Y)) / 2;
+ strokes.Add(GenerateArrowLineStroke(new Point(iniP.X, iniP.Y),
+ new Point(iniP.X - d / 1.76, iniP.Y + d / 1.76)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 3:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ pointList = new List {
+ new Point(iniP.X, iniP.Y),
+ new Point(iniP.X, endP.Y),
+ new Point(endP.X, endP.Y),
+ new Point(endP.X, iniP.Y),
+ new Point(iniP.X, iniP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 19:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ var a = iniP.X - endP.X;
+ var b = iniP.Y - endP.Y;
+ pointList = new List {
+ new Point(iniP.X - a, iniP.Y - b),
+ new Point(iniP.X - a, iniP.Y + b),
+ new Point(iniP.X + a, iniP.Y + b),
+ new Point(iniP.X + a, iniP.Y - b),
+ new Point(iniP.X - a, iniP.Y - b)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 4:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ pointList = GenerateEllipseGeometry(iniP, endP);
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 5:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ var R = GetDistance(iniP, endP);
+ pointList = GenerateEllipseGeometry(new Point(iniP.X - R, iniP.Y - R),
+ new Point(iniP.X + R, iniP.Y + R));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 16:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ var halfA = endP.X - iniP.X;
+ var halfB = endP.Y - iniP.Y;
+ pointList = GenerateEllipseGeometry(new Point(iniP.X - halfA, iniP.Y - halfB),
+ new Point(iniP.X + halfA, iniP.Y + halfB));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ try {
+ inkCanvas.Strokes.Remove(lastTempStroke);
+ }
+ catch { }
+
+ lastTempStroke = stroke;
+ inkCanvas.Strokes.Add(stroke);
+ break;
+ case 23:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ a = Math.Abs(endP.X - iniP.X);
+ b = Math.Abs(endP.Y - iniP.Y);
+ pointList = GenerateEllipseGeometry(new Point(iniP.X - a, iniP.Y - b),
+ new Point(iniP.X + a, iniP.Y + b));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke);
+ var c = Math.Sqrt(Math.Abs(a * a - b * b));
+ StylusPoint stylusPoint;
+ if (a > b) {
+ stylusPoint = new StylusPoint(iniP.X + c, iniP.Y, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ stylusPoint = new StylusPoint(iniP.X - c, iniP.Y, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+ else if (a < b) {
+ stylusPoint = new StylusPoint(iniP.X, iniP.Y - c, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ stylusPoint = new StylusPoint(iniP.X, iniP.Y + c, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch { }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 10:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ R = GetDistance(iniP, endP);
+ strokes = GenerateDashedLineEllipseStrokeCollection(new Point(iniP.X - R, iniP.Y - R),
+ new Point(iniP.X + R, iniP.Y + R));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 24:
+ case 25:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ //双曲线 x^2/a^2 - y^2/b^2 = 1
+ if (Math.Abs(iniP.X - endP.X) < 0.01 || Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ var pointList2 = new List();
+ var pointList3 = new List();
+ var pointList4 = new List();
+ if (drawMultiStepShapeCurrentStep == 0) {
+ //第一笔:画渐近线
+ var k = Math.Abs((endP.Y - iniP.Y) / (endP.X - iniP.X));
+ strokes.Add(
+ GenerateDashedLineStrokeCollection(new Point(2 * iniP.X - endP.X, 2 * iniP.Y - endP.Y),
+ endP));
+ strokes.Add(GenerateDashedLineStrokeCollection(new Point(2 * iniP.X - endP.X, endP.Y),
+ new Point(endP.X, 2 * iniP.Y - endP.Y)));
+ drawMultiStepShapeSpecialParameter3 = k;
+ drawMultiStepShapeSpecialStrokeCollection = strokes;
+ }
+ else {
+ //第二笔:画双曲线
+ var k = drawMultiStepShapeSpecialParameter3;
+ var isHyperbolaFocalPointOnXAxis = Math.Abs((endP.Y - iniP.Y) / (endP.X - iniP.X)) < k;
+ if (isHyperbolaFocalPointOnXAxis) {
+ // 焦点在 x 轴上
+ a = Math.Sqrt(Math.Abs((endP.X - iniP.X) * (endP.X - iniP.X) -
+ (endP.Y - iniP.Y) * (endP.Y - iniP.Y) / (k * k)));
+ b = a * k;
+ pointList = new List();
+ for (var i = a; i <= Math.Abs(endP.X - iniP.X); i += 0.5) {
+ var rY = Math.Sqrt(Math.Abs(k * k * i * i - b * b));
+ pointList.Add(new Point(iniP.X + i, iniP.Y - rY));
+ pointList2.Add(new Point(iniP.X + i, iniP.Y + rY));
+ pointList3.Add(new Point(iniP.X - i, iniP.Y - rY));
+ pointList4.Add(new Point(iniP.X - i, iniP.Y + rY));
+ }
+ }
+ else {
+ // 焦点在 y 轴上
+ a = Math.Sqrt(Math.Abs((endP.Y - iniP.Y) * (endP.Y - iniP.Y) -
+ (endP.X - iniP.X) * (endP.X - iniP.X) * (k * k)));
+ b = a / k;
+ pointList = new List();
+ for (var i = a; i <= Math.Abs(endP.Y - iniP.Y); i += 0.5) {
+ var rX = Math.Sqrt(Math.Abs(i * i / k / k - b * b));
+ pointList.Add(new Point(iniP.X - rX, iniP.Y + i));
+ pointList2.Add(new Point(iniP.X + rX, iniP.Y + i));
+ pointList3.Add(new Point(iniP.X - rX, iniP.Y - i));
+ pointList4.Add(new Point(iniP.X + rX, iniP.Y - i));
+ }
+ }
+
+ try {
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList2);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList3);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList4);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ if (drawingShapeMode == 25) {
+ //画焦点
+ c = Math.Sqrt(a * a + b * b);
+ stylusPoint = isHyperbolaFocalPointOnXAxis
+ ? new StylusPoint(iniP.X + c, iniP.Y, (float)1.0)
+ : new StylusPoint(iniP.X, iniP.Y + c, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ stylusPoint = isHyperbolaFocalPointOnXAxis
+ ? new StylusPoint(iniP.X - c, iniP.Y, (float)1.0)
+ : new StylusPoint(iniP.X, iniP.Y - c, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point)
+ { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ }
+ }
+ catch {
+ return;
+ }
+ }
+
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 20:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ //抛物线 y=ax^2
+ if (Math.Abs(iniP.X - endP.X) < 0.01 || Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ a = (iniP.Y - endP.Y) / ((iniP.X - endP.X) * (iniP.X - endP.X));
+ pointList = new List();
+ pointList2 = new List();
+ for (var i = 0.0; i <= Math.Abs(endP.X - iniP.X); i += 0.5) {
+ pointList.Add(new Point(iniP.X + i, iniP.Y - a * i * i));
+ pointList2.Add(new Point(iniP.X - i, iniP.Y - a * i * i));
+ }
+
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList2);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 21:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ //抛物线 y^2=ax
+ if (Math.Abs(iniP.X - endP.X) < 0.01 || Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ a = (iniP.X - endP.X) / ((iniP.Y - endP.Y) * (iniP.Y - endP.Y));
+ pointList = new List();
+ pointList2 = new List();
+ for (var i = 0.0; i <= Math.Abs(endP.Y - iniP.Y); i += 0.5) {
+ pointList.Add(new Point(iniP.X - a * i * i, iniP.Y + i));
+ pointList2.Add(new Point(iniP.X - a * i * i, iniP.Y - i));
+ }
+
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList2);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 22:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ //抛物线 y^2=ax, 含焦点
+ if (Math.Abs(iniP.X - endP.X) < 0.01 || Math.Abs(iniP.Y - endP.Y) < 0.01) return;
+ var p = (iniP.Y - endP.Y) * (iniP.Y - endP.Y) / (2 * (iniP.X - endP.X));
+ a = 0.5 / p;
+ pointList = new List();
+ pointList2 = new List();
+ for (var i = 0.0; i <= Math.Abs(endP.Y - iniP.Y); i += 0.5) {
+ pointList.Add(new Point(iniP.X - a * i * i, iniP.Y + i));
+ pointList2.Add(new Point(iniP.X - a * i * i, iniP.Y - i));
+ }
+
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ point = new StylusPointCollection(pointList2);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ stylusPoint = new StylusPoint(iniP.X - p / 2, iniP.Y, (float)1.0);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 6:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ newIniP = iniP;
+ if (iniP.Y > endP.Y) {
+ newIniP = new Point(iniP.X, endP.Y);
+ endP = new Point(endP.X, iniP.Y);
+ }
+
+ var topA = Math.Abs(newIniP.X - endP.X);
+ var topB = topA / 2.646;
+ //顶部椭圆
+ pointList = GenerateEllipseGeometry(new Point(newIniP.X, newIniP.Y - topB / 2),
+ new Point(endP.X, newIniP.Y + topB / 2));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ //底部椭圆
+ pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - topB / 2),
+ new Point(endP.X, endP.Y + topB / 2), false, true);
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ strokes.Add(GenerateDashedLineEllipseStrokeCollection(new Point(newIniP.X, endP.Y - topB / 2),
+ new Point(endP.X, endP.Y + topB / 2), true, false));
+ //左侧
+ pointList = new List {
+ new Point(newIniP.X, newIniP.Y),
+ new Point(newIniP.X, endP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ //右侧
+ pointList = new List {
+ new Point(endP.X, newIniP.Y),
+ new Point(endP.X, endP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 7:
+ _currentCommitType = CommitReason.ShapeDrawing;
+ if (iniP.Y > endP.Y) {
+ newIniP = new Point(iniP.X, endP.Y);
+ endP = new Point(endP.X, iniP.Y);
+ }
+
+ var bottomA = Math.Abs(newIniP.X - endP.X);
+ var bottomB = bottomA / 2.646;
+ //底部椭圆
+ pointList = GenerateEllipseGeometry(new Point(newIniP.X, endP.Y - bottomB / 2),
+ new Point(endP.X, endP.Y + bottomB / 2), false, true);
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ strokes.Add(GenerateDashedLineEllipseStrokeCollection(new Point(newIniP.X, endP.Y - bottomB / 2),
+ new Point(endP.X, endP.Y + bottomB / 2), true, false));
+ //左侧
+ pointList = new List {
+ new Point((newIniP.X + endP.X) / 2, newIniP.Y),
+ new Point(newIniP.X, endP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ //右侧
+ pointList = new List {
+ new Point((newIniP.X + endP.X) / 2, newIniP.Y),
+ new Point(endP.X, endP.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ break;
+ case 9:
+ // 画长方体
+ _currentCommitType = CommitReason.ShapeDrawing;
+ if (isFirstTouchCuboid) {
+ //分开画线条方便后期单独擦除某一条棱
+ strokes.Add(GenerateLineStroke(new Point(iniP.X, iniP.Y), new Point(iniP.X, endP.Y)));
+ strokes.Add(GenerateLineStroke(new Point(iniP.X, endP.Y), new Point(endP.X, endP.Y)));
+ strokes.Add(GenerateLineStroke(new Point(endP.X, endP.Y), new Point(endP.X, iniP.Y)));
+ strokes.Add(GenerateLineStroke(new Point(iniP.X, iniP.Y), new Point(endP.X, iniP.Y)));
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ CuboidFrontRectIniP = iniP;
+ CuboidFrontRectEndP = endP;
+ }
+ else {
+ d = CuboidFrontRectIniP.Y - endP.Y;
+ if (d < 0) d = -d; //就是懒不想做反向的,不要让我去做,想做自己做好之后 Pull Request
+ a = CuboidFrontRectEndP.X - CuboidFrontRectIniP.X; //正面矩形长
+ b = CuboidFrontRectEndP.Y - CuboidFrontRectIniP.Y; //正面矩形宽
+
+ //横上
+ var newLineIniP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectIniP.Y - d);
+ var newLineEndP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectIniP.Y - d);
+ pointList = new List { newLineIniP, newLineEndP };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ //横下 (虚线)
+ newLineIniP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectEndP.Y - d);
+ newLineEndP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectEndP.Y - d);
+ strokes.Add(GenerateDashedLineStrokeCollection(newLineIniP, newLineEndP));
+ //斜左上
+ newLineIniP = new Point(CuboidFrontRectIniP.X, CuboidFrontRectIniP.Y);
+ newLineEndP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectIniP.Y - d);
+ pointList = new List { newLineIniP, newLineEndP };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ //斜右上
+ newLineIniP = new Point(CuboidFrontRectEndP.X, CuboidFrontRectIniP.Y);
+ newLineEndP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectIniP.Y - d);
+ pointList = new List { newLineIniP, newLineEndP };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ //斜左下 (虚线)
+ newLineIniP = new Point(CuboidFrontRectIniP.X, CuboidFrontRectEndP.Y);
+ newLineEndP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectEndP.Y - d);
+ strokes.Add(GenerateDashedLineStrokeCollection(newLineIniP, newLineEndP));
+ //斜右下
+ newLineIniP = new Point(CuboidFrontRectEndP.X, CuboidFrontRectEndP.Y);
+ newLineEndP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectEndP.Y - d);
+ pointList = new List { newLineIniP, newLineEndP };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+ //竖左 (虚线)
+ newLineIniP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectIniP.Y - d);
+ newLineEndP = new Point(CuboidFrontRectIniP.X + d, CuboidFrontRectEndP.Y - d);
+ strokes.Add(GenerateDashedLineStrokeCollection(newLineIniP, newLineEndP));
+ //竖右
+ newLineIniP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectIniP.Y - d);
+ newLineEndP = new Point(CuboidFrontRectEndP.X + d, CuboidFrontRectEndP.Y - d);
+ pointList = new List { newLineIniP, newLineEndP };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() };
+ strokes.Add(stroke.Clone());
+
+ try {
+ inkCanvas.Strokes.Remove(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ lastTempStrokeCollection = strokes;
+ inkCanvas.Strokes.Add(strokes);
+ }
+
+ break;
+ }
+ }
+
+ #endregion
+
+ private bool isFirstTouchCuboid = true;
+ private Point CuboidFrontRectIniP = new Point();
+ private Point CuboidFrontRectEndP = new Point();
+
+ private void Main_Grid_TouchUp(object sender, TouchEventArgs e) {
+
+ inkCanvas.ReleaseAllTouchCaptures();
+ ViewboxFloatingBar.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+
+ inkCanvas_MouseUp(sender, null);
+ if (dec.Count == 0) isWaitUntilNextTouchDown = false;
+ }
+
+ private Stroke lastTempStroke = null;
+ private StrokeCollection lastTempStrokeCollection = new StrokeCollection();
+
+ private bool isWaitUntilNextTouchDown = false;
+
+ private List GenerateEllipseGeometry(Point st, Point ed, bool isDrawTop = true,
+ bool isDrawBottom = true) {
+ var a = 0.5 * (ed.X - st.X);
+ var b = 0.5 * (ed.Y - st.Y);
+ var pointList = new List();
+ if (isDrawTop && isDrawBottom) {
+ for (double r = 0; r <= 2 * Math.PI; r = r + 0.01)
+ pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r),
+ 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
+ }
+ else {
+ if (isDrawBottom)
+ for (double r = 0; r <= Math.PI; r = r + 0.01)
+ pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r),
+ 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
+ if (isDrawTop)
+ for (var r = Math.PI; r <= 2 * Math.PI; r = r + 0.01)
+ pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r),
+ 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
+ }
+
+ return pointList;
+ }
+
+ private StrokeCollection GenerateDashedLineEllipseStrokeCollection(Point st, Point ed, bool isDrawTop = true,
+ bool isDrawBottom = true) {
+ var a = 0.5 * (ed.X - st.X);
+ var b = 0.5 * (ed.Y - st.Y);
+ var step = 0.05;
+ var pointList = new List();
+ StylusPointCollection point;
+ Stroke stroke;
+ var strokes = new StrokeCollection();
+ if (isDrawBottom)
+ for (var i = 0.0; i < 1.0; i += step * 1.66) {
+ pointList = new List();
+ for (var r = Math.PI * i; r <= Math.PI * (i + step); r = r + 0.01)
+ pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r),
+ 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+
+ if (isDrawTop)
+ for (var i = 1.0; i < 2.0; i += step * 1.66) {
+ pointList = new List();
+ for (var r = Math.PI * i; r <= Math.PI * (i + step); r = r + 0.01)
+ pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r),
+ 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+
+ return strokes;
+ }
+
+ private Stroke GenerateLineStroke(Point st, Point ed) {
+ var pointList = new List();
+ StylusPointCollection point;
+ Stroke stroke;
+ pointList = new List {
+ new Point(st.X, st.Y),
+ new Point(ed.X, ed.Y)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ return stroke;
+ }
+
+ private Stroke GenerateArrowLineStroke(Point st, Point ed) {
+ var pointList = new List();
+ StylusPointCollection point;
+ Stroke stroke;
+
+ double w = 20, h = 7;
+ var theta = Math.Atan2(st.Y - ed.Y, st.X - ed.X);
+ var sint = Math.Sin(theta);
+ var cost = Math.Cos(theta);
+
+ pointList = new List {
+ new Point(st.X, st.Y),
+ new Point(ed.X, ed.Y),
+ new Point(ed.X + (w * cost - h * sint), ed.Y + (w * sint + h * cost)),
+ new Point(ed.X, ed.Y),
+ new Point(ed.X + (w * cost + h * sint), ed.Y - (h * cost - w * sint))
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ return stroke;
+ }
+
+
+ private StrokeCollection GenerateDashedLineStrokeCollection(Point st, Point ed) {
+ double step = 5;
+ var pointList = new List();
+ StylusPointCollection point;
+ Stroke stroke;
+ var strokes = new StrokeCollection();
+ var d = GetDistance(st, ed);
+ var sinTheta = (ed.Y - st.Y) / d;
+ var cosTheta = (ed.X - st.X) / d;
+ for (var i = 0.0; i < d; i += step * 2.76) {
+ pointList = new List {
+ new Point(st.X + i * cosTheta, st.Y + i * sinTheta),
+ new Point(st.X + Math.Min(i + step, d) * cosTheta, st.Y + Math.Min(i + step, d) * sinTheta)
+ };
+ point = new StylusPointCollection(pointList);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+
+ return strokes;
+ }
+
+ private StrokeCollection GenerateDotLineStrokeCollection(Point st, Point ed) {
+ double step = 3;
+ var pointList = new List();
+ StylusPointCollection point;
+ Stroke stroke;
+ var strokes = new StrokeCollection();
+ var d = GetDistance(st, ed);
+ var sinTheta = (ed.Y - st.Y) / d;
+ var cosTheta = (ed.X - st.X) / d;
+ for (var i = 0.0; i < d; i += step * 2.76) {
+ var stylusPoint = new StylusPoint(st.X + i * cosTheta, st.Y + i * sinTheta, (float)0.8);
+ point = new StylusPointCollection();
+ point.Add(stylusPoint);
+ stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ strokes.Add(stroke.Clone());
+ }
+
+ return strokes;
+ }
+
+ private bool isMouseDown = false;
+
+ private void inkCanvas_MouseDown(object sender, MouseButtonEventArgs e) {
+ inkCanvas.CaptureMouse();
+ ViewboxFloatingBar.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+
+ isMouseDown = true;
+ if (NeedUpdateIniP()) iniP = e.GetPosition(inkCanvas);
+ }
+
+ private void inkCanvas_MouseMove(object sender, MouseEventArgs e) {
+ if (isMouseDown) MouseTouchMove(e.GetPosition(inkCanvas));
+ }
+
+ private void inkCanvas_MouseUp(object sender, MouseButtonEventArgs e) {
+ inkCanvas.ReleaseMouseCapture();
+ ViewboxFloatingBar.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+
+ if (drawingShapeMode == 5) {
+ if (lastTempStroke != null) {
+ var circle = new Circle(new Point(), 0, lastTempStroke);
+ circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
+ circle.Centroid = new Point(
+ (circle.Stroke.StylusPoints[0].X +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
+ (circle.Stroke.StylusPoints[0].Y +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2);
+ circles.Add(circle);
+ }
+
+ if (lastIsInMultiTouchMode) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ lastIsInMultiTouchMode = false;
+ }
+ }
+
+ if (drawingShapeMode != 9 && drawingShapeMode != 0 && drawingShapeMode != 24 && drawingShapeMode != 25) {
+ if (isLongPressSelected) { }
+ else {
+ BtnPen_Click(null, null); //画完一次还原到笔模式
+ if (lastIsInMultiTouchMode) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ lastIsInMultiTouchMode = false;
+ }
+ }
+ }
+
+ if (drawingShapeMode == 9) {
+ if (isFirstTouchCuboid) {
+ if (CuboidStrokeCollection == null) CuboidStrokeCollection = new StrokeCollection();
+ isFirstTouchCuboid = false;
+ var newIniP = new Point(Math.Min(CuboidFrontRectIniP.X, CuboidFrontRectEndP.X),
+ Math.Min(CuboidFrontRectIniP.Y, CuboidFrontRectEndP.Y));
+ var newEndP = new Point(Math.Max(CuboidFrontRectIniP.X, CuboidFrontRectEndP.X),
+ Math.Max(CuboidFrontRectIniP.Y, CuboidFrontRectEndP.Y));
+ CuboidFrontRectIniP = newIniP;
+ CuboidFrontRectEndP = newEndP;
+ try {
+ CuboidStrokeCollection.Add(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+ }
+ else {
+ BtnPen_Click(null, null); //画完还原到笔模式
+ if (lastIsInMultiTouchMode) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ lastIsInMultiTouchMode = false;
+ }
+
+ if (_currentCommitType == CommitReason.ShapeDrawing) {
+ try {
+ CuboidStrokeCollection.Add(lastTempStrokeCollection);
+ }
+ catch {
+ Trace.WriteLine("lastTempStrokeCollection failed.");
+ }
+
+ _currentCommitType = CommitReason.UserInput;
+ timeMachine.CommitStrokeUserInputHistory(CuboidStrokeCollection);
+ CuboidStrokeCollection = null;
+ }
+ }
+ }
+
+ if (drawingShapeMode == 24 || drawingShapeMode == 25) {
+ if (drawMultiStepShapeCurrentStep == 0) {
+ drawMultiStepShapeCurrentStep = 1;
+ }
+ else {
+ drawMultiStepShapeCurrentStep = 0;
+ if (drawMultiStepShapeSpecialStrokeCollection != null) {
+ var opFlag = false;
+ switch (Settings.Canvas.HyperbolaAsymptoteOption) {
+ case OptionalOperation.Yes:
+ opFlag = true;
+ break;
+ case OptionalOperation.No:
+ opFlag = false;
+ break;
+ case OptionalOperation.Ask:
+ opFlag = MessageBox.Show("是否移除渐近线?", "Ink Canvas", MessageBoxButton.YesNo) !=
+ MessageBoxResult.Yes;
+ break;
+ }
+
+ ;
+ if (!opFlag) inkCanvas.Strokes.Remove(drawMultiStepShapeSpecialStrokeCollection);
+ }
+
+ BtnPen_Click(null, null); //画完还原到笔模式
+ if (lastIsInMultiTouchMode) {
+ ToggleSwitchEnableMultiTouchMode.IsOn = true;
+ lastIsInMultiTouchMode = false;
+ }
+ }
+ }
+
+ isMouseDown = false;
+ if (ReplacedStroke != null || AddedStroke != null) {
+ timeMachine.CommitStrokeEraseHistory(ReplacedStroke, AddedStroke);
+ AddedStroke = null;
+ ReplacedStroke = null;
+ }
+
+ if (_currentCommitType == CommitReason.ShapeDrawing && drawingShapeMode != 9) {
+ _currentCommitType = CommitReason.UserInput;
+ StrokeCollection collection = null;
+ if (lastTempStrokeCollection != null && lastTempStrokeCollection.Count > 0)
+ collection = lastTempStrokeCollection;
+ else if (lastTempStroke != null) collection = new StrokeCollection() { lastTempStroke };
+ if (collection != null) timeMachine.CommitStrokeUserInputHistory(collection);
+ }
+
+ lastTempStroke = null;
+ lastTempStrokeCollection = null;
+
+ if (StrokeManipulationHistory?.Count > 0)
+ {
+ timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
+ foreach (var item in StrokeManipulationHistory)
+ {
+ StrokeInitialHistory[item.Key] = item.Value.Item2;
+ }
+ StrokeManipulationHistory = null;
+ }
+
+ if (DrawingAttributesHistory.Count > 0)
+ {
+ timeMachine.CommitStrokeDrawingAttributesHistory(DrawingAttributesHistory);
+ DrawingAttributesHistory = new Dictionary>();
+ foreach (var item in DrawingAttributesHistoryFlag)
+ {
+ item.Value.Clear();
+ }
+ }
+
+ if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = true;
+ }
+
+ private bool NeedUpdateIniP() {
+ if (drawingShapeMode == 24 || drawingShapeMode == 25)
+ if (drawMultiStepShapeCurrentStep == 1)
+ return false;
+ return true;
+ }
+
+ private void MainWindow_OnMouseMove(object sender, MouseEventArgs e) {
+ if (e.StylusDevice == null) {
+ System.Windows.Forms.Cursor.Show();
+ } else {
+ System.Windows.Forms.Cursor.Hide();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs
new file mode 100644
index 00000000..e31f1e09
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs
@@ -0,0 +1,544 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using Point = System.Windows.Point;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private StrokeCollection newStrokes = new StrokeCollection();
+ private List circles = new List();
+
+ private void inkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) {
+ if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false;
+
+ try {
+ inkCanvas.Opacity = 1;
+ if (Settings.InkToShape.IsInkToShapeEnabled && !Environment.Is64BitProcess) {
+ void InkToShapeProcess() {
+ try {
+ newStrokes.Add(e.Stroke);
+ if (newStrokes.Count > 4) newStrokes.RemoveAt(0);
+ for (var i = 0; i < newStrokes.Count; i++)
+ if (!inkCanvas.Strokes.Contains(newStrokes[i]))
+ newStrokes.RemoveAt(i--);
+
+ for (var i = 0; i < circles.Count; i++)
+ if (!inkCanvas.Strokes.Contains(circles[i].Stroke))
+ circles.RemoveAt(i);
+
+ var strokeReco = new StrokeCollection();
+ var result = InkRecognizeHelper.RecognizeShape(newStrokes);
+ for (var i = newStrokes.Count - 1; i >= 0; i--) {
+ strokeReco.Add(newStrokes[i]);
+ var newResult = InkRecognizeHelper.RecognizeShape(strokeReco);
+ if (newResult.InkDrawingNode.GetShapeName() == "Circle" ||
+ newResult.InkDrawingNode.GetShapeName() == "Ellipse") {
+ result = newResult;
+ break;
+ }
+ //Label.Visibility = Visibility.Visible;
+ //Label.Content = circles.Count.ToString() + "\n" + newResult.InkDrawingNode.GetShapeName();
+ }
+
+ if (result.InkDrawingNode.GetShapeName() == "Circle" &&
+ Settings.InkToShape.IsInkToShapeRounded == true) {
+ var shape = result.InkDrawingNode.GetShape();
+ if (shape.Width > 75) {
+ foreach (var circle in circles)
+ //判断是否画同心圆
+ if (Math.Abs(result.Centroid.X - circle.Centroid.X) / shape.Width < 0.12 &&
+ Math.Abs(result.Centroid.Y - circle.Centroid.Y) / shape.Width < 0.12) {
+ result.Centroid = circle.Centroid;
+ break;
+ }
+ else {
+ var d = (result.Centroid.X - circle.Centroid.X) *
+ (result.Centroid.X - circle.Centroid.X) +
+ (result.Centroid.Y - circle.Centroid.Y) *
+ (result.Centroid.Y - circle.Centroid.Y);
+ d = Math.Sqrt(d);
+ //判断是否画外切圆
+ var x = shape.Width / 2.0 + circle.R - d;
+ if (Math.Abs(x) / shape.Width < 0.1) {
+ var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d;
+ var cosTheta = (result.Centroid.X - circle.Centroid.X) / d;
+ var newX = result.Centroid.X + x * cosTheta;
+ var newY = result.Centroid.Y + x * sinTheta;
+ result.Centroid = new Point(newX, newY);
+ }
+
+ //判断是否画外切圆
+ x = Math.Abs(circle.R - shape.Width / 2.0) - d;
+ if (Math.Abs(x) / shape.Width < 0.1) {
+ var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d;
+ var cosTheta = (result.Centroid.X - circle.Centroid.X) / d;
+ var newX = result.Centroid.X + x * cosTheta;
+ var newY = result.Centroid.Y + x * sinTheta;
+ result.Centroid = new Point(newX, newY);
+ }
+ }
+
+ var iniP = new Point(result.Centroid.X - shape.Width / 2,
+ result.Centroid.Y - shape.Height / 2);
+ var endP = new Point(result.Centroid.X + shape.Width / 2,
+ result.Centroid.Y + shape.Height / 2);
+ var pointList = GenerateEllipseGeometry(iniP, endP);
+ var point = new StylusPointCollection(pointList);
+ var stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ circles.Add(new Circle(result.Centroid, shape.Width / 2.0, stroke));
+ SetNewBackupOfStroke();
+ _currentCommitType = CommitReason.ShapeRecognition;
+ inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
+ inkCanvas.Strokes.Add(stroke);
+ _currentCommitType = CommitReason.UserInput;
+ newStrokes = new StrokeCollection();
+ }
+ }
+ else if (result.InkDrawingNode.GetShapeName().Contains("Ellipse") &&
+ Settings.InkToShape.IsInkToShapeRounded == true) {
+ var shape = result.InkDrawingNode.GetShape();
+ //var shape1 = result.InkDrawingNode.GetShape();
+ //shape1.Fill = Brushes.Gray;
+ //Canvas.Children.Add(shape1);
+ var p = result.InkDrawingNode.HotPoints;
+ var a = GetDistance(p[0], p[2]) / 2; //长半轴
+ var b = GetDistance(p[1], p[3]) / 2; //短半轴
+ if (a < b) {
+ var t = a;
+ a = b;
+ b = t;
+ }
+
+ result.Centroid = new Point((p[0].X + p[2].X) / 2, (p[0].Y + p[2].Y) / 2);
+ var needRotation = true;
+
+ if (shape.Width > 75 || (shape.Height > 75 && p.Count == 4)) {
+ var iniP = new Point(result.Centroid.X - shape.Width / 2,
+ result.Centroid.Y - shape.Height / 2);
+ var endP = new Point(result.Centroid.X + shape.Width / 2,
+ result.Centroid.Y + shape.Height / 2);
+
+ foreach (var circle in circles)
+ //判断是否画同心椭圆
+ if (Math.Abs(result.Centroid.X - circle.Centroid.X) / a < 0.2 &&
+ Math.Abs(result.Centroid.Y - circle.Centroid.Y) / a < 0.2) {
+ result.Centroid = circle.Centroid;
+ iniP = new Point(result.Centroid.X - shape.Width / 2,
+ result.Centroid.Y - shape.Height / 2);
+ endP = new Point(result.Centroid.X + shape.Width / 2,
+ result.Centroid.Y + shape.Height / 2);
+
+ //再判断是否与圆相切
+ if (Math.Abs(a - circle.R) / a < 0.2) {
+ if (shape.Width >= shape.Height) {
+ iniP.X = result.Centroid.X - circle.R;
+ endP.X = result.Centroid.X + circle.R;
+ iniP.Y = result.Centroid.Y - b;
+ endP.Y = result.Centroid.Y + b;
+ }
+ else {
+ iniP.Y = result.Centroid.Y - circle.R;
+ endP.Y = result.Centroid.Y + circle.R;
+ iniP.X = result.Centroid.X - a;
+ endP.X = result.Centroid.X + a;
+ }
+ }
+
+ break;
+ }
+ else if (Math.Abs(result.Centroid.X - circle.Centroid.X) / a < 0.2) {
+ var sinTheta = Math.Abs(circle.Centroid.Y - result.Centroid.Y) /
+ circle.R;
+ var cosTheta = Math.Sqrt(1 - sinTheta * sinTheta);
+ var newA = circle.R * cosTheta;
+ if (circle.R * sinTheta / circle.R < 0.9 && a / b > 2 &&
+ Math.Abs(newA - a) / newA < 0.3) {
+ iniP.X = circle.Centroid.X - newA;
+ endP.X = circle.Centroid.X + newA;
+ iniP.Y = result.Centroid.Y - newA / 5;
+ endP.Y = result.Centroid.Y + newA / 5;
+
+ var topB = endP.Y - iniP.Y;
+
+ SetNewBackupOfStroke();
+ _currentCommitType = CommitReason.ShapeRecognition;
+ inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
+ newStrokes = new StrokeCollection();
+
+ var _pointList = GenerateEllipseGeometry(iniP, endP, false, true);
+ var _point = new StylusPointCollection(_pointList);
+ var _stroke = new Stroke(_point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ var _dashedLineStroke =
+ GenerateDashedLineEllipseStrokeCollection(iniP, endP, true, false);
+ var strokes = new StrokeCollection() {
+ _stroke,
+ _dashedLineStroke
+ };
+ inkCanvas.Strokes.Add(strokes);
+ _currentCommitType = CommitReason.UserInput;
+ return;
+ }
+ }
+ else if (Math.Abs(result.Centroid.Y - circle.Centroid.Y) / a < 0.2) {
+ var cosTheta = Math.Abs(circle.Centroid.X - result.Centroid.X) /
+ circle.R;
+ var sinTheta = Math.Sqrt(1 - cosTheta * cosTheta);
+ var newA = circle.R * sinTheta;
+ if (circle.R * sinTheta / circle.R < 0.9 && a / b > 2 &&
+ Math.Abs(newA - a) / newA < 0.3) {
+ iniP.X = result.Centroid.X - newA / 5;
+ endP.X = result.Centroid.X + newA / 5;
+ iniP.Y = circle.Centroid.Y - newA;
+ endP.Y = circle.Centroid.Y + newA;
+ needRotation = false;
+ }
+ }
+
+ //纠正垂直与水平关系
+ var newPoints = FixPointsDirection(p[0], p[2]);
+ p[0] = newPoints[0];
+ p[2] = newPoints[1];
+ newPoints = FixPointsDirection(p[1], p[3]);
+ p[1] = newPoints[0];
+ p[3] = newPoints[1];
+
+ var pointList = GenerateEllipseGeometry(iniP, endP);
+ var point = new StylusPointCollection(pointList);
+ var stroke = new Stroke(point) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+
+ if (needRotation) {
+ var m = new Matrix();
+ var fe = e.Source as FrameworkElement;
+ var tanTheta = (p[2].Y - p[0].Y) / (p[2].X - p[0].X);
+ var theta = Math.Atan(tanTheta);
+ m.RotateAt(theta * 180.0 / Math.PI, result.Centroid.X, result.Centroid.Y);
+ stroke.Transform(m, false);
+ }
+
+ SetNewBackupOfStroke();
+ _currentCommitType = CommitReason.ShapeRecognition;
+ inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
+ inkCanvas.Strokes.Add(stroke);
+ _currentCommitType = CommitReason.UserInput;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ newStrokes = new StrokeCollection();
+ }
+ }
+ else if (result.InkDrawingNode.GetShapeName().Contains("Triangle") &&
+ Settings.InkToShape.IsInkToShapeTriangle == true) {
+ var shape = result.InkDrawingNode.GetShape();
+ var p = result.InkDrawingNode.HotPoints;
+ if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) -
+ Math.Min(Math.Min(p[0].X, p[1].X), p[2].X) >= 100 ||
+ Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y) -
+ Math.Min(Math.Min(p[0].Y, p[1].Y), p[2].Y) >= 100) &&
+ result.InkDrawingNode.HotPoints.Count == 3) {
+ //纠正垂直与水平关系
+ var newPoints = FixPointsDirection(p[0], p[1]);
+ p[0] = newPoints[0];
+ p[1] = newPoints[1];
+ newPoints = FixPointsDirection(p[0], p[2]);
+ p[0] = newPoints[0];
+ p[2] = newPoints[1];
+ newPoints = FixPointsDirection(p[1], p[2]);
+ p[1] = newPoints[0];
+ p[2] = newPoints[1];
+
+ var pointList = p.ToList();
+ //pointList.Add(p[0]);
+ var point = new StylusPointCollection(pointList);
+ var stroke = new Stroke(GenerateFakePressureTriangle(point)) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ SetNewBackupOfStroke();
+ _currentCommitType = CommitReason.ShapeRecognition;
+ inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
+ inkCanvas.Strokes.Add(stroke);
+ _currentCommitType = CommitReason.UserInput;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ newStrokes = new StrokeCollection();
+ }
+ }
+ else if ((result.InkDrawingNode.GetShapeName().Contains("Rectangle") ||
+ result.InkDrawingNode.GetShapeName().Contains("Diamond") ||
+ result.InkDrawingNode.GetShapeName().Contains("Parallelogram") ||
+ result.InkDrawingNode.GetShapeName().Contains("Square") ||
+ result.InkDrawingNode.GetShapeName().Contains("Trapezoid")) &&
+ Settings.InkToShape.IsInkToShapeRectangle == true) {
+ var shape = result.InkDrawingNode.GetShape();
+ var p = result.InkDrawingNode.HotPoints;
+ if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) -
+ Math.Min(Math.Min(Math.Min(p[0].X, p[1].X), p[2].X), p[3].X) >= 100 ||
+ Math.Max(Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y), p[3].Y) -
+ Math.Min(Math.Min(Math.Min(p[0].Y, p[1].Y), p[2].Y), p[3].Y) >= 100) &&
+ result.InkDrawingNode.HotPoints.Count == 4) {
+ //纠正垂直与水平关系
+ var newPoints = FixPointsDirection(p[0], p[1]);
+ p[0] = newPoints[0];
+ p[1] = newPoints[1];
+ newPoints = FixPointsDirection(p[1], p[2]);
+ p[1] = newPoints[0];
+ p[2] = newPoints[1];
+ newPoints = FixPointsDirection(p[2], p[3]);
+ p[2] = newPoints[0];
+ p[3] = newPoints[1];
+ newPoints = FixPointsDirection(p[3], p[0]);
+ p[3] = newPoints[0];
+ p[0] = newPoints[1];
+
+ var pointList = p.ToList();
+ pointList.Add(p[0]);
+ var point = new StylusPointCollection(pointList);
+ var stroke = new Stroke(GenerateFakePressureRectangle(point)) {
+ DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
+ };
+ SetNewBackupOfStroke();
+ _currentCommitType = CommitReason.ShapeRecognition;
+ inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes);
+ inkCanvas.Strokes.Add(stroke);
+ _currentCommitType = CommitReason.UserInput;
+ GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
+ newStrokes = new StrokeCollection();
+ }
+ }
+ }
+ catch { }
+ }
+
+ InkToShapeProcess();
+ }
+
+ foreach (var stylusPoint in e.Stroke.StylusPoints)
+ //LogHelper.WriteLogToFile(stylusPoint.PressureFactor.ToString(), LogHelper.LogType.Info);
+ // 检查是否是压感笔书写
+ //if (stylusPoint.PressureFactor != 0.5 && stylusPoint.PressureFactor != 0)
+ if ((stylusPoint.PressureFactor > 0.501 || stylusPoint.PressureFactor < 0.5) &&
+ stylusPoint.PressureFactor != 0)
+ return;
+
+ try {
+ if (e.Stroke.StylusPoints.Count > 3) {
+ var random = new Random();
+ var _speed = GetPointSpeed(
+ e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint(),
+ e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint(),
+ e.Stroke.StylusPoints[random.Next(0, e.Stroke.StylusPoints.Count - 1)].ToPoint());
+
+ RandWindow.randSeed = (int)(_speed * 100000 * 1000);
+ }
+ }
+ catch { }
+
+ switch (Settings.Canvas.InkStyle) {
+ case 1:
+ if (penType == 0)
+ try {
+ var stylusPoints = new StylusPointCollection();
+ var n = e.Stroke.StylusPoints.Count - 1;
+ var s = "";
+
+ for (var i = 0; i <= n; i++) {
+ var speed = GetPointSpeed(e.Stroke.StylusPoints[Math.Max(i - 1, 0)].ToPoint(),
+ e.Stroke.StylusPoints[i].ToPoint(),
+ e.Stroke.StylusPoints[Math.Min(i + 1, n)].ToPoint());
+ s += speed.ToString() + "\t";
+ var point = new StylusPoint();
+ if (speed >= 0.25)
+ point.PressureFactor = (float)(0.5 - 0.3 * (Math.Min(speed, 1.5) - 0.3) / 1.2);
+ else if (speed >= 0.05)
+ point.PressureFactor = (float)0.5;
+ else
+ point.PressureFactor = (float)(0.5 + 0.4 * (0.05 - speed) / 0.05);
+
+ point.X = e.Stroke.StylusPoints[i].X;
+ point.Y = e.Stroke.StylusPoints[i].Y;
+ stylusPoints.Add(point);
+ }
+
+ e.Stroke.StylusPoints = stylusPoints;
+ }
+ catch { }
+
+ break;
+ case 0:
+ if (penType == 0)
+ try {
+ var stylusPoints = new StylusPointCollection();
+ var n = e.Stroke.StylusPoints.Count - 1;
+ var pressure = 0.1;
+ var x = 10;
+ if (n == 1) return;
+ if (n >= x) {
+ for (var i = 0; i < n - x; i++) {
+ var point = new StylusPoint();
+
+ point.PressureFactor = (float)0.5;
+ point.X = e.Stroke.StylusPoints[i].X;
+ point.Y = e.Stroke.StylusPoints[i].Y;
+ stylusPoints.Add(point);
+ }
+
+ for (var i = n - x; i <= n; i++) {
+ var point = new StylusPoint();
+
+ point.PressureFactor = (float)((0.5 - pressure) * (n - i) / x + pressure);
+ point.X = e.Stroke.StylusPoints[i].X;
+ point.Y = e.Stroke.StylusPoints[i].Y;
+ stylusPoints.Add(point);
+ }
+ }
+ else {
+ for (var i = 0; i <= n; i++) {
+ var point = new StylusPoint();
+
+ point.PressureFactor = (float)(0.4 * (n - i) / n + pressure);
+ point.X = e.Stroke.StylusPoints[i].X;
+ point.Y = e.Stroke.StylusPoints[i].Y;
+ stylusPoints.Add(point);
+ }
+ }
+
+ e.Stroke.StylusPoints = stylusPoints;
+ }
+ catch { }
+
+ break;
+ }
+ }
+ catch { }
+
+ if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = true;
+ }
+
+ private void SetNewBackupOfStroke() {
+ lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
+ var whiteboardIndex = CurrentWhiteboardIndex;
+ if (currentMode == 0) whiteboardIndex = 0;
+
+ strokeCollections[whiteboardIndex] = lastTouchDownStrokeCollection;
+ }
+
+ public double GetDistance(Point point1, Point point2) {
+ return Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) +
+ (point1.Y - point2.Y) * (point1.Y - point2.Y));
+ }
+
+ public double GetPointSpeed(Point point1, Point point2, Point point3) {
+ return (Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) +
+ (point1.Y - point2.Y) * (point1.Y - point2.Y))
+ + Math.Sqrt((point3.X - point2.X) * (point3.X - point2.X) +
+ (point3.Y - point2.Y) * (point3.Y - point2.Y)))
+ / 20;
+ }
+
+ public Point[] FixPointsDirection(Point p1, Point p2) {
+ if (Math.Abs(p1.X - p2.X) / Math.Abs(p1.Y - p2.Y) > 8) {
+ //水平
+ var x = Math.Abs(p1.Y - p2.Y) / 2;
+ if (p1.Y > p2.Y) {
+ p1.Y -= x;
+ p2.Y += x;
+ }
+ else {
+ p1.Y += x;
+ p2.Y -= x;
+ }
+ }
+ else if (Math.Abs(p1.Y - p2.Y) / Math.Abs(p1.X - p2.X) > 8) {
+ //垂直
+ var x = Math.Abs(p1.X - p2.X) / 2;
+ if (p1.X > p2.X) {
+ p1.X -= x;
+ p2.X += x;
+ }
+ else {
+ p1.X += x;
+ p2.X -= x;
+ }
+ }
+
+ return new Point[2] { p1, p2 };
+ }
+
+ public StylusPointCollection GenerateFakePressureTriangle(StylusPointCollection points) {
+ if (Settings.InkToShape.IsInkToShapeNoFakePressureTriangle == true || penType == 1) {
+ var newPoint = new StylusPointCollection();
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y));
+ var cPoint = GetCenterPoint(points[0], points[1]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y));
+ cPoint = GetCenterPoint(points[1], points[2]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y));
+ cPoint = GetCenterPoint(points[2], points[0]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y));
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y));
+ return newPoint;
+ }
+ else {
+ var newPoint = new StylusPointCollection();
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
+ var cPoint = GetCenterPoint(points[0], points[1]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
+ cPoint = GetCenterPoint(points[1], points[2]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
+ cPoint = GetCenterPoint(points[2], points[0]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
+ return newPoint;
+ }
+ }
+
+ public StylusPointCollection GenerateFakePressureRectangle(StylusPointCollection points) {
+ if (Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) {
+ return points;
+ }
+ else {
+ var newPoint = new StylusPointCollection();
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
+ var cPoint = GetCenterPoint(points[0], points[1]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
+ newPoint.Add(new StylusPoint(points[1].X, points[1].Y, (float)0.4));
+ cPoint = GetCenterPoint(points[1], points[2]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
+ newPoint.Add(new StylusPoint(points[2].X, points[2].Y, (float)0.4));
+ cPoint = GetCenterPoint(points[2], points[3]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
+ newPoint.Add(new StylusPoint(points[3].X, points[3].Y, (float)0.4));
+ cPoint = GetCenterPoint(points[3], points[0]);
+ newPoint.Add(new StylusPoint(cPoint.X, cPoint.Y, (float)0.8));
+ newPoint.Add(new StylusPoint(points[0].X, points[0].Y, (float)0.4));
+ return newPoint;
+ }
+ }
+
+ public Point GetCenterPoint(Point point1, Point point2) {
+ return new Point((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
+ }
+
+ public StylusPoint GetCenterPoint(StylusPoint point1, StylusPoint point2) {
+ return new StylusPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs b/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs
new file mode 100644
index 00000000..544f5c0a
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs
@@ -0,0 +1,287 @@
+using Ink_Canvas.Helpers;
+using System.Collections.Generic;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Diagnostics;
+using System.Windows.Media.Imaging;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ private enum CommitReason {
+ UserInput,
+ CodeInput,
+ ShapeDrawing,
+ ShapeRecognition,
+ ClearingCanvas,
+ Manipulation
+ }
+
+ private CommitReason _currentCommitType = CommitReason.UserInput;
+ private bool IsEraseByPoint => inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint;
+ private StrokeCollection ReplacedStroke;
+ private StrokeCollection AddedStroke;
+ private StrokeCollection CuboidStrokeCollection;
+ private Dictionary> StrokeManipulationHistory;
+
+ private Dictionary StrokeInitialHistory =
+ new Dictionary();
+
+ private Dictionary> DrawingAttributesHistory =
+ new Dictionary>();
+
+ private Dictionary> DrawingAttributesHistoryFlag = new Dictionary>() {
+ { DrawingAttributeIds.Color, new List() },
+ { DrawingAttributeIds.DrawingFlags, new List() },
+ { DrawingAttributeIds.IsHighlighter, new List() },
+ { DrawingAttributeIds.StylusHeight, new List() },
+ { DrawingAttributeIds.StylusTip, new List() },
+ { DrawingAttributeIds.StylusTipTransform, new List() },
+ { DrawingAttributeIds.StylusWidth, new List() }
+ };
+
+ private TimeMachine timeMachine = new TimeMachine();
+
+ private void ApplyHistoryToCanvas(TimeMachineHistory item, InkCanvas applyCanvas = null) {
+ _currentCommitType = CommitReason.CodeInput;
+ var canvas = inkCanvas;
+ if (applyCanvas != null && applyCanvas is InkCanvas) {
+ canvas = applyCanvas;
+ }
+
+ if (item.CommitType == TimeMachineHistoryType.UserInput) {
+ if (!item.StrokeHasBeenCleared) {
+ foreach (var strokes in item.CurrentStroke)
+ if (!canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Add(strokes);
+ } else {
+ foreach (var strokes in item.CurrentStroke)
+ if (canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Remove(strokes);
+ }
+ } else if (item.CommitType == TimeMachineHistoryType.ShapeRecognition) {
+ if (item.StrokeHasBeenCleared) {
+ foreach (var strokes in item.CurrentStroke)
+ if (canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Remove(strokes);
+
+ foreach (var strokes in item.ReplacedStroke)
+ if (!canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Add(strokes);
+ } else {
+ foreach (var strokes in item.CurrentStroke)
+ if (!canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Add(strokes);
+
+ foreach (var strokes in item.ReplacedStroke)
+ if (canvas.Strokes.Contains(strokes))
+ canvas.Strokes.Remove(strokes);
+ }
+ } else if (item.CommitType == TimeMachineHistoryType.Manipulation) {
+ if (!item.StrokeHasBeenCleared) {
+ foreach (var currentStroke in item.StylusPointDictionary) {
+ if (canvas.Strokes.Contains(currentStroke.Key)) {
+ currentStroke.Key.StylusPoints = currentStroke.Value.Item2;
+ }
+ }
+ } else {
+ foreach (var currentStroke in item.StylusPointDictionary) {
+ if (canvas.Strokes.Contains(currentStroke.Key)) {
+ currentStroke.Key.StylusPoints = currentStroke.Value.Item1;
+ }
+ }
+ }
+ } else if (item.CommitType == TimeMachineHistoryType.DrawingAttributes) {
+ if (!item.StrokeHasBeenCleared) {
+ foreach (var currentStroke in item.DrawingAttributes) {
+ if (canvas.Strokes.Contains(currentStroke.Key)) {
+ currentStroke.Key.DrawingAttributes = currentStroke.Value.Item2;
+ }
+ }
+ } else {
+ foreach (var currentStroke in item.DrawingAttributes) {
+ if (canvas.Strokes.Contains(currentStroke.Key)) {
+ currentStroke.Key.DrawingAttributes = currentStroke.Value.Item1;
+ }
+ }
+ }
+ } else if (item.CommitType == TimeMachineHistoryType.Clear) {
+ if (!item.StrokeHasBeenCleared) {
+ if (item.CurrentStroke != null)
+ foreach (var currentStroke in item.CurrentStroke)
+ if (!canvas.Strokes.Contains(currentStroke))
+ canvas.Strokes.Add(currentStroke);
+
+ if (item.ReplacedStroke != null)
+ foreach (var replacedStroke in item.ReplacedStroke)
+ if (canvas.Strokes.Contains(replacedStroke))
+ canvas.Strokes.Remove(replacedStroke);
+ } else {
+ if (item.ReplacedStroke != null)
+ foreach (var replacedStroke in item.ReplacedStroke)
+ if (!canvas.Strokes.Contains(replacedStroke))
+ canvas.Strokes.Add(replacedStroke);
+
+ if (item.CurrentStroke != null)
+ foreach (var currentStroke in item.CurrentStroke)
+ if (canvas.Strokes.Contains(currentStroke))
+ canvas.Strokes.Remove(currentStroke);
+ }
+ }
+
+ _currentCommitType = CommitReason.UserInput;
+ }
+
+ private StrokeCollection ApplyHistoriesToNewStrokeCollection(TimeMachineHistory[] items) {
+ InkCanvas fakeInkCanv = new InkCanvas() {
+ Width = inkCanvas.ActualWidth,
+ Height = inkCanvas.ActualHeight,
+ EditingMode = InkCanvasEditingMode.None,
+ };
+
+ if (items != null && items.Length > 0) {
+ foreach (var timeMachineHistory in items) {
+ ApplyHistoryToCanvas(timeMachineHistory, fakeInkCanv);
+ }
+ }
+
+ return fakeInkCanv.Strokes;
+ }
+
+ private void TimeMachine_OnUndoStateChanged(bool status) {
+ var result = status ? Visibility.Visible : Visibility.Collapsed;
+ BtnUndo.Visibility = result;
+ BtnUndo.IsEnabled = status;
+ }
+
+ private void TimeMachine_OnRedoStateChanged(bool status) {
+ var result = status ? Visibility.Visible : Visibility.Collapsed;
+ BtnRedo.Visibility = result;
+ BtnRedo.IsEnabled = status;
+ }
+
+ private void StrokesOnStrokesChanged(object sender, StrokeCollectionChangedEventArgs e) {
+ if (!isHidingSubPanelsWhenInking) {
+ isHidingSubPanelsWhenInking = true;
+ HideSubPanels(); // 书写时自动隐藏二级菜单
+ }
+
+ foreach (var stroke in e?.Removed) {
+ stroke.StylusPointsChanged -= Stroke_StylusPointsChanged;
+ stroke.StylusPointsReplaced -= Stroke_StylusPointsReplaced;
+ stroke.DrawingAttributesChanged -= Stroke_DrawingAttributesChanged;
+ StrokeInitialHistory.Remove(stroke);
+ }
+
+ foreach (var stroke in e?.Added) {
+ stroke.StylusPointsChanged += Stroke_StylusPointsChanged;
+ stroke.StylusPointsReplaced += Stroke_StylusPointsReplaced;
+ stroke.DrawingAttributesChanged += Stroke_DrawingAttributesChanged;
+ StrokeInitialHistory[stroke] = stroke.StylusPoints.Clone();
+ }
+
+ if (_currentCommitType == CommitReason.CodeInput || _currentCommitType == CommitReason.ShapeDrawing) return;
+
+ if ((e.Added.Count != 0 || e.Removed.Count != 0) && IsEraseByPoint) {
+ if (AddedStroke == null) AddedStroke = new StrokeCollection();
+ if (ReplacedStroke == null) ReplacedStroke = new StrokeCollection();
+ AddedStroke.Add(e.Added);
+ ReplacedStroke.Add(e.Removed);
+ return;
+ }
+
+ if (e.Added.Count != 0) {
+ if (_currentCommitType == CommitReason.ShapeRecognition) {
+ timeMachine.CommitStrokeShapeHistory(ReplacedStroke, e.Added);
+ ReplacedStroke = null;
+ return;
+ } else {
+ timeMachine.CommitStrokeUserInputHistory(e.Added);
+ return;
+ }
+ }
+
+ if (e.Removed.Count != 0) {
+ if (_currentCommitType == CommitReason.ShapeRecognition) {
+ ReplacedStroke = e.Removed;
+ return;
+ } else if (!IsEraseByPoint || _currentCommitType == CommitReason.ClearingCanvas) {
+ timeMachine.CommitStrokeEraseHistory(e.Removed);
+ return;
+ }
+ }
+ }
+
+ private void Stroke_DrawingAttributesChanged(object sender, PropertyDataChangedEventArgs e) {
+ var key = sender as Stroke;
+ var currentValue = key.DrawingAttributes.Clone();
+ DrawingAttributesHistory.TryGetValue(key, out var previousTuple);
+ var previousValue = previousTuple?.Item1 ?? currentValue.Clone();
+ var needUpdateValue = !DrawingAttributesHistoryFlag[e.PropertyGuid].Contains(key);
+ if (needUpdateValue) {
+ DrawingAttributesHistoryFlag[e.PropertyGuid].Add(key);
+ Debug.Write(e.PreviousValue.ToString());
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.Color && needUpdateValue) {
+ previousValue.Color = (Color)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.IsHighlighter && needUpdateValue) {
+ previousValue.IsHighlighter = (bool)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.StylusHeight && needUpdateValue) {
+ previousValue.Height = (double)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.StylusWidth && needUpdateValue) {
+ previousValue.Width = (double)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.StylusTip && needUpdateValue) {
+ previousValue.StylusTip = (StylusTip)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.StylusTipTransform && needUpdateValue) {
+ previousValue.StylusTipTransform = (Matrix)e.PreviousValue;
+ }
+
+ if (e.PropertyGuid == DrawingAttributeIds.DrawingFlags && needUpdateValue) {
+ previousValue.IgnorePressure = (bool)e.PreviousValue;
+ }
+
+ DrawingAttributesHistory[key] =
+ new Tuple(previousValue, currentValue);
+ }
+
+ private void Stroke_StylusPointsReplaced(object sender, StylusPointsReplacedEventArgs e) {
+ StrokeInitialHistory[sender as Stroke] = e.NewStylusPoints.Clone();
+ }
+
+ private void Stroke_StylusPointsChanged(object sender, EventArgs e) {
+ var selectedStrokes = inkCanvas.GetSelectedStrokes();
+ var count = selectedStrokes.Count;
+ if (count == 0) count = inkCanvas.Strokes.Count;
+ if (StrokeManipulationHistory == null) {
+ StrokeManipulationHistory =
+ new Dictionary>();
+ }
+
+ StrokeManipulationHistory[sender as Stroke] =
+ new Tuple(StrokeInitialHistory[sender as Stroke],
+ (sender as Stroke).StylusPoints.Clone());
+ if ((StrokeManipulationHistory.Count == count || sender == null) && dec.Count == 0) {
+ timeMachine.CommitStrokeManipulationHistory(StrokeManipulationHistory);
+ foreach (var item in StrokeManipulationHistory) {
+ StrokeInitialHistory[item.Key] = item.Value.Item2;
+ }
+
+ StrokeManipulationHistory = null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_Timer.cs b/Ink Canvas/MainWindow_cs/MW_Timer.cs
new file mode 100644
index 00000000..aa6f64ba
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_Timer.cs
@@ -0,0 +1,326 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Timers;
+using System.Windows;
+using MessageBox = System.Windows.MessageBox;
+
+namespace Ink_Canvas {
+ public class TimeViewModel : INotifyPropertyChanged {
+ private string _nowTime;
+ private string _nowDate;
+
+ public string nowTime {
+ get => _nowTime;
+ set {
+ if (_nowTime != value) {
+ _nowTime = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ public string nowDate {
+ get => _nowDate;
+ set {
+ if (_nowDate != value) {
+ _nowDate = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ public partial class MainWindow : Window {
+ private Timer timerCheckPPT = new Timer();
+ private Timer timerKillProcess = new Timer();
+ private Timer timerCheckAutoFold = new Timer();
+ private string AvailableLatestVersion = null;
+ private Timer timerCheckAutoUpdateWithSilence = new Timer();
+ private bool isHidingSubPanelsWhenInking = false; // 避免书写时触发二次关闭二级菜单导致动画不连续
+
+ private Timer timerDisplayTime = new Timer();
+ private Timer timerDisplayDate = new Timer();
+
+ private TimeViewModel nowTimeVM = new TimeViewModel();
+
+ private void InitTimers() {
+ timerCheckPPT.Elapsed += TimerCheckPPT_Elapsed;
+ timerCheckPPT.Interval = 500;
+ timerKillProcess.Elapsed += TimerKillProcess_Elapsed;
+ timerKillProcess.Interval = 2000;
+ timerCheckAutoFold.Elapsed += timerCheckAutoFold_Elapsed;
+ timerCheckAutoFold.Interval = 500;
+ timerCheckAutoUpdateWithSilence.Elapsed += timerCheckAutoUpdateWithSilence_Elapsed;
+ timerCheckAutoUpdateWithSilence.Interval = 1000 * 60 * 10;
+ WaterMarkTime.DataContext = nowTimeVM;
+ WaterMarkDate.DataContext = nowTimeVM;
+ timerDisplayTime.Elapsed += TimerDisplayTime_Elapsed;
+ timerDisplayTime.Interval = 1000;
+ timerDisplayTime.Start();
+ timerDisplayDate.Elapsed += TimerDisplayDate_Elapsed;
+ timerDisplayDate.Interval = 1000 * 60 * 60 * 1;
+ timerDisplayDate.Start();
+ timerKillProcess.Start();
+ nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
+ nowTimeVM.nowTime = DateTime.Now.ToShortTimeString().ToString();
+ }
+
+ private void TimerDisplayTime_Elapsed(object sender, ElapsedEventArgs e) {
+ nowTimeVM.nowTime = DateTime.Now.ToShortTimeString().ToString();
+ }
+
+ private void TimerDisplayDate_Elapsed(object sender, ElapsedEventArgs e) {
+ nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
+ }
+
+ private void TimerKillProcess_Elapsed(object sender, ElapsedEventArgs e) {
+ try {
+ // 希沃相关: easinote swenserver RemoteProcess EasiNote.MediaHttpService smartnote.cloud EasiUpdate smartnote EasiUpdate3 EasiUpdate3Protect SeewoP2P CefSharp.BrowserSubprocess SeewoUploadService
+ var arg = "/F";
+ if (Settings.Automation.IsAutoKillPptService) {
+ var processes = Process.GetProcessesByName("PPTService");
+ if (processes.Length > 0) arg += " /IM PPTService.exe";
+ processes = Process.GetProcessesByName("SeewoIwbAssistant");
+ if (processes.Length > 0) arg += " /IM SeewoIwbAssistant.exe" + " /IM Sia.Guard.exe";
+ }
+
+ if (Settings.Automation.IsAutoKillEasiNote) {
+ var processes = Process.GetProcessesByName("EasiNote");
+ if (processes.Length > 0) arg += " /IM EasiNote.exe";
+ }
+
+ if (Settings.Automation.IsAutoKillHiteAnnotation) {
+ var processes = Process.GetProcessesByName("HiteAnnotation");
+ if (processes.Length > 0) arg += " /IM HiteAnnotation.exe";
+ }
+
+ if (Settings.Automation.IsAutoKillVComYouJiao)
+ {
+ var processes = Process.GetProcessesByName("VcomTeach");
+ if (processes.Length > 0) arg += " /IM VcomTeach.exe" + " /IM VcomDaemon.exe" + " /IM VcomRender.exe";
+ }
+
+ if (Settings.Automation.IsAutoKillICA) {
+ var processesAnnotation = Process.GetProcessesByName("Ink Canvas Annotation");
+ var processesArtistry = Process.GetProcessesByName("Ink Canvas Artistry");
+ if (processesAnnotation.Length > 0) arg += " /IM \"Ink Canvas Annotation.exe\"";
+ if (processesArtistry.Length > 0) arg += " /IM \"Ink Canvas Artistry.exe\"";
+ }
+
+ if (Settings.Automation.IsAutoKillInkCanvas) {
+ var processes = Process.GetProcessesByName("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\"";
+ }
+
+ if (Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation) {
+ //由于希沃桌面2.0提供的桌面批注是64位应用程序,32位程序无法访问,目前暂不做精准匹配,只匹配进程名称,后面会考虑封装一套基于P/Invoke和WMI的综合进程识别方案。
+ var processes = Process.GetProcessesByName("DesktopAnnotation");
+ if (processes.Length > 0) arg += " /IM DesktopAnnotation.exe";
+ }
+
+ if (arg != "/F") {
+ var p = new Process();
+ p.StartInfo = new ProcessStartInfo("taskkill", arg);
+ p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ p.Start();
+
+ if (arg.Contains("EasiNote")) {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“希沃白板 5”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("HiteAnnotation")) {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“鸿合屏幕书写”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("Ink Canvas Annotation") || arg.Contains("Ink Canvas Artistry")) {
+ Dispatcher.Invoke(() => {
+ ShowNewMessage("“ICA”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("\"Ink Canvas.exe\"")) {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“Ink Canvas”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("智绘教")) {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“智绘教”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("VcomTeach"))
+ {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“优教授课端”已自动关闭");
+ });
+ }
+
+ if (arg.Contains("DesktopAnnotation"))
+ {
+ Dispatcher.Invoke(() => {
+ ShowNotification("“DesktopAnnotation”已自动关闭");
+ });
+ }
+ }
+ }
+ catch {}
+ }
+
+
+ private bool foldFloatingBarByUser = false, // 保持收纳操作不受自动收纳的控制
+ unfoldFloatingBarByUser = false; // 允许用户在希沃软件内进行展开操作
+
+ private void timerCheckAutoFold_Elapsed(object sender, ElapsedEventArgs e) {
+ if (isFloatingBarChangingHideMode) return;
+ try {
+ var windowProcessName = ForegroundWindowInfo.ProcessName();
+ var windowTitle = ForegroundWindowInfo.WindowTitle();
+ //LogHelper.WriteLogToFile("windowTitle | " + windowTitle + " | windowProcessName | " + windowProcessName);
+
+ if (windowProcessName == "EasiNote") {
+ // 检测到有可能是EasiNote5或者EasiNote3/3C
+ if (ForegroundWindowInfo.ProcessPath() != "Unknown") {
+ var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
+ string version = versionInfo.FileVersion;
+ string prodName = versionInfo.ProductName;
+ Trace.WriteLine(ForegroundWindowInfo.ProcessPath());
+ Trace.WriteLine(version);
+ Trace.WriteLine(prodName);
+ if (version.StartsWith("5.") && Settings.Automation.IsAutoFoldInEasiNote && (!(windowTitle.Length == 0 && ForegroundWindowInfo.WindowRect().Height < 500) ||
+ !Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno)) { // EasiNote5
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ } else if (version.StartsWith("3.") && Settings.Automation.IsAutoFoldInEasiNote3) { // EasiNote3
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ } else if (prodName.Contains("3C") && Settings.Automation.IsAutoFoldInEasiNote3C &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) { // EasiNote3C
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ }
+ }
+ // EasiCamera
+ } else if (Settings.Automation.IsAutoFoldInEasiCamera && windowProcessName == "EasiCamera" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // EasiNote5C
+ } else if (Settings.Automation.IsAutoFoldInEasiNote5C && windowProcessName == "EasiNote5C" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // SeewoPinco
+ } else if (Settings.Automation.IsAutoFoldInSeewoPincoTeacher && (windowProcessName == "BoardService" || windowProcessName == "seewoPincoTeacher")) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // HiteCamera
+ } else if (Settings.Automation.IsAutoFoldInHiteCamera && windowProcessName == "HiteCamera" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // HiteTouchPro
+ } else if (Settings.Automation.IsAutoFoldInHiteTouchPro && windowProcessName == "HiteTouchPro" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // WxBoardMain
+ } else if (Settings.Automation.IsAutoFoldInWxBoardMain && windowProcessName == "WxBoardMain" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // MSWhiteboard
+ } else if (Settings.Automation.IsAutoFoldInMSWhiteboard && (windowProcessName == "MicrosoftWhiteboard" ||
+ windowProcessName == "msedgewebview2")) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // OldZyBoard
+ } else if (Settings.Automation.IsAutoFoldInOldZyBoard && // 中原旧白板
+ (WinTabWindowsChecker.IsWindowExisted("WhiteBoard - DrawingWindow")
+ || WinTabWindowsChecker.IsWindowExisted("InstantAnnotationWindow"))) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // HiteLightBoard
+ } else if (Settings.Automation.IsAutoFoldInHiteLightBoard && windowProcessName == "HiteLightBoard" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // AdmoxWhiteboard
+ } else if (Settings.Automation.IsAutoFoldInAdmoxWhiteboard && windowProcessName == "Amdox.WhiteBoard" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // AdmoxBooth
+ } else if (Settings.Automation.IsAutoFoldInAdmoxBooth && windowProcessName == "Amdox.Booth" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // QPoint
+ } else if (Settings.Automation.IsAutoFoldInQPoint && windowProcessName == "QPoint" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // YiYunVisualPresenter
+ } else if (Settings.Automation.IsAutoFoldInYiYunVisualPresenter && windowProcessName == "YiYunVisualPresenter" &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ // MaxHubWhiteboard
+ } else if (Settings.Automation.IsAutoFoldInMaxHubWhiteboard && windowProcessName == "WhiteBoard" &&
+ WinTabWindowsChecker.IsWindowExisted("白板书写") &&
+ ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
+ ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16) {
+ if (ForegroundWindowInfo.ProcessPath() != "Unknown") {
+ var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
+ var version = versionInfo.FileVersion; var prodName = versionInfo.ProductName;
+ if (version.StartsWith("6.") && prodName=="WhiteBoard") if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
+ }
+ } else if (WinTabWindowsChecker.IsWindowExisted("幻灯片放映", false)) {
+ // 处于幻灯片放映状态
+ if (!Settings.Automation.IsAutoFoldInPPTSlideShow && isFloatingBarFolded && !foldFloatingBarByUser)
+ UnFoldFloatingBar_MouseUp(new object(), null);
+ } else {
+ if (isFloatingBarFolded && !foldFloatingBarByUser) UnFoldFloatingBar_MouseUp(new object(), null);
+ unfoldFloatingBarByUser = false;
+ }
+ }
+ catch { }
+ }
+
+ private void timerCheckAutoUpdateWithSilence_Elapsed(object sender, ElapsedEventArgs e) {
+ Dispatcher.Invoke(() => {
+ try {
+ if (!Topmost || inkCanvas.Strokes.Count > 0) return;
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ });
+ try {
+ if (AutoUpdateWithSilenceTimeComboBox.CheckIsInSilencePeriod(
+ Settings.Startup.AutoUpdateWithSilenceStartTime,
+ Settings.Startup.AutoUpdateWithSilenceEndTime)) {
+ AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
+ timerCheckAutoUpdateWithSilence.Stop();
+ }
+ }
+ catch (Exception ex) {
+ LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs
new file mode 100644
index 00000000..e69f6780
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs
@@ -0,0 +1,427 @@
+using Ink_Canvas.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using Point = System.Windows.Point;
+
+namespace Ink_Canvas {
+ public partial class MainWindow : Window {
+ #region Multi-Touch
+
+ private bool isInMultiTouchMode = false;
+
+ private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (isInMultiTouchMode) {
+ inkCanvas.StylusDown -= MainWindow_StylusDown;
+ inkCanvas.StylusMove -= MainWindow_StylusMove;
+ inkCanvas.StylusUp -= MainWindow_StylusUp;
+ inkCanvas.TouchDown -= MainWindow_TouchDown;
+ inkCanvas.TouchDown += Main_Grid_TouchDown;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ inkCanvas.Children.Clear();
+ isInMultiTouchMode = false;
+ }
+ else {
+ inkCanvas.StylusDown += MainWindow_StylusDown;
+ inkCanvas.StylusMove += MainWindow_StylusMove;
+ inkCanvas.StylusUp += MainWindow_StylusUp;
+ inkCanvas.TouchDown += MainWindow_TouchDown;
+ inkCanvas.TouchDown -= Main_Grid_TouchDown;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ inkCanvas.Children.Clear();
+ isInMultiTouchMode = true;
+ }
+ }
+
+ private void MainWindow_TouchDown(object sender, TouchEventArgs e) {
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
+ || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
+ || inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
+
+ if (!isHidingSubPanelsWhenInking) {
+ isHidingSubPanelsWhenInking = true;
+ HideSubPanels(); // 书写时自动隐藏二级菜单
+ }
+
+ double boundWidth = e.GetTouchPoint(null).Bounds.Width, eraserMultiplier = 1.0;
+ if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
+ eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
+
+ if ((Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen) //启用特殊屏幕且触摸倍数为 0 时禁用橡皮
+ && boundWidth > BoundsWidth * 2.5) {
+ if (drawingShapeMode == 0 && forceEraser) return;
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(boundWidth * k * eraserMultiplier * 0.25,
+ boundWidth * k * eraserMultiplier * 0.25);
+ TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.EraseByPoint;
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ }
+ else {
+ TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ }
+ }
+
+ private void MainWindow_StylusDown(object sender, StylusDownEventArgs e) {
+
+ inkCanvas.CaptureStylus();
+ ViewboxFloatingBar.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint
+ || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke
+ || inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
+
+ TouchDownPointsList[e.StylusDevice.Id] = InkCanvasEditingMode.None;
+ }
+
+ private async void MainWindow_StylusUp(object sender, StylusEventArgs e) {
+ try {
+ inkCanvas.Strokes.Add(GetStrokeVisual(e.StylusDevice.Id).Stroke);
+ await Task.Delay(5); // 避免渲染墨迹完成前预览墨迹被删除导致墨迹闪烁
+ inkCanvas.Children.Remove(GetVisualCanvas(e.StylusDevice.Id));
+
+ inkCanvas_StrokeCollected(inkCanvas,
+ new InkCanvasStrokeCollectedEventArgs(GetStrokeVisual(e.StylusDevice.Id).Stroke));
+ }
+ catch (Exception ex) {
+ Label.Content = ex.ToString();
+ }
+
+ try {
+ StrokeVisualList.Remove(e.StylusDevice.Id);
+ VisualCanvasList.Remove(e.StylusDevice.Id);
+ TouchDownPointsList.Remove(e.StylusDevice.Id);
+ if (StrokeVisualList.Count == 0 || VisualCanvasList.Count == 0 || TouchDownPointsList.Count == 0) {
+ inkCanvas.Children.Clear();
+ StrokeVisualList.Clear();
+ VisualCanvasList.Clear();
+ TouchDownPointsList.Clear();
+ }
+ }
+ catch { }
+
+ inkCanvas.ReleaseStylusCapture();
+ ViewboxFloatingBar.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+ }
+
+ private void MainWindow_StylusMove(object sender, StylusEventArgs e) {
+ try {
+ if (GetTouchDownPointsList(e.StylusDevice.Id) != InkCanvasEditingMode.None) return;
+ try {
+ if (e.StylusDevice.StylusButtons[1].StylusButtonState == StylusButtonState.Down) return;
+ }
+ catch { }
+
+ var strokeVisual = GetStrokeVisual(e.StylusDevice.Id);
+ var stylusPointCollection = e.GetStylusPoints(this);
+ foreach (var stylusPoint in stylusPointCollection)
+ strokeVisual.Add(new StylusPoint(stylusPoint.X, stylusPoint.Y, stylusPoint.PressureFactor));
+ strokeVisual.Redraw();
+ }
+ catch { }
+ }
+
+ private StrokeVisual GetStrokeVisual(int id) {
+ if (StrokeVisualList.TryGetValue(id, out var visual)) return visual;
+
+ var strokeVisual = new StrokeVisual(inkCanvas.DefaultDrawingAttributes.Clone());
+ StrokeVisualList[id] = strokeVisual;
+ StrokeVisualList[id] = strokeVisual;
+ var visualCanvas = new VisualCanvas(strokeVisual);
+ VisualCanvasList[id] = visualCanvas;
+ inkCanvas.Children.Add(visualCanvas);
+
+ return strokeVisual;
+ }
+
+ private VisualCanvas GetVisualCanvas(int id) {
+ return VisualCanvasList.TryGetValue(id, out var visualCanvas) ? visualCanvas : null;
+ }
+
+ private InkCanvasEditingMode GetTouchDownPointsList(int id) {
+ return TouchDownPointsList.TryGetValue(id, out var inkCanvasEditingMode) ? inkCanvasEditingMode : inkCanvas.EditingMode;
+ }
+
+ private Dictionary TouchDownPointsList { get; } =
+ new Dictionary();
+
+ private Dictionary StrokeVisualList { get; } = new Dictionary();
+ private Dictionary VisualCanvasList { get; } = new Dictionary();
+
+ #endregion
+
+
+ private int lastTouchDownTime = 0, lastTouchUpTime = 0;
+
+ private Point iniP = new Point(0, 0);
+ private bool isLastTouchEraser = false;
+ private bool forcePointEraser = true;
+
+ private void Main_Grid_TouchDown(object sender, TouchEventArgs e) {
+
+ inkCanvas.CaptureTouch(e.TouchDevice);
+ ViewboxFloatingBar.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+
+ if (!isHidingSubPanelsWhenInking) {
+ isHidingSubPanelsWhenInking = true;
+ HideSubPanels(); // 书写时自动隐藏二级菜单
+ }
+
+ if (NeedUpdateIniP()) iniP = e.GetTouchPoint(inkCanvas).Position;
+ if (drawingShapeMode == 9 && isFirstTouchCuboid == false) MouseTouchMove(iniP);
+ inkCanvas.Opacity = 1;
+ double boundsWidth = GetTouchBoundWidth(e), eraserMultiplier = 1.0;
+ if (!Settings.Advanced.EraserBindTouchMultiplier && Settings.Advanced.IsSpecialScreen)
+ eraserMultiplier = 1 / Settings.Advanced.TouchMultiplier;
+ if (boundsWidth > BoundsWidth) {
+ isLastTouchEraser = true;
+ if (drawingShapeMode == 0 && forceEraser) return;
+ if (boundsWidth > BoundsWidth * 2.5) {
+ double k = 1;
+ switch (Settings.Canvas.EraserSize) {
+ case 0:
+ k = 0.5;
+ break;
+ case 1:
+ k = 0.8;
+ break;
+ case 3:
+ k = 1.25;
+ break;
+ case 4:
+ k = 1.8;
+ break;
+ }
+
+ inkCanvas.EraserShape = new EllipseStylusShape(boundsWidth * k * eraserMultiplier,
+ boundsWidth * k * eraserMultiplier);
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
+ }
+ else {
+ if (StackPanelPPTControls.Visibility == Visibility.Visible && inkCanvas.Strokes.Count == 0 &&
+ Settings.PowerPointSettings.IsEnableFingerGestureSlideShowControl) {
+ isLastTouchEraser = false;
+ inkCanvas.EditingMode = InkCanvasEditingMode.GestureOnly;
+ inkCanvas.Opacity = 0.1;
+ }
+ else {
+ inkCanvas.EraserShape = new EllipseStylusShape(5, 5);
+ inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
+ }
+ }
+ }
+ else {
+ isLastTouchEraser = false;
+ inkCanvas.EraserShape =
+ forcePointEraser ? new EllipseStylusShape(50, 50) : new EllipseStylusShape(5, 5);
+ if (forceEraser) return;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ }
+ }
+
+ private double GetTouchBoundWidth(TouchEventArgs e) {
+ var args = e.GetTouchPoint(null).Bounds;
+ double value;
+ if (!Settings.Advanced.IsQuadIR) value = args.Width;
+ else value = Math.Sqrt(args.Width * args.Height); //四边红外
+ if (Settings.Advanced.IsSpecialScreen) value *= Settings.Advanced.TouchMultiplier;
+ return value;
+ }
+
+ //记录触摸设备ID
+ private List dec = new List();
+
+ //中心点
+ private Point centerPoint;
+ private InkCanvasEditingMode lastInkCanvasEditingMode = InkCanvasEditingMode.Ink;
+ private bool isSingleFingerDragMode = false;
+
+ private void inkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) {
+
+ inkCanvas.CaptureTouch(e.TouchDevice);
+ ViewboxFloatingBar.IsHitTestVisible = false;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = false;
+
+ dec.Add(e.TouchDevice.Id);
+ //设备1个的时候,记录中心点
+ if (dec.Count == 1) {
+ var touchPoint = e.GetTouchPoint(inkCanvas);
+ centerPoint = touchPoint.Position;
+
+ //记录第一根手指点击时的 StrokeCollection
+ lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone();
+ }
+ //设备两个及两个以上,将画笔功能关闭
+ if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) {
+ if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.None ||
+ inkCanvas.EditingMode == InkCanvasEditingMode.Select) return;
+ lastInkCanvasEditingMode = inkCanvas.EditingMode;
+ inkCanvas.EditingMode = InkCanvasEditingMode.None;
+ }
+ }
+
+ private void inkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) {
+
+ inkCanvas.ReleaseAllTouchCaptures();
+ ViewboxFloatingBar.IsHitTestVisible = true;
+ BlackboardUIGridForInkReplay.IsHitTestVisible = true;
+
+ //手势完成后切回之前的状态
+ if (dec.Count > 1)
+ if (inkCanvas.EditingMode == InkCanvasEditingMode.None)
+ inkCanvas.EditingMode = lastInkCanvasEditingMode;
+ dec.Remove(e.TouchDevice.Id);
+ inkCanvas.Opacity = 1;
+ if (dec.Count == 0)
+ if (lastTouchDownStrokeCollection.Count() != inkCanvas.Strokes.Count() &&
+ !(drawingShapeMode == 9 && !isFirstTouchCuboid)) {
+ var whiteboardIndex = CurrentWhiteboardIndex;
+ if (currentMode == 0) whiteboardIndex = 0;
+ strokeCollections[whiteboardIndex] = lastTouchDownStrokeCollection;
+ }
+ }
+
+ private void inkCanvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e) {
+ e.Mode = ManipulationModes.All;
+ }
+
+ private void inkCanvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) { }
+
+ private void Main_Grid_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
+ if (e.Manipulators.Count() != 0) return;
+ if (forceEraser) return;
+ inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
+ }
+
+ // -- removed --
+ //
+ //private void inkCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
+ //{
+ // if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture || inkCanvas.Strokes.Count == 0 || dec.Count() < 2) return;
+ // _currentCommitType = CommitReason.Manipulation;
+ // StrokeCollection strokes = inkCanvas.GetSelectedStrokes();
+ // if (strokes.Count != 0)
+ // {
+ // inkCanvas.Strokes.Replace(strokes, strokes.Clone());
+ // }
+ // else
+ // {
+ // var originalStrokes = inkCanvas.Strokes;
+ // var targetStrokes = originalStrokes.Clone();
+ // originalStrokes.Replace(originalStrokes, targetStrokes);
+ // }
+ // _currentCommitType = CommitReason.UserInput;
+ //}
+
+ private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
+ if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return;
+ if ((dec.Count >= 2 && (Settings.PowerPointSettings.IsEnableTwoFingerGestureInPresentationMode ||
+ StackPanelPPTControls.Visibility != Visibility.Visible ||
+ StackPanelPPTButtons.Visibility == Visibility.Collapsed)) ||
+ isSingleFingerDragMode) {
+ var md = e.DeltaManipulation;
+ var trans = md.Translation; // 获得位移矢量
+
+ var m = new Matrix();
+
+ if (Settings.Gesture.IsEnableTwoFingerTranslate)
+ m.Translate(trans.X, trans.Y); // 移动
+
+ if (Settings.Gesture.IsEnableTwoFingerGestureTranslateOrRotation) {
+ var rotate = md.Rotation; // 获得旋转角度
+ var scale = md.Scale; // 获得缩放倍数
+
+ // Find center of element and then transform to get current location of center
+ var fe = e.Source as FrameworkElement;
+ var center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
+ center = m.Transform(center); // 转换为矩阵缩放和旋转的中心点
+
+ if (Settings.Gesture.IsEnableTwoFingerRotation)
+ m.RotateAt(rotate, center.X, center.Y); // 旋转
+ if (Settings.Gesture.IsEnableTwoFingerZoom)
+ m.ScaleAt(scale.X, scale.Y, center.X, center.Y); // 缩放
+ }
+
+ var strokes = inkCanvas.GetSelectedStrokes();
+ if (strokes.Count != 0) {
+ foreach (var stroke in strokes) {
+ stroke.Transform(m, false);
+
+ foreach (var circle in circles)
+ if (stroke == circle.Stroke) {
+ circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
+ circle.Centroid = new Point(
+ (circle.Stroke.StylusPoints[0].X +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
+ (circle.Stroke.StylusPoints[0].Y +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2);
+ break;
+ }
+
+ if (!Settings.Gesture.IsEnableTwoFingerZoom) continue;
+ try {
+ stroke.DrawingAttributes.Width *= md.Scale.X;
+ stroke.DrawingAttributes.Height *= md.Scale.Y;
+ }
+ catch { }
+ }
+ }
+ else {
+ if (Settings.Gesture.IsEnableTwoFingerZoom) {
+ foreach (var stroke in inkCanvas.Strokes) {
+ stroke.Transform(m, false);
+ try {
+ stroke.DrawingAttributes.Width *= md.Scale.X;
+ stroke.DrawingAttributes.Height *= md.Scale.Y;
+ }
+ catch { }
+ }
+
+ ;
+ }
+ else {
+ foreach (var stroke in inkCanvas.Strokes) stroke.Transform(m, false);
+ ;
+ }
+
+ foreach (var circle in circles) {
+ circle.R = GetDistance(circle.Stroke.StylusPoints[0].ToPoint(),
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].ToPoint()) / 2;
+ circle.Centroid = new Point(
+ (circle.Stroke.StylusPoints[0].X +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].X) / 2,
+ (circle.Stroke.StylusPoints[0].Y +
+ circle.Stroke.StylusPoints[circle.Stroke.StylusPoints.Count / 2].Y) / 2
+ );
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs
new file mode 100644
index 00000000..e4c943a0
--- /dev/null
+++ b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs
@@ -0,0 +1,139 @@
+using Ink_Canvas.Helpers;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Forms.VisualStyles;
+using System.Windows.Interop;
+using System.Windows.Media.Animation;
+using Hardcodet.Wpf.TaskbarNotification;
+
+namespace Ink_Canvas
+{
+ public partial class App : Application {
+
+ private void SysTrayMenu_Opened(object sender, RoutedEventArgs e) {
+ var s = (ContextMenu)sender;
+ var FoldFloatingBarTrayIconMenuItemIconEyeOff =
+ (Image)((Grid)((MenuItem)s.Items[s.Items.Count-5]).Icon).Children[0];
+ var FoldFloatingBarTrayIconMenuItemIconEyeOn =
+ (Image)((Grid)((MenuItem)s.Items[s.Items.Count - 5]).Icon).Children[1];
+ var FoldFloatingBarTrayIconMenuItemHeaderText =
+ (TextBlock)((SimpleStackPanel)((MenuItem)s.Items[s.Items.Count - 5]).Header).Children[0];
+ var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
+ var HideICCMainWindowTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 9];
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) {
+ // 判斷是否在收納模式中
+ if (mainWin.isFloatingBarFolded) {
+ FoldFloatingBarTrayIconMenuItemIconEyeOff.Visibility = Visibility.Hidden;
+ FoldFloatingBarTrayIconMenuItemIconEyeOn.Visibility = Visibility.Visible;
+ FoldFloatingBarTrayIconMenuItemHeaderText.Text = "退出收纳模式";
+ if (!HideICCMainWindowTrayIconMenuItem.IsChecked) {
+ ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = false;
+ ResetFloatingBarPositionTrayIconMenuItem.Opacity = 0.5;
+ }
+ } else {
+ FoldFloatingBarTrayIconMenuItemIconEyeOff.Visibility = Visibility.Visible;
+ FoldFloatingBarTrayIconMenuItemIconEyeOn.Visibility = Visibility.Hidden;
+ FoldFloatingBarTrayIconMenuItemHeaderText.Text = "切换为收纳模式";
+ if (!HideICCMainWindowTrayIconMenuItem.IsChecked) {
+ ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = true;
+ ResetFloatingBarPositionTrayIconMenuItem.Opacity = 1;
+ }
+
+ }
+ }
+ }
+
+ private void CloseAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) mainWin.BtnExit_Click(null,null);
+ }
+
+ private void RestartAppTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) mainWin.BtnRestart_Click(null,null);
+ }
+
+ private void ForceFullScreenTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e) {
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) {
+ Ink_Canvas.MainWindow.MoveWindow(new WindowInteropHelper(mainWin).Handle, 0, 0,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, true);
+ Ink_Canvas.MainWindow.ShowNewMessage($"已强制全屏化:{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height}(缩放比例为{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth}x{System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight})");
+ }
+ }
+
+ private void FoldFloatingBarTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
+ {
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded)
+ if (mainWin.isFloatingBarFolded) mainWin.UnFoldFloatingBar_MouseUp(new object(),null);
+ else mainWin.FoldFloatingBar_MouseUp(new object(),null);
+ }
+
+ private void ResetFloatingBarPositionTrayIconMenuItem_Clicked(object sender, RoutedEventArgs e)
+ {
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) {
+ var isInPPTPresentationMode = false;
+ Dispatcher.Invoke(() => {
+ isInPPTPresentationMode = mainWin.BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
+ });
+ if (!mainWin.isFloatingBarFolded) {
+ if (!isInPPTPresentationMode) mainWin.PureViewboxFloatingBarMarginAnimationInDesktopMode();
+ else mainWin.PureViewboxFloatingBarMarginAnimationInPPTMode();
+ }
+ }
+ }
+
+ private void HideICCMainWindowTrayIconMenuItem_Checked(object sender, RoutedEventArgs e) {
+ var mi = (MenuItem)sender;
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) {
+ mainWin.Hide();
+ var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu;
+ var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
+ var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
+ var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
+ ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = false;
+ FoldFloatingBarTrayIconMenuItem.IsEnabled = false;
+ ForceFullScreenTrayIconMenuItem.IsEnabled = false;
+ ResetFloatingBarPositionTrayIconMenuItem.Opacity = 0.5;
+ FoldFloatingBarTrayIconMenuItem.Opacity = 0.5;
+ ForceFullScreenTrayIconMenuItem.Opacity = 0.5;
+ } else {
+ mi.IsChecked = false;
+ }
+
+ }
+
+ private void HideICCMainWindowTrayIconMenuItem_UnChecked(object sender, RoutedEventArgs e) {
+ var mi = (MenuItem)sender;
+ var mainWin = (MainWindow)Application.Current.MainWindow;
+ if (mainWin.IsLoaded) {
+ mainWin.Show();
+ var s = ((TaskbarIcon)Application.Current.Resources["TaskbarTrayIcon"]).ContextMenu;
+ var ResetFloatingBarPositionTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 4];
+ var FoldFloatingBarTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 5];
+ var ForceFullScreenTrayIconMenuItem = (MenuItem)s.Items[s.Items.Count - 6];
+ ResetFloatingBarPositionTrayIconMenuItem.IsEnabled = true;
+ FoldFloatingBarTrayIconMenuItem.IsEnabled = true;
+ ForceFullScreenTrayIconMenuItem.IsEnabled = true;
+ ResetFloatingBarPositionTrayIconMenuItem.Opacity = 1;
+ FoldFloatingBarTrayIconMenuItem.Opacity = 1;
+ ForceFullScreenTrayIconMenuItem.Opacity = 1;
+ } else {
+ mi.IsChecked = false;
+ }
+ }
+
+ }
+}
diff --git a/Ink Canvas/Properties/AssemblyInfo.cs b/Ink Canvas/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..c4d6a88c
--- /dev/null
+++ b/Ink Canvas/Properties/AssemblyInfo.cs
@@ -0,0 +1,53 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("InkCanvasForClass")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HARKOTEK Studio")]
+[assembly: AssemblyProduct("InkCanvasForClass")]
+[assembly: AssemblyCopyright("© Copyright HARKOTEK Studio 2024-now")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[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)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("5.0.5.1")]
+[assembly: AssemblyFileVersion("5.0.5.1")]
\ No newline at end of file
diff --git a/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml b/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 00000000..c0035a49
--- /dev/null
+++ b/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,13 @@
+
+
+
+
+ Release
+ Any CPU
+ dist\
+ FileSystem
+ <_TargetId>Folder
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml.user b/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 00000000..e9ea52ed
--- /dev/null
+++ b/Ink Canvas/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/Ink Canvas/Properties/Resources.Designer.cs b/Ink Canvas/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..fd581c62
--- /dev/null
+++ b/Ink Canvas/Properties/Resources.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+//
+// 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 Ink_Canvas.Properties {
+ using System;
+
+
+ ///
+ /// 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.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [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("Ink_Canvas.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;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
+ ///
+ internal static System.IO.UnmanagedMemoryStream TimerDownNotice {
+ get {
+ return ResourceManager.GetStream("TimerDownNotice", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Ink Canvas/Properties/Resources.resx b/Ink Canvas/Properties/Resources.resx
new file mode 100644
index 00000000..09ce9aea
--- /dev/null
+++ b/Ink Canvas/Properties/Resources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\TimerDownNotice.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Properties/Settings.Designer.cs b/Ink Canvas/Properties/Settings.Designer.cs
new file mode 100644
index 00000000..9c56a3a2
--- /dev/null
+++ b/Ink Canvas/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace Ink_Canvas.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.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/Ink Canvas/Properties/Settings.settings b/Ink Canvas/Properties/Settings.settings
new file mode 100644
index 00000000..033d7a5e
--- /dev/null
+++ b/Ink Canvas/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Resources/ChickenSoup.cs b/Ink Canvas/Resources/ChickenSoup.cs
new file mode 100644
index 00000000..0d461c44
--- /dev/null
+++ b/Ink Canvas/Resources/ChickenSoup.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Ink_Canvas
+{
+ public static class ChickenSoup {
+ public static string[] OSUPlayerYuLu = new string[] {
+ "澳洲原神,启动!",
+ "一眼丁真,鉴定为玩osu!玩的",
+ "喊MimosaM给我炒两菜",
+ "不要……不要把背景圖刪掉的說!",
+ "6秒800PP,I Can!",
+ "osu! 启动!",
+ "你说得对,但是osu!,前面忘了,后面忘了",
+ "换电脑变成残疾人",
+ "难绷acc",
+ "牢大:这是串pp图啊",
+ "你看人家,坚持不刷PP,都在新人群买房了",
+ "打o不要这么努力吧",
+ "凹不了一点",
+ "大神进步好快啊",
+ "pass和fc之间是天堑",
+ "4星就是一个巨大的开放暴毙世界(",
+ "我是要成为owc选手的人!",
+ "戳完就跳",
+ "我疑似有点罕见了",
+ "小时候喝了这个手指学会了强双",
+ "90bpm熬老头呢",
+ "艹了,发现我从没fc过一张串图",
+ "oshit!",
+ "hso!",
+ "不好玩!",
+ "钝角跳真的挺恶心的",
+ "我草,O!",
+ "又有人2000了"
+ };
+
+ public static string[] MingYanJingJu = new string[] {
+ "老骥伏枥,志在千里;烈士暮年,壮心不已",
+ "有志者,事竟成",
+ "有志者自有千方百计,无志者只感千难万难",
+ "有志的人战天斗地,无志的人怨天恨地",
+ "有伟大志向的人,都可以成为圣人。",
+ "人的志向,应在千里之外。",
+ "人不在于地位的高低,而在于志向的远大。",
+ "人的志向,应崇高而远大。",
+ "立志没有所谓过迟",
+ "鸟不展翅膀难高飞",
+ "不怕路远,就怕志短",
+ "当今之世,舍我其谁",
+ "立志不坚,终不济事",
+ "鸟贵有翼,人贵有志",
+ "少年立志要远大,持身要紧严立志不高,则溺于流俗;",
+ "持身不严,则入于匪辞",
+ "人若有志,万事可为",
+ "心志要坚,意趣要乐",
+ "胸无大志,枉活一世",
+ "燕雀安知鸿鹄之志哉",
+ "一人立志,万夫莫敌",
+ "鹰爱高飞,鸦栖一枝",
+ "治天下者必先立其志",
+ "强行者有志",
+ "志当存高远",
+ "百学须先立志",
+ "以天下为己任",
+ "志,气之帅也",
+ "才自清明志自高",
+ "褴褛衣内可藏志",
+ "无所求则无所获",
+ "慷慨丈夫志,可以耀锋芒",
+ "母鸡的理想不过是一把糠",
+ "男儿千年志,吾生未有涯",
+ "男儿四方志,岂久困泥沙",
+ "男子千年志,吾生未有涯",
+ "穷且益坚,不坠青云之志",
+ "人生志气立,所贵功业昌",
+ "生无一锥土,常有四海心",
+ "无志愁压头,有志能搬山",
+ "心随朗月高,志与秋霜洁",
+ "胸有凌云志,无高不可攀",
+ "雄心志四海,万里望风尘",
+ "一分事业心能抵十分特权",
+ "有志登山顶,无志站山脚",
+ "丈夫清万里,谁能扫一室",
+ "丈夫四海志,万里犹比邻",
+ "丈夫志不大,何以佐乾坤",
+ "丈夫志气薄,儿女安得知",
+ "志不立,天下无可成之事",
+ "志高山峰矮,路从脚下伸",
+ "壮志与毅力是事业的双翼",
+ "成功是别人失败时还在坚持",
+ "贫不足羞,可羞是贫而无志",
+ "虽长不满七尺,而心雄万丈",
+ "有志者能使石头长出青草来",
+ "志之难也,不在胜人,在自胜",
+ "有志始知蓬莱近,无为总觉咫尺远",
+ "不要在夕阳西下时幻想,要在旭日东升时努力",
+ "立志是事业的大门,工作是登门入室的的旅途",
+ "一个人如果胸无大志,既使再有壮丽的举动也称不上是伟人",
+ "志不立,如无舵这舟,无衔之马,漂荡奔逸,终亦何所底乎",
+ "有志不在年高,无志空活百岁",
+ };
+
+ public static string[] GaoKaoPhrases = new string[] {
+ "以梦为马,不负韶华。祝你高考顺利,未来可期!",
+ "高考顺利,愿你乘风破浪,前程似锦!",
+ "愿你高考顺利,不负韶华,梦想成真!",
+ "高考必胜,愿你展翅高飞,未来可期!",
+ "愿你不畏困难,勇往直前,高考成绩如你所愿,未来更加光明。",
+ "高考将至,愿你所学皆精,所考皆通,一鸣惊人,一举夺魁!",
+ "十年磨一剑,今朝试锋芒。高考顺利,未来可期!",
+ "恭祝,恭祝,此战青云平步。祝高考金榜题名。",
+ };
+ }
+}
diff --git a/Ink Canvas/Resources/Cursors/Cursor.cur b/Ink Canvas/Resources/Cursors/Cursor.cur
new file mode 100644
index 00000000..95b01752
Binary files /dev/null and b/Ink Canvas/Resources/Cursors/Cursor.cur differ
diff --git a/Ink Canvas/Resources/Cursors/Pen.cur b/Ink Canvas/Resources/Cursors/Pen.cur
new file mode 100644
index 00000000..323fefe5
Binary files /dev/null and b/Ink Canvas/Resources/Cursors/Pen.cur differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/Alan-CRL.png b/Ink Canvas/Resources/DeveloperAvatars/Alan-CRL.png
new file mode 100644
index 00000000..4aff7a43
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/Alan-CRL.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/CN-Ironegg.jpg b/Ink Canvas/Resources/DeveloperAvatars/CN-Ironegg.jpg
new file mode 100644
index 00000000..aeb7da94
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/CN-Ironegg.jpg differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/ChangSakura.png b/Ink Canvas/Resources/DeveloperAvatars/ChangSakura.png
new file mode 100644
index 00000000..a1f21215
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/ChangSakura.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/NetheriteBowl.png b/Ink Canvas/Resources/DeveloperAvatars/NetheriteBowl.png
new file mode 100644
index 00000000..39f224e4
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/NetheriteBowl.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/NotYoojun.png b/Ink Canvas/Resources/DeveloperAvatars/NotYoojun.png
new file mode 100644
index 00000000..b328c1de
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/NotYoojun.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/RaspberryKan.jpg b/Ink Canvas/Resources/DeveloperAvatars/RaspberryKan.jpg
new file mode 100644
index 00000000..d26b4db0
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/RaspberryKan.jpg differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/STBBRD.png b/Ink Canvas/Resources/DeveloperAvatars/STBBRD.png
new file mode 100644
index 00000000..098d12e7
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/STBBRD.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/WXRIW.png b/Ink Canvas/Resources/DeveloperAvatars/WXRIW.png
new file mode 100644
index 00000000..35b2da50
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/WXRIW.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/aaaaaaccd.jpg b/Ink Canvas/Resources/DeveloperAvatars/aaaaaaccd.jpg
new file mode 100644
index 00000000..cca5f67a
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/aaaaaaccd.jpg differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/clover-yan.png b/Ink Canvas/Resources/DeveloperAvatars/clover-yan.png
new file mode 100644
index 00000000..162440fd
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/clover-yan.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/dubi906w.jpg b/Ink Canvas/Resources/DeveloperAvatars/dubi906w.jpg
new file mode 100644
index 00000000..914e5024
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/dubi906w.jpg differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/jiajiaxd.jpg b/Ink Canvas/Resources/DeveloperAvatars/jiajiaxd.jpg
new file mode 100644
index 00000000..e845b2cd
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/jiajiaxd.jpg differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/kengwang.png b/Ink Canvas/Resources/DeveloperAvatars/kengwang.png
new file mode 100644
index 00000000..1170d789
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/kengwang.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/wwei.png b/Ink Canvas/Resources/DeveloperAvatars/wwei.png
new file mode 100644
index 00000000..379b90f8
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/wwei.png differ
diff --git a/Ink Canvas/Resources/DeveloperAvatars/yuwenhui2020.png b/Ink Canvas/Resources/DeveloperAvatars/yuwenhui2020.png
new file mode 100644
index 00000000..61abd488
Binary files /dev/null and b/Ink Canvas/Resources/DeveloperAvatars/yuwenhui2020.png differ
diff --git a/Ink Canvas/Resources/DrawShapeImageDictionary.xaml b/Ink Canvas/Resources/DrawShapeImageDictionary.xaml
new file mode 100644
index 00000000..c7e2428d
--- /dev/null
+++ b/Ink Canvas/Resources/DrawShapeImageDictionary.xaml
@@ -0,0 +1,1136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Resources/IconImageDictionary.xaml b/Ink Canvas/Resources/IconImageDictionary.xaml
new file mode 100644
index 00000000..5231b528
--- /dev/null
+++ b/Ink Canvas/Resources/IconImageDictionary.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_add_circle_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_add_circle_24_regular.png
new file mode 100644
index 00000000..8cff4ad8
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_add_circle_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_left_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_left_24_regular.png
new file mode 100644
index 00000000..bb4ca412
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_left_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_right_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_right_24_regular.png
new file mode 100644
index 00000000..a1f32b60
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_circle_right_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_clockwise_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_clockwise_24_regular.png
new file mode 100644
index 00000000..d0df658c
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_clockwise_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_rotate_clockwise_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_rotate_clockwise_24_regular.png
new file mode 100644
index 00000000..83d839af
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_arrow_rotate_clockwise_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_book_question_mark_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_book_question_mark_24_regular.png
new file mode 100644
index 00000000..1e81d1f8
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_book_question_mark_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_calendar_sync_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_calendar_sync_24_regular.png
new file mode 100644
index 00000000..1f8bc2e6
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_calendar_sync_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_camera_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_camera_24_regular.png
new file mode 100644
index 00000000..65cd343b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_camera_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_clock_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_clock_24_regular.png
new file mode 100644
index 00000000..917c24aa
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_clock_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png
new file mode 100644
index 00000000..2a3b12e2
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_24_regular.png
new file mode 100644
index 00000000..5111c67d
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_add_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_add_24_regular.png
new file mode 100644
index 00000000..282f5978
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_copy_add_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursorWITHdelete_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursorWITHdelete_24_regular.png
new file mode 100644
index 00000000..e7be83b3
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursorWITHdelete_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursor_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursor_24_regular.png
new file mode 100644
index 00000000..9a257c47
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_cursor_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dark_theme_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dark_theme_24_regular.png
new file mode 100644
index 00000000..5033b8ca
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dark_theme_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_delete_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_delete_24_regular.png
new file mode 100644
index 00000000..3f63c700
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_delete_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dismiss_circle_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dismiss_circle_24_regular.png
new file mode 100644
index 00000000..12cce339
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dismiss_circle_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_drag_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_drag_24_regular.png
new file mode 100644
index 00000000..b124eed3
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_drag_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dual_screen_span_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dual_screen_span_24_regular.png
new file mode 100644
index 00000000..f09da311
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_dual_screen_span_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_edit_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_edit_24_regular.png
new file mode 100644
index 00000000..eb115c18
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_edit_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_horizontal_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_horizontal_24_regular.png
new file mode 100644
index 00000000..8d8017b9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_horizontal_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_vertical_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_vertical_24_regular.png
new file mode 100644
index 00000000..cdde7533
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_flip_vertical_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_folder_open_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_folder_open_24_regular.png
new file mode 100644
index 00000000..36f4ee95
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_folder_open_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_keyboard_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_keyboard_24_regular.png
new file mode 100644
index 00000000..6e6b6be8
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_keyboard_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_lasso_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_lasso_24_regular.png
new file mode 100644
index 00000000..8fc71dc6
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_lasso_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_24_regular.png
new file mode 100644
index 00000000..1a6531b9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_money_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_money_24_regular.png
new file mode 100644
index 00000000..39dc566b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_people_money_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_person_money_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_person_money_24_regular.png
new file mode 100644
index 00000000..b408b1fd
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_person_money_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_power_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_power_24_regular.png
new file mode 100644
index 00000000..0d4d216e
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_power_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_save_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_save_24_regular.png
new file mode 100644
index 00000000..9c011039
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_save_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scale_fit_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scale_fit_24_regular.png
new file mode 100644
index 00000000..96423d8d
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scale_fit_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scales_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scales_24_regular.png
new file mode 100644
index 00000000..2d5c7ad9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_scales_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_settings_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_settings_24_regular.png
new file mode 100644
index 00000000..1b47f7ae
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_settings_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_shapes_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_shapes_24_regular.png
new file mode 100644
index 00000000..8d1061ea
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_shapes_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_signature_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_signature_24_regular.png
new file mode 100644
index 00000000..96712711
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_signature_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_timer_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_timer_24_regular.png
new file mode 100644
index 00000000..959a94d9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_timer_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_moon_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_moon_24_regular.png
new file mode 100644
index 00000000..c643601b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_moon_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_sunny_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_sunny_24_regular.png
new file mode 100644
index 00000000..017da27e
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_weather_sunny_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/ic_fluent_whiteboard_24_regular.png b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_whiteboard_24_regular.png
new file mode 100644
index 00000000..d9972bf1
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/ic_fluent_whiteboard_24_regular.png differ
diff --git a/Ink Canvas/Resources/Icons-Fluent/party.png b/Ink Canvas/Resources/Icons-Fluent/party.png
new file mode 100644
index 00000000..76aca439
Binary files /dev/null and b/Ink Canvas/Resources/Icons-Fluent/party.png differ
diff --git a/Ink Canvas/Resources/Icons-png/AdmoxBooth.png b/Ink Canvas/Resources/Icons-png/AdmoxBooth.png
new file mode 100644
index 00000000..de7cd830
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/AdmoxBooth.png differ
diff --git a/Ink Canvas/Resources/Icons-png/AdmoxWhiteboard.png b/Ink Canvas/Resources/Icons-png/AdmoxWhiteboard.png
new file mode 100644
index 00000000..0e8a1d93
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/AdmoxWhiteboard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/Desmos.png b/Ink Canvas/Resources/Icons-png/Desmos.png
new file mode 100644
index 00000000..80f84afa
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/Desmos.png differ
diff --git a/Ink Canvas/Resources/Icons-png/Donview.png b/Ink Canvas/Resources/Icons-png/Donview.png
new file mode 100644
index 00000000..751c4aff
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/Donview.png differ
diff --git a/Ink Canvas/Resources/Icons-png/EasiCamera.png b/Ink Canvas/Resources/Icons-png/EasiCamera.png
new file mode 100644
index 00000000..5f33e682
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/EasiCamera.png differ
diff --git a/Ink Canvas/Resources/Icons-png/EasiNote.png b/Ink Canvas/Resources/Icons-png/EasiNote.png
new file mode 100644
index 00000000..2161d59e
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/EasiNote.png differ
diff --git a/Ink Canvas/Resources/Icons-png/EasiNote3.png b/Ink Canvas/Resources/Icons-png/EasiNote3.png
new file mode 100644
index 00000000..3fe8e79a
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/EasiNote3.png differ
diff --git a/Ink Canvas/Resources/Icons-png/EasiNote3C.png b/Ink Canvas/Resources/Icons-png/EasiNote3C.png
new file mode 100644
index 00000000..01b5ed51
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/EasiNote3C.png differ
diff --git a/Ink Canvas/Resources/Icons-png/EasiNote5C.png b/Ink Canvas/Resources/Icons-png/EasiNote5C.png
new file mode 100644
index 00000000..f73a074a
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/EasiNote5C.png differ
diff --git a/Ink Canvas/Resources/Icons-png/HiteAnnotation.png b/Ink Canvas/Resources/Icons-png/HiteAnnotation.png
new file mode 100644
index 00000000..f0d41dfa
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/HiteAnnotation.png differ
diff --git a/Ink Canvas/Resources/Icons-png/HiteBoard.png b/Ink Canvas/Resources/Icons-png/HiteBoard.png
new file mode 100644
index 00000000..550fdbdd
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/HiteBoard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/HiteCamera.png b/Ink Canvas/Resources/Icons-png/HiteCamera.png
new file mode 100644
index 00000000..77b1b12f
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/HiteCamera.png differ
diff --git a/Ink Canvas/Resources/Icons-png/HiteLightBoard.png b/Ink Canvas/Resources/Icons-png/HiteLightBoard.png
new file mode 100644
index 00000000..c0ca4c0c
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/HiteLightBoard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/InkCanvas.png b/Ink Canvas/Resources/Icons-png/InkCanvas.png
new file mode 100644
index 00000000..21a3fe9d
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/InkCanvas.png differ
diff --git a/Ink Canvas/Resources/Icons-png/MaxHubWhiteboard.png b/Ink Canvas/Resources/Icons-png/MaxHubWhiteboard.png
new file mode 100644
index 00000000..ca254976
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/MaxHubWhiteboard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/PPTTools.png b/Ink Canvas/Resources/Icons-png/PPTTools.png
new file mode 100644
index 00000000..bdc0ebcf
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/PPTTools.png differ
diff --git a/Ink Canvas/Resources/Icons-png/Powerpoint.png b/Ink Canvas/Resources/Icons-png/Powerpoint.png
new file mode 100644
index 00000000..28a48ec9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/Powerpoint.png differ
diff --git a/Ink Canvas/Resources/Icons-png/Seewo2Annotation.png b/Ink Canvas/Resources/Icons-png/Seewo2Annotation.png
new file mode 100644
index 00000000..e1c62d91
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/Seewo2Annotation.png differ
diff --git a/Ink Canvas/Resources/Icons-png/SeewoPinco.png b/Ink Canvas/Resources/Icons-png/SeewoPinco.png
new file mode 100644
index 00000000..ac8c87bb
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/SeewoPinco.png differ
diff --git a/Ink Canvas/Resources/Icons-png/VComYouJiao.png b/Ink Canvas/Resources/Icons-png/VComYouJiao.png
new file mode 100644
index 00000000..a8e64175
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/VComYouJiao.png differ
diff --git a/Ink Canvas/Resources/Icons-png/WPS.png b/Ink Canvas/Resources/Icons-png/WPS.png
new file mode 100644
index 00000000..f0993570
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/WPS.png differ
diff --git a/Ink Canvas/Resources/Icons-png/WenXiang.png b/Ink Canvas/Resources/Icons-png/WenXiang.png
new file mode 100644
index 00000000..efabf098
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/WenXiang.png differ
diff --git a/Ink Canvas/Resources/Icons-png/Whiteboard.png b/Ink Canvas/Resources/Icons-png/Whiteboard.png
new file mode 100644
index 00000000..865040b9
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/Whiteboard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/YiYunVisualPresenter.png b/Ink Canvas/Resources/Icons-png/YiYunVisualPresenter.png
new file mode 100644
index 00000000..4671f558
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/YiYunVisualPresenter.png differ
diff --git a/Ink Canvas/Resources/Icons-png/YiYunWhiteboard.png b/Ink Canvas/Resources/Icons-png/YiYunWhiteboard.png
new file mode 100644
index 00000000..dc69bbe8
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/YiYunWhiteboard.png differ
diff --git a/Ink Canvas/Resources/Icons-png/check-box-background.png b/Ink Canvas/Resources/Icons-png/check-box-background.png
new file mode 100644
index 00000000..6b8b7ba2
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/check-box-background.png differ
diff --git a/Ink Canvas/Resources/Icons-png/close-circle.png b/Ink Canvas/Resources/Icons-png/close-circle.png
new file mode 100644
index 00000000..e367c9ae
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/close-circle.png differ
diff --git a/Ink Canvas/Resources/Icons-png/down.png b/Ink Canvas/Resources/Icons-png/down.png
new file mode 100644
index 00000000..8e3b571f
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/down.png differ
diff --git a/Ink Canvas/Resources/Icons-png/eraser-line.png b/Ink Canvas/Resources/Icons-png/eraser-line.png
new file mode 100644
index 00000000..fa280d07
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/eraser-line.png differ
diff --git a/Ink Canvas/Resources/Icons-png/eraser-outline.png b/Ink Canvas/Resources/Icons-png/eraser-outline.png
new file mode 100644
index 00000000..31417199
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/eraser-outline.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/arrow.png b/Ink Canvas/Resources/Icons-png/geo-icons/arrow.png
new file mode 100644
index 00000000..23bb85fa
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/arrow.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle-dashed.png b/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle-dashed.png
new file mode 100644
index 00000000..5dbdf15e
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle-dashed.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle.png b/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle.png
new file mode 100644
index 00000000..88db868d
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/centered-circle.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/centered-oval.png b/Ink Canvas/Resources/Icons-png/geo-icons/centered-oval.png
new file mode 100644
index 00000000..099718e1
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/centered-oval.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/centered-square.png b/Ink Canvas/Resources/Icons-png/geo-icons/centered-square.png
new file mode 100644
index 00000000..22169f67
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/centered-square.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/cone.png b/Ink Canvas/Resources/Icons-png/geo-icons/cone.png
new file mode 100644
index 00000000..f1cf4ca5
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/cone.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/cube.png b/Ink Canvas/Resources/Icons-png/geo-icons/cube.png
new file mode 100644
index 00000000..f882b0fe
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/cube.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/cylinder.png b/Ink Canvas/Resources/Icons-png/geo-icons/cylinder.png
new file mode 100644
index 00000000..3232b222
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/cylinder.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/dashed-line.png b/Ink Canvas/Resources/Icons-png/geo-icons/dashed-line.png
new file mode 100644
index 00000000..dbb63b2b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/dashed-line.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/dotted-line.png b/Ink Canvas/Resources/Icons-png/geo-icons/dotted-line.png
new file mode 100644
index 00000000..97233c43
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/dotted-line.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/line.png b/Ink Canvas/Resources/Icons-png/geo-icons/line.png
new file mode 100644
index 00000000..d2ef2dd0
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/line.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/paralle-lines.png b/Ink Canvas/Resources/Icons-png/geo-icons/paralle-lines.png
new file mode 100644
index 00000000..c165763b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/paralle-lines.png differ
diff --git a/Ink Canvas/Resources/Icons-png/geo-icons/square.png b/Ink Canvas/Resources/Icons-png/geo-icons/square.png
new file mode 100644
index 00000000..051efc85
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/geo-icons/square.png differ
diff --git a/Ink Canvas/Resources/Icons-png/ica.png b/Ink Canvas/Resources/Icons-png/ica.png
new file mode 100644
index 00000000..76209ba2
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/ica.png differ
diff --git a/Ink Canvas/Resources/Icons-png/icc-transparent-dark-small.png b/Ink Canvas/Resources/Icons-png/icc-transparent-dark-small.png
new file mode 100644
index 00000000..b2bbf8bf
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/icc-transparent-dark-small.png differ
diff --git a/Ink Canvas/Resources/Icons-png/icc-transparent-dark.png b/Ink Canvas/Resources/Icons-png/icc-transparent-dark.png
new file mode 100644
index 00000000..b2bbf8bf
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/icc-transparent-dark.png differ
diff --git a/Ink Canvas/Resources/Icons-png/icc-transparent.png b/Ink Canvas/Resources/Icons-png/icc-transparent.png
new file mode 100644
index 00000000..b2bbf8bf
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/icc-transparent.png differ
diff --git a/Ink Canvas/Resources/Icons-png/icc.png b/Ink Canvas/Resources/Icons-png/icc.png
new file mode 100644
index 00000000..ae5a6e73
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/icc.png differ
diff --git a/Ink Canvas/Resources/Icons-png/idt.png b/Ink Canvas/Resources/Icons-png/idt.png
new file mode 100644
index 00000000..73b7db28
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/idt.png differ
diff --git a/Ink Canvas/Resources/Icons-png/kuanciya.png b/Ink Canvas/Resources/Icons-png/kuanciya.png
new file mode 100644
index 00000000..46ea474e
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/kuanciya.png differ
diff --git a/Ink Canvas/Resources/Icons-png/kuandogeyuanliangwo.png b/Ink Canvas/Resources/Icons-png/kuandogeyuanliangwo.png
new file mode 100644
index 00000000..fe174aff
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/kuandogeyuanliangwo.png differ
diff --git a/Ink Canvas/Resources/Icons-png/kuandoujiyanhuaji.png b/Ink Canvas/Resources/Icons-png/kuandoujiyanhuaji.png
new file mode 100644
index 00000000..42ce15d1
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/kuandoujiyanhuaji.png differ
diff --git a/Ink Canvas/Resources/Icons-png/kuanneikuhuaji.png b/Ink Canvas/Resources/Icons-png/kuanneikuhuaji.png
new file mode 100644
index 00000000..f7ff6602
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/kuanneikuhuaji.png differ
diff --git a/Ink Canvas/Resources/Icons-png/kuanshounvhuaji.png b/Ink Canvas/Resources/Icons-png/kuanshounvhuaji.png
new file mode 100644
index 00000000..a29e79ac
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/kuanshounvhuaji.png differ
diff --git a/Ink Canvas/Resources/Icons-png/minimize.png b/Ink Canvas/Resources/Icons-png/minimize.png
new file mode 100644
index 00000000..4c7777ac
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/minimize.png differ
diff --git a/Ink Canvas/Resources/Icons-png/penUpright.png b/Ink Canvas/Resources/Icons-png/penUpright.png
new file mode 100644
index 00000000..fd566c5b
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/penUpright.png differ
diff --git a/Ink Canvas/Resources/Icons-png/playCircle.png b/Ink Canvas/Resources/Icons-png/playCircle.png
new file mode 100644
index 00000000..cb7ce2e2
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/playCircle.png differ
diff --git a/Ink Canvas/Resources/Icons-png/pressdown-background.png b/Ink Canvas/Resources/Icons-png/pressdown-background.png
new file mode 100644
index 00000000..b2bbf8bf
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/pressdown-background.png differ
diff --git a/Ink Canvas/Resources/Icons-png/redo.png b/Ink Canvas/Resources/Icons-png/redo.png
new file mode 100644
index 00000000..23f5c982
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/redo.png differ
diff --git a/Ink Canvas/Resources/Icons-png/setting.png b/Ink Canvas/Resources/Icons-png/setting.png
new file mode 100644
index 00000000..4a4cd210
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/setting.png differ
diff --git a/Ink Canvas/Resources/Icons-png/tiebahuaji.png b/Ink Canvas/Resources/Icons-png/tiebahuaji.png
new file mode 100644
index 00000000..11b9603c
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/tiebahuaji.png differ
diff --git a/Ink Canvas/Resources/Icons-png/transparent-grid.png b/Ink Canvas/Resources/Icons-png/transparent-grid.png
new file mode 100644
index 00000000..21c01463
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/transparent-grid.png differ
diff --git a/Ink Canvas/Resources/Icons-png/twoFingelMove-Blue.png b/Ink Canvas/Resources/Icons-png/twoFingelMove-Blue.png
new file mode 100644
index 00000000..8bbe0f5d
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/twoFingelMove-Blue.png differ
diff --git a/Ink Canvas/Resources/Icons-png/twoFingelMove.png b/Ink Canvas/Resources/Icons-png/twoFingelMove.png
new file mode 100644
index 00000000..97f2c781
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/twoFingelMove.png differ
diff --git a/Ink Canvas/Resources/Icons-png/undo.png b/Ink Canvas/Resources/Icons-png/undo.png
new file mode 100644
index 00000000..1be1ff63
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/undo.png differ
diff --git a/Ink Canvas/Resources/Icons-png/up.png b/Ink Canvas/Resources/Icons-png/up.png
new file mode 100644
index 00000000..a472aafb
Binary files /dev/null and b/Ink Canvas/Resources/Icons-png/up.png differ
diff --git a/Ink Canvas/Resources/Icons/DrawShapeIcon.ai b/Ink Canvas/Resources/Icons/DrawShapeIcon.ai
new file mode 100644
index 00000000..80e6f4b5
--- /dev/null
+++ b/Ink Canvas/Resources/Icons/DrawShapeIcon.ai
@@ -0,0 +1,1136 @@
+%PDF-1.5
%
+1 0 obj
<>/OCGs[21 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+
+
+
+
+ application/pdf
+
+
+ DrawShapeIcon
+
+
+ Adobe Illustrator 24.0 (Windows)
+ 2021-12-05T10:47:36+09:00
+ 2021-12-05T10:47:37+08:00
+ 2021-12-05T10:47:37+08:00
+
+
+
+ 256
+ 240
+ JPEG
+ /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA8AEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXmn/OQX5m
3f5e/l9LqenBf0xfTLY6azjksckis7SlTseCRsRXblSu22KvgfXPMWva9fPfa1qFxqN45JM1zI0r
CprQcieI9htiqXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqiLDUdQ066S70+5ls7uI1iuIHaKRSN6
q6EMMVfbH/OLH5v6x530G/0fzDcfWta0T0yl41BJPbS1Cl6AVeNk4s3eorvU4q90xV2KuxV2KuxV
2KuxV2KuxV2KuxV2KuxV2KuxV81/85vf8ot5a/5jpv8Akzir4/xV2KuxV2KuxV2KuxV2KuxV2Kux
V2KuxV2KuxV9F/8AOErN/j3XlqeJ0qpXsSLiKh/HFX2TirsVdirsVdirsVdirsVdirsVdirsVdir
sVdir5r/AOc3v+UW8tf8x03/ACZxV8f4qn3kLR7LWvPPl3Rr4M1lqWp2VndBDxYxT3CRvxbseLHf
FX2Z/wBChfk3/wAs19/0lt/TFXf9Chfk3/yzX3/SW39MVd/0KF+Tf/LNff8ASW39MVd/0KF+Tf8A
yzX3/SW39MVd/wBChfk3/wAs19/0lt/TFXf9Chfk3/yzX3/SW39MVd/0KF+Tf/LNff8ASW39MVd/
0KF+Tf8AyzX3/SW39MVd/wBChfk3/wAs19/0lt/TFXf9Chfk3/yzX3/SW39MVd/0KF+Tf/LNff8A
SW39MVfK/wCfPkrQ/Jf5l6h5f0NZE062it3iWZzI9ZYVdqsf8psVee4q+iv+cJf+U/13/tlH/qJi
xV9lYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+a/+c3v+UW8tf8AMdN/yZxV8f4qyv8AKf8A
8mn5N/7bmm/9RkeKv0pxV2KuxV2KuxV2KuxV2KuxV2KuxV8F/wDOWH/k7dY/4wWf/UNHirx/FX0V
/wA4S/8AKf67/wBso/8AUTFir7KxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV81/85vf8ot5a
/wCY6b/kzir4/wAVZX+U/wD5NPyb/wBtzTf+oyPFX6U4q7FXYq7FXYq7FXYq7FXYq7FXYq+C/wDn
LD/ydusf8YLP/qGjxV4/ir6M/wCcJEc+e9ekAPBdL4s3YFriMgfTxOKvsjFXYq7FXYq7FXYq7FXY
q7FXYq7FXYq7FXYq7FXzX/zm9/yi3lr/AJjpv+TOKvj/ABVlf5T/APk0/Jv/AG3NN/6jI8VfpTir
sVdirsVdirsVdirsVdirsVdir4L/AOcsP/J26x/xgs/+oaPFXkKI7uqIpZ2ICqBUknoAMVffP/OO
X5RH8vvJpl1BaeY9a9O41MH/AHSqg+lbD/jGGJb/ACiewGKsg/MT86fy+8gFIdfvz9flXnHp1shm
uCh/aKigQHsXYV7YqlXkX/nI78rfOWpppVhfyWWpTHjbWuoR+gZj4RuC8ZY9l5cj2GKvTsVdirsV
dirsVdirsVdirsVdirsVdirsVfNf/Ob3/KLeWv8AmOm/5M4q+P8AFWV/lP8A+TT8m/8Abc03/qMj
xV+lOKuxV2KuxV2KuxV2KuxV2KuxV2Kvgv8A5yw/8nbrH/GCz/6ho8VTz/nEz8qP8S+am826nDy0
Xy/IptlYVWa/pyQfKEESH34++KvrL8yPPWmeRvJuo+ZL8hltI6W1vWhmuH+GKJf9ZuvgtT2xV+cf
mLzBqvmLXL7XNWnNxqOoStPcSmv2m6Kta0VRRVXsABiqXo7o6ujFXUgqwNCCOhBxV99f843/AJrH
z75GSO/m9TzFovC11QsavKpB9G4/56KpDf5Stir1jFXYq7FXYq7FXYq7FXYq7FXYq7FXYq+a/wDn
N7/lFvLX/MdN/wAmcVfH+Ksr/Kf/AMmn5N/7bmm/9RkeKv0pxV2KuxV2KuxV2KuxV2KuxV2KuxV8
P/8AORHlvVfM3/OR1xoOkxerqGoixggXsCbZCWY9lRQWY9gMVfYPkLyZpXkvylp3lvTB/o9jEFeU
gBpZW+KWV6ftO5J9umKvjz/nKr81/wDFvnH/AA7pk3PQfLzvFyU1Se9+zNLt1VP7tP8AZEbNirw3
FXYqzn8mfzJuvy+892WtqWbTpP8ARtWt139S1kI50HdkIDr7imKv0Vs7y1vbOC9tJVntLmNJredD
yR45FDI6kdQymoxVWxV2KuxV2KuxV2KuxV2KuxV2KuxV81/85vf8ot5a/wCY6b/kzir4/wAVZX+U
/wD5NPyb/wBtzTf+oyPFX6U4q7FXYq7FXYq7FXYq7FXYq7FXYqwjSvyxsLX809c/MC5dZ7/ULe3t
NPjp/vPFHEqTNv8AtyFBuOi7dzirHP8AnJL81x5D8jPBp83DzHrYa203iaPElP31z/zzU0X/ACiP
A4q+BiSTU7k4q1irsVdir6//AOcPvzW/SOky+QdVmre6arT6Mz9XtSayQ1PUxM1VH8p8FxV9K4q7
FXYq7FXYq7FXYq7FXYq7FXYq+a/+c3v+UW8tf8x03/JnFXx/irK/yn/8mn5N/wC25pv/AFGR4q/S
nFXYq7FXYq7FXYq7FXYq7FXYq7FVDUL+z06wub++mW3srSJ57mdzRUjjUs7N7BRXFX50fnB+ZF7+
YPnm916XklkD9X0q2Y/3VrGTwFP5mqXb/KJxVhOKs+/JP8srn8w/PVppBDLpUFLrWLhajhbIRyUM
OjyH4F+dexxVmX/OUv5RQeS/NUWuaNbCDy5rlSkMYpHb3aD95EANlVx8af7IDZcVeH4qmvlXzLqv
ljzFp+v6VJ6V/p0yzwtvQ02ZGp1V1JVh3BOKv0i8jecNL84+VNO8x6Y1ba/iDmOtWjkHwyRN/lI4
KnFU9xV2KuxV2KuxV2KuxV2KuxV2Kvmv/nN7/lFvLX/MdN/yZxV8paD5a8w+Yb0WWhabc6nd9TDa
xPKwB7twB4j3O2KvoD8ov+cVPzDtfNGieZPMMtto1vpV7bX/ANSLfWLmT6tKswQiI+mnLjSpeo/l
xV9g4q7FXYq7FXYq7FXYq7FXYq7FXYq+Yf8AnMP81/qtnF+XulTUuLoJc666HdYdmhtyR/vw/Gw8
AvZsVfJOKrkR3dURSzsQFUCpJPQAYq/QH/nHn8qk/L/yJCl5EF8w6txutXYj4kYj91b18IVah/yi
2Ksr/MnyJpvnryZqPlu+ogu462txSphuE+KKUf6rdadVqO+Kvzg13RNS0LWb3RtThMGoafM9vcxH
s8ZoaHuD1B7jfFUBir6D/wCcRvzV/QHmZ/JmpzBdI16QNYs5osV/QKoH/GdQE/1gvvir7RxV2Kux
V2KuxV2KuxV2KuxV2Ksc84/l55Q85CxTzLp66jDp0rT20Du6xiRhxJZUZee3ZtsVTfStH0jR7JLL
SrKDT7KIfBb20aQxrQfyoFGKsK81fn7+Unlhni1DzFbzXSbG0suV3JyH7LegHVD/AK5GKvLda/5z
c8pwMy6L5cvr8A0DXU0VoD7/AAC6P4YqxW5/5zf8ysW+q+WLKIEfAJbiWSh8TxWOv4Yqo2//ADm5
5yUH6x5d06Q129N549vpaTFWQaV/znFYswXVvKcsS13ltLtZTSv++5Ioun+vir0byx/zlT+TuuOk
UupS6NcPssepwmJa+8sZlhX/AGTjFXqun6lp2pWiXmnXUN7aS7x3FvIssbD/ACXQlTiqIxV2KuxV
2KsZ/Mjz1pnkbybqPmS/IZbSOltb1oZrh/hiiX/Wbr4LU9sVfnDr+u6nr+t32tapMZ9Q1CZ7i5lP
d3NaAdlHQDsNsVS/FXvn/OJn5Uf4l81N5t1OHlovl+RTbKwqs1/Tkg+UIIkPvx98VfbGKuxV8t/8
5i/lV6sMP5h6VD8cQS115EHVCeMFwf8AVJEbf7HwOKvk/FV8UssUqSxO0csbBo5FJVlZTUEEbgg4
q/Qv8hvzRi/MLyHbX87qdcsKWmsxCgPrKPhmAH7My/F0pWo7Yq9GxV2KuxV2KuxV2KuxV2KuxV4p
+av/ADlL5K8nNLpui8fMOvJVXigcC0hb/i2ccuTD+RK+BK4q+UvP/wCd35j+eZJE1nVXj05yaaVa
VgtAPAoprJ85CxxVgeKuxV2KuxV2KuxVO/K3nbzb5UvReeXdVudMnqC/oOQj06CSM1jkHs6kYq+l
/wAsv+cyrad4dO/MCzFsxoo1uyVjHXpWe3HJl8S0df8AUGKvpjS9U03VbCDUNMuor2xuVDwXMDiS
N1PdWUkHFUVirsVfDv8AzlV+a/8Ai3zj/h3TJueg+XneLkpqk979maXbqqf3af7IjZsVeG4qmnlf
y3qvmbzBYaDpMXq6hqMywQL2BO5Zj2VFBZj2AxV+kPkLyZpXkvylp3lvTB/o9jEFeUgBpZW+KWV6
ftO5J9umKp/irsVQuq6XYatpl1pmowrc2F7E8F1A/wBl45FKsp+g4q/OP81Py+v/ACD531Dy7dcn
hhb1dPuSKetayVMUnzp8LU6MCO2KsRxV6V+QP5oyfl959t7u4kI0LUuNprMfYRM3wTU8YWPLx48h
3xV+hEckcsayRsHjcBkdSCrKRUEEdQcVXYq7FXYq7FXYq7FUNqep6fpen3Go6jcR2ljaRtLc3MrB
URFFSzE4q+Mfzy/5yf1fzXJc6B5Rkk03yzvFNeLWO5vV6Gp2aKJv5PtEfa68Qq8CxV2KuxVk3lv8
s/zB8zLHJoXl6/voJPsXUcDi3P8Az3YLEP8AgsVZzYf84ofnbdFfV0eCyVj9q4vLYgClakRPK2/T
piqJvP8AnEX854EDRWdldk1qkN3GCKf8ZfSG/wA8VYrrv5DfnDoi877yrfMlKlrRVvQAO7G1abj9
OKsElilhlaKVGjlQlXjcFWUjYgg7g4qsxV2Ks+/Kn85/N/5camJdMmNzpErhr7RpmPoSjoWXr6cl
Ojr9NRtir7r/AC3/ADL8sfmD5fTWNCnrxol7ZSUE9tKRX05F/wCIsNm7Yqp/m7deabX8tPMM/laN
pNdS0b6qI6+ooJAleOm/qJEXZKb8gMVfm2SSancnFWsVfYH/ADh/+VH6N0iTz9qsNL7U1aDRkcbx
2laPNQ9DMy0U/wAo8GxV9KYq7FXYq7FXi3/OUf5Vf4y8kNrGnRc9f8vK9xAFHxTWtKzw7bkgLzT3
FB9rFXwpirsVfan/ADiR+av+IfKzeT9Tm5avoEY+pFj8U1hXin0wGiH/ACSvvir6AxV2KuxV2Kux
VZcXEFvBJcXEixQQq0ksrkKqooqzMTsAAN8VfC3/ADkP+fV5591aTRNFmeHyfZSUiUVU3kiH+/kH
Xh/vtD8zvsFXi+KuxV65+U3/ADjZ528/RxalP/uE8uSbrqVyhaSZfG3gqrOP8piq+BNKYq+sPIX/
ADj3+V3kxY5bPSl1HUoyGGp6kFuZwwNQUBURRkdiiA+5xV6RirsVdirsVY35v/LfyN5wgMXmPRbb
UGK8VuHThcIPBJ04yp/sWxV8y/ml/wA4darpyTan5CuX1O1UF30a6Ki6Udf3MoCpL/qsFb3Y4q+b
rq1ubS5ltbqF7e5gdo54JVKSI6GjK6tQqwOxBxVSxVlH5dfmL5k8g+ZIdc0Obi60S6tXJ9G4hrVo
pVHUHseoO4xV+hP5fefdB89eV7XzDoshNvOOM0D09SCZac4ZAP2lr9IoRscVfJ3/ADlT+Sw8r60f
OGh2/Hy/q8p+uwxj4bW8erGgH2Y5tyvYNUbfCMVee/kn+WVz+Yfnq00ghl0qCl1rFwtRwtkI5KGH
R5D8C/OvY4q/RG1tba0tYbS1jWG2t0WKCFBRURAFVVA6AAUGKquKuxV2KuxV2Kvgr/nJj8qv8Dee
XvLCHh5e14vdWAUfDFKCDPb+3FmDL/ksB2OKvIMVZB5D856r5L82ad5k0w/6RYyhniJIWWI/DLE9
P2XQke3XFX6Q+WfMWl+ZNAsNe0qX1tP1GFZ7d+9GG6sOzKaqw7EYqmeKuxV2KuxV8uf85e/nBJbo
Py70WbjJMizeYJkNCEajRWtR/MKO/txHcjFXydirsVfVv/OPP/OMcBgtvN3n205u9JdL0GdfhC9V
lu0I3J6rEen7X8oVfU4AAAAoBsAMVdirsVdirsVdirsVdiryf87vyB0D8xbCS+tVTT/NsMdLTUQK
JNxHwxXQUVZdqB/tL7j4Sq+E9f0DWPL+sXWjazavZalZOY7m2kFGVhuCCNmVhurDYjcbYql+KvU/
+cfPzdn/AC985R/XJG/w3qrJBq8W5EYrRLkDxiLb+K1HWmKvu/XdE0fzJoN3pGpxJeaVqUJimSoI
ZHFQysOhGzKw6GhGKsR/Jr8n9I/LPQruwtZvrt7fXDzXWoMgR3jViLeOgJoI4z/wRY98VegYq7FX
Yq7FXYq7FWF/m/8AlzZ/mD5GvtBl4pe0+saXcMP7q7jB9Nq9lapRv8knFX5z39heaffXFhewtb3l
pI8FzA4oySRsVdWHiGFMVQ+Kvpn/AJw9/NX6jqc3kDVZgLTUGa40R3OyXIFZYN+0qjkv+UD3bFX1
3irsVdirH/zA842Pk3ybqvmW9HKLToC8cVaepMxCQx/7ORlXFX5sazq+oazq15q2oyme/v5nuLmU
9WkkYsx+87DFUFir6M/5xR/JSPX9QHnrX4Oej6dLx0i1cfDcXUZ3lavWOE9PF/8AVIKr7IxV2Kux
V2KuxV2KuxV2KuxV2KvF/wDnJX8lYvPXlxtb0mEf4r0eJmg4j4ru3WrNbGm5YbtF/lVH7VQq+FCC
DQ7EdRirWKvuD/nEr8yG8y+Q28vX0pfVfLRWBWY1Z7OSv1dt/wCTi0fsAvjir3TFXYq7FXYq7FXY
q7FXYq+Rv+cw/wAqvqWow/mBpcNLW+ZLbW0QbJcAUinNO0ijgx/mA7tir5kxVXsb67sL23vrOVoL
u1kSa3nQ0ZJI2DIynxBFcVfov+Tv5kWn5g+RbHXUKpfqPq+q26/7qu4wOYp2V6h1/wAkjFWbYq7F
Xy1/zmz5zZIdC8mwPT1eWqX6juqlobcfIt6p+gYq+UMVTryX5Wv/ADX5r0vy5YA/WdTuEgD05BEJ
rJKR/LGgZz7DFX6U+XPL+meXdBsND0uL0dP06BLe3TvxQU5MRSrMd2Pc74qmOKuxV2KuxV2KuxV2
KuxV2KuxV2KvhL/nKj8to/KH5hnUrCL09H8xq95AoACJchv9KiUeHJlkHYc6DpirxjFXp/8Azjf5
zbyr+bWjyu/Cy1Vv0XejsUuiFjJ/1ZgjfIYq/QXFXYq7FXYq7FXYq7FXYqlvmXy9pfmPQb/QtViE
2n6jC0FxGetGGzKezKaMp7EVxV+b3n7yXqnkrzdqPlvUhWexk4pMBRZYmHKKVfZ0IPt07Yqx7FXr
3/ONX5q/4F89Ja383p+XddKWuoljRIpKkQXBr04M3Fj/ACknsMVfe2KuxV+e/wDzkf5hbXPzl8xy
8uUNjMunQrWoUWiCJwP+equfpxV5nir6S/5wp8pRXnmnW/NE6chpNulpaclqBNdli7qezLHEV+T4
q+wsVdirsVdirsVdirsVdirsVdirsVdirx3/AJyt8pJr35R314kZe90GWPUICo34A+lOCf5fSkLn
/VGKvg3FV8UskMqSxMUljYOjjYhlNQR8jir9O/KGuJr/AJU0bXFoBqllb3ZUdjPErlfoLUxVNsVd
irsVdirsVdirsVdirwL/AJy1/Kr/ABH5VXzdpkPLWfL8bG7CirS2G7OPnCSZB/k8vbFXxRirsVfd
X/OLf5rf4x8lDRdRm5+YPLypBMW+1Na04wTb/aIA4OfEAn7WKvasVfl55i1FtT8wanqTHk19dz3J
bxMsjPXoP5sVS7FX3F/zh3o31H8ozekfFquo3NyD/kxhLcD5Vhb78Ve5Yq7FXYq7FXYq7FXYq7FX
Yq7FXYq7FUs80aPFrflrVtGlr6epWdxaPTrSeJozT/gsVfl9irsVfoL/AM4zaib78kfLTs1ZIY7i
3YeAhupUQf8AABcVen4q7FXYq7FXYq7FXYq7FWnRJEaORQ6OCrowqCDsQQcVfnx/zkB+Vr/l959u
LW2jI0HUuV3oz9QsTN8cFfGFjx/1eJ74q8zxVlv5WfmBqHkLztp/mK05NFC3pX9uDT1rWQgSxn6P
iWvRgD2xV+jmk6rYavpdpqmnTLcWF9ClxazL0eORQyn7jir8tsVdir79/wCcWQg/Ivy4V6k3xffv
9fnH6qYq9XxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV+WeoJEl/cpEAIlldYwNxxDECn0Yqh8VfeH
/OJTTH8ldOEihUW6vBCR3X1mNT/siRiqZfnF+fmjfljf6bZX2mXGoy6jFJMpgdECLGwXfn1qTirz
3/od7yt/1LV9/wAjocVd/wBDveVv+pavv+R0OKu/6He8rf8AUtX3/I6HFXf9DveVv+pavv8AkdDi
rv8Aod7yt/1LV9/yOhxV3/Q73lb/AKlq+/5HQ4q7/od7yt/1LV9/yOhxV3/Q73lb/qWr7/kdDirA
fzo/5yI8kfmT5QbR38vXdpqVvItxpl+0kTelINnDAUJSRKgjxoe2Kvn3FXYq+rf+cOvzW5JL+Xeq
S/EnqXWgOx6jd57YfLeVf9n7Yq+XtYsG0/V76wYENaXEsDA9QYnKb9PDFUHir7p/5xB1ZL78nILU
fa0u/urVvm7Lc/quMVe14q7FXYq7FXYq7FXYq7FXYq7FXYq7FUHrOpQaXo99qdw3GCxt5bmVj2SF
C7H7lxV+W+KuxV+gH/OL1g1n+SHl0OCHuPrU5B8JLuUpT5pQ4q+e/wDnM/UBcfmnY2qn4bPSYFYb
bPJPNIf+FZcVeB4q7FXYq7FXYq7FXYq7FXYq7FXYqmHl/W77QtcsNasHKXmnXEdzAwNPiiYMAfY0
ofbFWY/n9oDaH+cPmi048Y57xr2LagK3oFz8PsDKR9GKvPsVfUP/ADhJ5rWPUfMPlSZz/pEcepWa
fs8oj6M/0sJIv+BOKvrPFXYq7FXYq7FXYq7FXYq7FXYq7FXYq8t/5yZ81J5e/J3WyJAl1qyrpdsp
/bN0aTKP+jdZDir8/cVbAJNBuTir9M/y+0A+XvIugaIy8JdP0+2gnA/36sS+qfpepxV8if8AOSXk
n8wvMH5w61faZ5Z1e/01FtYbW6t7G6midUto+fB0RlIEhYbHFXmP/Kp/zT/6k3XP+4bef9U8Vd/y
qf8ANP8A6k3XP+4bef8AVPFXf8qn/NP/AKk3XP8AuG3n/VPFXf8AKp/zT/6k3XP+4bef9U8Vd/yq
f80/+pN1z/uG3n/VPFXf8qn/ADT/AOpN1z/uG3n/AFTxV3/Kp/zT/wCpN1z/ALht5/1TxV3/ACqf
80/+pN1z/uG3n/VPFXf8qn/NP/qTdc/7ht5/1TxV3/Kp/wA0/wDqTdc/7ht5/wBU8VcPym/NQmn+
Ddc/7ht3/wBU8Veufkj/AM4v+bb/AMx2Wt+c7FtJ0OwkW4FlPQXF08bBljMYPKOOo+MtQkbAb1Cq
cf8AObPk9otU0LzfCh9O6jbTL1x0EkRMsFfd0aQfJcVfMGKsn/LPzrceSfPWkeZYQXWwnBuYl6yW
8gMc6Cu1WjZuNehocVfpNp9/Z6jYW1/ZSrPZ3cST206bq8Uih0YexU1xVXxV2KuxV2KuxV2KuxV2
KuxV2KuxV8Wf85g/mLHrnnO28q2Ewew8uq31sqTxa+mpzU0ND6SBV9mLjFXz9irPfyL8mv5t/NLQ
dLKc7SK4F7f1FVFva/vXDezlRH82xV+i+KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVh35u+Q4/P
X5f6t5eov1uaP1dOkbYJdQ/HCa9gzDix8CcVfnDc21xa3EttcxtDcQO0c0TgqyOh4srA9CCKHFVL
FX1f/wA4i/nLE1uv5da5PxljLSeXp5DsyklpLQk9wavH4iq9lBVfUuKuxV2KuxV2KuxV2KuxV2Ku
xV5v+e35t2f5c+TpbqJ0fzBqAeDRbVqGslPinZf99whgx8TRe+Kvz4urq5u7ma6uZWmubh2lnmkJ
Z3dzyZmJ3JJNScVUsVfY/wDzht+Xb6X5avfOl7HxutcP1fTgwoVs4W+Nv+eso+5Ae+Kvo3FXYq7F
XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXx5/zl1+UUml6z/j7SIP8AcZqbhNZRBtDdnZZjTos/Qn+f
3cYq+bsVVLe4uLa4iubeRobiB1khmjJV0dDVWVhuCCKg4q+2/wDnH7/nI2w86WsHl3zNNHa+b4gE
hlNEiv1A+2nRVm/nj79V2qqqvdcVdirsVdirsVdirsVdirC/zT/Njyv+XOgtqOry+rezBl03S4yP
WuZAOg68EH7chFF9yQCq+AvP3n3zF568y3Gv67N6l1N8EMKVEUEKklIYlNaItfmTUmpJOKscxVnH
5O/llf8A5iedbXRYeUenx0n1a8Uf3NspHKhO3N/sp7mvQHFX6Kadp9lp1hbafYwrb2VnEkFtAn2U
ijUKij2CimKojFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FUFrWjaXrek3ekarbrd6dfRNDdW7
9GRxQ9Nwe4I3B3GKvz9/Ov8AJ3V/y18ytavzudCvCz6RqJGzpX+6kIAUSp+0B16jrirzrFVyO6Or
oxV1IKsDQgjcEEYq+jfyl/5y81fRooNI89xS6vp6USLWIqG9jUCg9ZWoJx0+KofqTzOKvqjyl578
oeb7AX3lvVbfUoaAyLE1JY69BLE3GSM+zqMVT3FXYq7FXYqhtR1PTdMspb7UruGysoBymuriRYok
HizuVUfScVfPf5o/85g+XdKjm07yLENY1LdDqkysllEelUU8XmI/2K96t0xV8meZPM2veZtYn1jX
b2W/1K5NZZ5TU07Kqiioi/sqoAHYYqleKpp5a8t6z5l1y00PRrZrrUb2QRwxKPvZj+yqjdmPQb4q
/QX8nPyo0n8t/KcelWxWfVLnjNq+oAbzT06LXcRx1KoPp6k4qzvFXYq7FXYq7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FUm84eT/L/m/QLnQtetVutPuRup2dHH2ZI26o69iP1Yq+FPzm/IbzN+XF+9xx
fUPLEz0s9WRfs1PwxXAH93J7/Zbt3AVeX4q7FURYajqGnXcd5p91LZ3cRrFc27tFIh8VdCGH0Yq9
T8tf85S/nJoaJE+rR6vbxrxSLUoVmPzMyelOx/1pDirN9P8A+c3fN6IBqHlzT7h9qtbyTQCnfZzP
+vFUTd/85w664b6n5VtYWK/AZrqSUBvE8Y4qj2xViWu/85f/AJv6lGY7OSw0YV/vLO25vTwJumuV
+kKMVeU+Y/OHmrzNci58watd6pMpJjN1K8ipy6iNSeKD2UAYqk+KuxVP/JPkXzP511yLRvL1m13d
vvI/SKFK7yTSdEQeJ+QqdsVfdv5Mfkj5e/LTST6JF95gu0A1HVWWhPf0oQfsRA/Sx3PYBV6RirsV
dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqjeWdpe2k1neQR3NpcIY57eVQ8bowoysrV
BBHY4q+Z/wA1/wDnDy1unn1X8vpltZ2q76Fct+5JPUW8x3T2V6j/AClG2KvmDzL5S8y+WNQbT/MG
m3GmXgrSO4QqGA25Rt9l1/ylJGKpRirsVdirsVdirsVVbW1uru4jtrWF7i5lYLFDEpd3Y9AqqCSf
lir3r8r/APnEbzfr7w3/AJvL+XtING+qkA38q+AQ1WH5yfEP5cVfW/kzyN5W8maOmkeXbCOytFoZ
Cu8kr0pzlkPxO3ufkNsVT7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq
gdZ0LRNcsXsNZsLfUbJ92t7qJJo6+PFwRX3xV4z5s/5w+/K/V2ebR3u/L9w24S3f17ep7mKbk/0L
IoxV5brX/OEvnWBmOja/p9+g6fWkmtHIp2CC5Wv+y+nFWLXP/OJP50wycY9PtLhf9+R3kIXr/wAW
FD+GKqaf84nfnYzqp0m3QEgFjeW1B7mjk4qn2lf84X/mdcsDf6hpdhH+0PVmmkH+xSLh/wAPir0b
yx/zhR5RtHSXzFrl3qpWhNvaolnET/KxJnkI/wBVlOKva/KH5b+RfJ0Pp+W9FttOYrxe4Redw67b
PPIWlYbdC2KskxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV/9k=
+
+
+
+ uuid:C1BCCE1871B8DB11993190FCD52B4E9F
+ xmp.did:4ae39f1f-22e5-af4e-9609-3e681ff7056c
+ uuid:c8651ad7-4276-40ef-b8d9-38284df93300
+ proof:pdf
+
+ uuid:84856ffd-5d3a-44ad-8f9c-9d45d44a028a
+ xmp.did:a633c392-a5e1-6b46-9145-559725e4aa0f
+ uuid:C1BCCE1871B8DB11993190FCD52B4E9F
+ proof:pdf
+
+
+
+
+ saved
+ xmp.iid:4ae39f1f-22e5-af4e-9609-3e681ff7056c
+ 2021-12-05T10:47:33+08:00
+ Adobe Illustrator 24.0 (Windows)
+ /
+
+
+
+ Document
+ Mobile
+ AIRobin
+ 1
+ False
+ False
+
+ 1000.000000
+ 1000.000000
+ Pixels
+
+
+
+ Black
+
+
+
+
+
+ Default Swatch Group
+ 0
+
+
+
+ White
+ RGB
+ PROCESS
+ 255
+ 255
+ 255
+
+
+ Black
+ RGB
+ PROCESS
+ 0
+ 0
+ 0
+
+
+ RGB Red
+ RGB
+ PROCESS
+ 255
+ 0
+ 0
+
+
+ RGB Yellow
+ RGB
+ PROCESS
+ 255
+ 255
+ 0
+
+
+ RGB Green
+ RGB
+ PROCESS
+ 0
+ 255
+ 0
+
+
+ RGB Cyan
+ RGB
+ PROCESS
+ 0
+ 255
+ 255
+
+
+ RGB Blue
+ RGB
+ PROCESS
+ 0
+ 0
+ 255
+
+
+ RGB Magenta
+ RGB
+ PROCESS
+ 255
+ 0
+ 255
+
+
+ R=193 G=39 B=45
+ RGB
+ PROCESS
+ 193
+ 39
+ 45
+
+
+ R=237 G=28 B=36
+ RGB
+ PROCESS
+ 237
+ 28
+ 36
+
+
+ R=241 G=90 B=36
+ RGB
+ PROCESS
+ 241
+ 90
+ 36
+
+
+ R=247 G=147 B=30
+ RGB
+ PROCESS
+ 247
+ 147
+ 30
+
+
+ R=251 G=176 B=59
+ RGB
+ PROCESS
+ 251
+ 176
+ 59
+
+
+ R=252 G=238 B=33
+ RGB
+ PROCESS
+ 252
+ 238
+ 33
+
+
+ R=217 G=224 B=33
+ RGB
+ PROCESS
+ 217
+ 224
+ 33
+
+
+ R=140 G=198 B=63
+ RGB
+ PROCESS
+ 140
+ 198
+ 63
+
+
+ R=57 G=181 B=74
+ RGB
+ PROCESS
+ 57
+ 181
+ 74
+
+
+ R=0 G=146 B=69
+ RGB
+ PROCESS
+ 0
+ 146
+ 69
+
+
+ R=0 G=104 B=55
+ RGB
+ PROCESS
+ 0
+ 104
+ 55
+
+
+ R=34 G=181 B=115
+ RGB
+ PROCESS
+ 34
+ 181
+ 115
+
+
+ R=0 G=169 B=157
+ RGB
+ PROCESS
+ 0
+ 169
+ 157
+
+
+ R=41 G=171 B=226
+ RGB
+ PROCESS
+ 41
+ 171
+ 226
+
+
+ R=0 G=113 B=188
+ RGB
+ PROCESS
+ 0
+ 113
+ 188
+
+
+ R=46 G=49 B=146
+ RGB
+ PROCESS
+ 46
+ 49
+ 146
+
+
+ R=27 G=20 B=100
+ RGB
+ PROCESS
+ 27
+ 20
+ 100
+
+
+ R=102 G=45 B=145
+ RGB
+ PROCESS
+ 102
+ 45
+ 145
+
+
+ R=147 G=39 B=143
+ RGB
+ PROCESS
+ 147
+ 39
+ 143
+
+
+ R=158 G=0 B=93
+ RGB
+ PROCESS
+ 158
+ 0
+ 93
+
+
+ R=212 G=20 B=90
+ RGB
+ PROCESS
+ 212
+ 20
+ 90
+
+
+ R=237 G=30 B=121
+ RGB
+ PROCESS
+ 237
+ 30
+ 121
+
+
+ R=199 G=178 B=153
+ RGB
+ PROCESS
+ 199
+ 178
+ 153
+
+
+ R=153 G=134 B=117
+ RGB
+ PROCESS
+ 153
+ 134
+ 117
+
+
+ R=115 G=99 B=87
+ RGB
+ PROCESS
+ 115
+ 99
+ 87
+
+
+ R=83 G=71 B=65
+ RGB
+ PROCESS
+ 83
+ 71
+ 65
+
+
+ R=198 G=156 B=109
+ RGB
+ PROCESS
+ 198
+ 156
+ 109
+
+
+ R=166 G=124 B=82
+ RGB
+ PROCESS
+ 166
+ 124
+ 82
+
+
+ R=140 G=98 B=57
+ RGB
+ PROCESS
+ 140
+ 98
+ 57
+
+
+ R=117 G=76 B=36
+ RGB
+ PROCESS
+ 117
+ 76
+ 36
+
+
+ R=96 G=56 B=19
+ RGB
+ PROCESS
+ 96
+ 56
+ 19
+
+
+ R=66 G=33 B=11
+ RGB
+ PROCESS
+ 66
+ 33
+ 11
+
+
+
+
+
+ Grays
+ 1
+
+
+
+ R=0 G=0 B=0
+ RGB
+ PROCESS
+ 0
+ 0
+ 0
+
+
+ R=26 G=26 B=26
+ RGB
+ PROCESS
+ 26
+ 26
+ 26
+
+
+ R=51 G=51 B=51
+ RGB
+ PROCESS
+ 51
+ 51
+ 51
+
+
+ R=77 G=77 B=77
+ RGB
+ PROCESS
+ 77
+ 77
+ 77
+
+
+ R=102 G=102 B=102
+ RGB
+ PROCESS
+ 102
+ 102
+ 102
+
+
+ R=128 G=128 B=128
+ RGB
+ PROCESS
+ 128
+ 128
+ 128
+
+
+ R=153 G=153 B=153
+ RGB
+ PROCESS
+ 153
+ 153
+ 153
+
+
+ R=179 G=179 B=179
+ RGB
+ PROCESS
+ 179
+ 179
+ 179
+
+
+ R=204 G=204 B=204
+ RGB
+ PROCESS
+ 204
+ 204
+ 204
+
+
+ R=230 G=230 B=230
+ RGB
+ PROCESS
+ 230
+ 230
+ 230
+
+
+ R=242 G=242 B=242
+ RGB
+ PROCESS
+ 242
+ 242
+ 242
+
+
+
+
+
+ Mobile Color Group
+ 1
+
+
+
+ R=136 G=168 B=13
+ RGB
+ PROCESS
+ 136
+ 168
+ 13
+
+
+ R=127 G=71 B=221
+ RGB
+ PROCESS
+ 127
+ 71
+ 221
+
+
+ R=251 G=174 B=23
+ RGB
+ PROCESS
+ 251
+ 174
+ 23
+
+
+
+
+
+
+ Adobe PDF library 15.00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
endobj
3 0 obj
<>
endobj
5 0 obj
<>/Resources<>/Properties<>>>/Thumb 25 0 R/TrimBox[0.0 0.0 1000.0 1000.0]/Type/Page>>
endobj
23 0 obj
<>stream
+HMn]7wERӺEGAdm2H?>ױw-J;<$>>%c:%Y)s[xsI_9'K?K5E~sY
WtNYlUۂ8}μڒUG:cxb#cIC9d/Wce~?#{\Z:PO)\([DQ5'ߧ +e-Ms[7YVT.eMҼ'˥W)IDe1rp`3rnElJge'J T
+b6|ҫL?O?o*\r[/mK^ )nzOЇo+${kApq1-ېz5F"