Compare commits
336 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f67b4db4ba | |||
| 7bac32e3c4 | |||
| 880ca08571 | |||
| 85d4d8a71e | |||
| abb8ed0bcc | |||
| bea0d10a6c | |||
| 80d943af23 | |||
| 90b85e469d | |||
| 0d419c1323 | |||
| f7a2ecc2e0 | |||
| 5fdbf83f32 | |||
| c513ad9291 | |||
| a2dfa55dbd | |||
| 78f8d9a271 | |||
| b25a5aac8c | |||
| 25cc70035e | |||
| e5d70d5a0e | |||
| 066b0d1f8a | |||
| 71b2e56187 | |||
| 457832fbbe | |||
| 00554e066b | |||
| 9f9775e585 | |||
| 9cf70ae74e | |||
| 4f046987c6 | |||
| 699666c23b | |||
| 6a8cdd0155 | |||
| ce61f0e2b7 | |||
| b3cb0bf93f | |||
| 07328eea2d | |||
| 39d54cc493 | |||
| d31f40408b | |||
| 7f88d9ae27 | |||
| 1c1dd81474 | |||
| 53a498c581 | |||
| bfb6346812 | |||
| bd2fa1e427 | |||
| 6c4bfeff29 | |||
| 299a77eea8 | |||
| 351a00fb1e | |||
| 2140e1ebe1 | |||
| 497a820ba2 | |||
| 7182f3554a | |||
| 506ba52502 | |||
| 90c1630af4 | |||
| 5934abd448 | |||
| 86f432ef01 | |||
| 4913019c5c | |||
| a6316797e6 | |||
| 00d7549bde | |||
| 8fc33f5649 | |||
| 729b544675 | |||
| 32e8324275 | |||
| 842f6dd726 | |||
| 59f7d11df3 | |||
| dcd2f52c59 | |||
| b45413c232 | |||
| b4481ff680 | |||
| d7d7a3919f | |||
| f8e4732dcd | |||
| 1b92ed66b7 | |||
| 9ba74b9504 | |||
| 8cd49f12d1 | |||
| c48ca9ee89 | |||
| 43bcf71bf5 | |||
| ee48813df1 | |||
| f4a67e2822 | |||
| f03733da04 | |||
| f38313ff2c | |||
| b5d9e21f37 | |||
| 5d42a8957e | |||
| b276c60909 | |||
| d03564bce9 | |||
| 41409c39d5 | |||
| aa9c5107d0 | |||
| 7a141822e7 | |||
| a4fd301d5a | |||
| b2ef8b96ef | |||
| baa9e1003e | |||
| 36b97b2adc | |||
| f13bffa834 | |||
| 4394566ed3 | |||
| de95c24f66 | |||
| 6b20d3e268 | |||
| ce037a437a | |||
| 1349dab6d4 | |||
| d3d31925ee | |||
| d9fa77c86b | |||
| dad01235b0 | |||
| 52d9c26076 | |||
| 1a0236237d | |||
| 58bb7a5ebc | |||
| efbab58bca | |||
| eedbc7a863 | |||
| 626cda63ff | |||
| 7b7a9d93aa | |||
| f5c68dac61 | |||
| 2b6b106771 | |||
| 047586883e | |||
| 0c1a25dd6b | |||
| 7840a9a713 | |||
| 28f96ffcd3 | |||
| 04b2663183 | |||
| 1a11027871 | |||
| 854a00803e | |||
| 11ae5f157f | |||
| ecfe05139e | |||
| 4a392e03a7 | |||
| a66037f886 | |||
| 58c399dcbe | |||
| f33e617f44 | |||
| 3e976c1026 | |||
| c15c75075c | |||
| bf8d988c75 | |||
| 6fb7af3d46 | |||
| 1c2860c180 | |||
| fc41f10c37 | |||
| dedf366866 | |||
| edb10096d6 | |||
| ba42a1e6c9 | |||
| a0058c104d | |||
| 7f1f322d04 | |||
| 57ac8d8771 | |||
| bcd0509eff | |||
| 624af87795 | |||
| 616df56657 | |||
| 4efd6abb56 | |||
| 8c657a4ccf | |||
| db582f6c88 | |||
| a7b861f83c | |||
| 19b1c7ae8b | |||
| 192cec68c7 | |||
| 4afa66f3f3 | |||
| 7fde157184 | |||
| a1935e8299 | |||
| 50e993fd89 | |||
| a25ec6b0af | |||
| efeb99aaac | |||
| f19118432d | |||
| b69eac2886 | |||
| 4efc4e7f34 | |||
| 4755eb06e2 | |||
| e4dc1c0b4e | |||
| 89f54c2b4a | |||
| abf52f0d49 | |||
| 044df3f09c | |||
| 271829f9c1 | |||
| 13625b37a8 | |||
| 781191196f | |||
| eb0cf27218 | |||
| 1706341283 | |||
| 71f46b3bff | |||
| 4c39798682 | |||
| b861aa385d | |||
| 156e8a2686 | |||
| f88acf1375 | |||
| be770d4607 | |||
| 7565f624c9 | |||
| 65d56297fd | |||
| 86caac4a1d | |||
| d382ac4fa2 | |||
| f9ceeaad44 | |||
| 0691293973 | |||
| 9491b48eb6 | |||
| 6c7f63270f | |||
| a62f793288 | |||
| 901b54b829 | |||
| 0efa1127a3 | |||
| 28fc53799a | |||
| bdc4af7cd4 | |||
| c68996ff20 | |||
| f517a63cda | |||
| fefb9b490e | |||
| 383e1d5368 | |||
| 4e4ce36e76 | |||
| 19983a113e | |||
| 8eaac465ff | |||
| 17b2d744ba | |||
| 166e0d400a | |||
| 5cf409ce0b | |||
| e37e847a8b | |||
| 32c77d3743 | |||
| 45e368d9e7 | |||
| 97496302fb | |||
| 675959e615 | |||
| f641b282b6 | |||
| e92a05683c | |||
| 93bef2e144 | |||
| 44e331ae96 | |||
| f295c85668 | |||
| 6f843bface | |||
| 2dea6076f0 | |||
| 78c6c7b571 | |||
| a50bec9326 | |||
| 7d193d7de6 | |||
| 5bbb3e6a6c | |||
| 15198c32ea | |||
| 476503338f | |||
| ba6303dca0 | |||
| 23432465ac | |||
| 1f0b5cebeb | |||
| 1f83c84a7e | |||
| e209af9c57 | |||
| a714d312a8 | |||
| 4a776c1fe8 | |||
| da86f07cbe | |||
| 48e0ca887d | |||
| 0f3b6c4cec | |||
| 9ce9631135 | |||
| c73a5c3a7e | |||
| 62d35127b1 | |||
| 09f17caabe | |||
| c5355d7497 | |||
| d5142ad82c | |||
| 428b278c78 | |||
| 33c1e04934 | |||
| 6c075d80ba | |||
| 38713108e0 | |||
| 6b75fea813 | |||
| de6fc84fec | |||
| ecd276a3a0 | |||
| 86fbd0cebc | |||
| 6a97919f7a | |||
| f2e7e17bd1 | |||
| eedd6cee1d | |||
| 25e11fa9de | |||
| 4742600b86 | |||
| b3e4850413 | |||
| fd8d13447c | |||
| 758a3d3f99 | |||
| fd8b4d94d6 | |||
| fa7dae8177 | |||
| 21638218c6 | |||
| a29a414e8a | |||
| 251c7f399e | |||
| 1da55f2011 | |||
| 856125edc2 | |||
| 32ef30ebd8 | |||
| 8972e42fee | |||
| 91f206aad0 | |||
| 5626babcdf | |||
| 98175152db | |||
| 817ade3e34 | |||
| ab5493f8c4 | |||
| 796bd99377 | |||
| a0dc60a403 | |||
| a92e58abf1 | |||
| e8f0793feb | |||
| 2d7eff8205 | |||
| 6412892985 | |||
| 69ae0ffc71 | |||
| 854be23cfb | |||
| 02e143217e | |||
| 4feec82b03 | |||
| 938ca648f1 | |||
| ee018ea287 | |||
| 8ab60ad000 | |||
| 17eaf34500 | |||
| 2485958f6e | |||
| 7ac3a22fa6 | |||
| 285f211f50 | |||
| 1e96477127 | |||
| 87ffa48265 | |||
| 8b64df435c | |||
| dcf88ee510 | |||
| b21a15376d | |||
| 3e87ed4f9b | |||
| a6cd9c955b | |||
| 86b52b76ed | |||
| 853f380e5d | |||
| 027686a3b5 | |||
| 79b87e59be | |||
| 3a37e55162 | |||
| 1ff40c0016 | |||
| 4f7c1021c8 | |||
| e687c78ba8 | |||
| 2c2f46a0d8 | |||
| 29fa565258 | |||
| 51f3d410c9 | |||
| a0d159da9d | |||
| 9edb58ee27 | |||
| ef8a894489 | |||
| 992f388a56 | |||
| a54e7206a0 | |||
| c4e74b21fc | |||
| 7b9e07bdda | |||
| 19f5204253 | |||
| c4ad5c5f81 | |||
| e888118a20 | |||
| 7afce136f6 | |||
| 71c4dadeee | |||
| a6d44685b3 | |||
| a8ce61dad9 | |||
| 0f47d1473d | |||
| 2134ee516a | |||
| 6c60306bee | |||
| 816748833c | |||
| cac0fca3bb | |||
| 5ed28b121e | |||
| c4180eba6f | |||
| 0065a1f81f | |||
| ed7ffbcb13 | |||
| 6a8d9db407 | |||
| 81140837f1 | |||
| 70232645a8 | |||
| 4d3b3ef3df | |||
| d203314424 | |||
| a8c5ccda17 | |||
| 86b996637c | |||
| 1480d4a14e | |||
| b8013afd64 | |||
| 812bc83939 | |||
| d6829744bb | |||
| a7a03544b6 | |||
| ffa8729d10 | |||
| ce291d3a77 | |||
| 297dbad60c | |||
| 54982218f5 | |||
| c14f4df494 | |||
| f53f23aa4b | |||
| 10c59fb4b4 | |||
| a5cffc5ea4 | |||
| 200c299ce7 | |||
| 8547276549 | |||
| b09afcf725 | |||
| a2860be7a3 | |||
| de9d026e3a | |||
| 27a1baae7b | |||
| f2584309d1 | |||
| 831fd09615 | |||
| e0e22a09c0 | |||
| 60c6e0632d | |||
| 6da13c4fc0 | |||
| ec330aea69 | |||
| 318682b63a | |||
| dd53d7ff0a | |||
| b03207d287 |
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"projectName": "community",
|
||||
"projectOwner": "InkCanvasForClass",
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"commitType": "docs",
|
||||
"commitConvention": "angular",
|
||||
"contributorsPerLine": 7,
|
||||
"contributors": [
|
||||
{
|
||||
"login": "CJKmkp",
|
||||
"name": "CJK_mkp",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/113243675?v=4",
|
||||
"profile": "https://github.com/CJKmkp",
|
||||
"contributions": [
|
||||
"maintenance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Hydro11451",
|
||||
"name": "Hydrogen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/214308559?v=4",
|
||||
"profile": "https://github.com/Hydro11451",
|
||||
"contributions": [
|
||||
"maintenance",
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6,7 +6,6 @@ labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
## Version(or version link)
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
name: .NET Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main,beta ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
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/"
|
||||
@@ -1,3 +1,16 @@
|
||||
obj/
|
||||
bin/
|
||||
.vs
|
||||
InkCanvasForClass/obj
|
||||
InkCanvasForClass/bin
|
||||
InkCanvasForClassX/obj
|
||||
InkCanvasForClassX/bin
|
||||
InkCanvasForClass.IACoreHelper/obj
|
||||
InkCanvasForClass.IACoreHelper/bin
|
||||
InkCanvasForClass.PowerPoint.InteropHelper/obj
|
||||
InkCanvasForClass.PowerPoint.InteropHelper/bin
|
||||
InkCanvasForClass.PowerPoint.VstoPlugin/obj
|
||||
InkCanvasForClass.PowerPoint.VstoPlugin/bin
|
||||
InkCanvasForClass.IccInkCanvas/obj
|
||||
InkCanvasForClass.IccInkCanvas/bin
|
||||
InkCanvasForClass.IccInkCanvas.Demo/obj
|
||||
InkCanvasForClass.IccInkCanvas.Demo/bin
|
||||
.vs
|
||||
.idea
|
||||
@@ -1,12 +1,12 @@
|
||||
# Default ignored files
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
# Rider 忽略的文件
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/.idea.Ink Canvas.iml
|
||||
# Editor-based HTTP Client requests
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders>
|
||||
<Path>../../ICC CE main</Path>
|
||||
</attachedFolders>
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,398 +0,0 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\dubi906w\\source\\repos\\icc-ce\\ink canvas\\mainwindow_cs\\mw_floatingbaricons.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_floatingbaricons.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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:\\Users\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\dubi906w\\source\\repos\\icc-ce\\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}"
|
||||
},
|
||||
{
|
||||
"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": 210,
|
||||
"SelectedChildIndex": 48,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{e506b91c-c606-466a-90a9-123d1d1e12b3}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{387cb18d-6153-4156-9257-9ac3f9207bbe}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{e8b06f52-6d01-11d2-aa7d-00c04f990343}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{46c87f81-5a06-43a8-9e25-85d33bac49f8}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{269a02dc-6af8-11d3-bdc4-00c04f688e50}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{99b8fa2f-ab90-4f57-9c32-949f146f1914}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{c79b74ff-f1d7-4c94-aefa-4d22bfe1b1f9}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{13b12e3e-c1b4-4539-9371-4fe9a0d523fc}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:2:0:{34c7837f-3b3a-449c-bdf0-bdad86cbaf4a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{37aba9be-445a-11d3-9949-00c04f68fd0a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{dcc4ea97-1c0c-482b-b205-e541c0df9728}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{75188d03-9892-4ae2-abf1-207126247ce5}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{eefa5220-e298-11d0-8f78-00a0c9110057}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{4a9b7e51-aa16-11d0-a8c5-00a0c921a4d2}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:133:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:3:0:{34c7837f-3b3a-449c-bdf0-bdad86cbaf4a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:153:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:154:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:152:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:151:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:150:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:148:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:149:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:136:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:144:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:147:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:145:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:146:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:143:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:142:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:141:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:140:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:139:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:138:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:137:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:135:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:134:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{13b12e3e-c1b4-4539-9371-4fe9a0d523fc}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{75188d03-9892-4ae2-abf1-207126247ce5}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{cce594b6-0c39-4442-ba28-10c64ac7e89f}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{b1e99781-ab81-11d0-b683-00aa00a3ee26}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "MW_FloatingBarIcons.cs",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"RelativeToolTip": "Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"ViewState": "AgIAAOgCAAAAAAAAAAAuwEoGAAAIAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-05-31T10:49:24.719Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "README.md",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\README.md",
|
||||
"RelativeDocumentMoniker": "README.md",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\README.md",
|
||||
"RelativeToolTip": "README.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-31T10:48:22.883Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 7,
|
||||
"Title": "MainWindow.xaml",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow.xaml",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow.xaml",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow.xaml",
|
||||
"RelativeToolTip": "Ink Canvas\\MainWindow.xaml",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
|
||||
"WhenOpened": "2025-05-24T13:22:56.715Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 9,
|
||||
"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": 6,
|
||||
"Title": "MW_PPT.cs",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"Title": "README.md",
|
||||
"DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"RelativeDocumentMoniker": "..\\..\\..\\..\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"RelativeToolTip": "..\\..\\..\\..\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-24T13:04:01.407Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "privacy.txt",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\privacy.txt",
|
||||
"RelativeDocumentMoniker": "privacy.txt",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\privacy.txt",
|
||||
"RelativeToolTip": "privacy.txt",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
|
||||
"WhenOpened": "2025-05-24T13:04:01.337Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "Manual.md",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Manual.md",
|
||||
"RelativeDocumentMoniker": "Manual.md",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Manual.md",
|
||||
"RelativeToolTip": "Manual.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-24T13:04:00.986Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "LICENSE",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\LICENSE",
|
||||
"RelativeDocumentMoniker": "LICENSE",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\LICENSE",
|
||||
"RelativeToolTip": "LICENSE",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
||||
"WhenOpened": "2025-05-24T13:04:00.902Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "Ink Canvas.sln.DotSettings.user",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas.sln.DotSettings.user",
|
||||
"RelativeDocumentMoniker": "Ink Canvas.sln.DotSettings.user",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{d84ee353-0bef-5a41-a649-8f89aca5d84d}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockedWidth": 204,
|
||||
"SelectedChildIndex": -1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:1:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{590a070c-4fcd-52d9-87da-dfaa11710261}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockedWidth": 190,
|
||||
"SelectedChildIndex": -1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{f4fc5ff1-28ef-4b04-ad02-6b298310ccc7}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,398 +0,0 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\dubi906w\\source\\repos\\icc-ce\\ink canvas\\mainwindow_cs\\mw_floatingbaricons.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_floatingbaricons.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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:\\Users\\dubi906w\\source\\repos\\icc-ce\\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\\dubi906w\\source\\repos\\icc-ce\\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:{8D0EDFC7-F974-4571-BC49-6F3A6653FE81}|Ink Canvas\\InkCanvasForClass.csproj|c:\\users\\dubi906w\\source\\repos\\icc-ce\\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}"
|
||||
},
|
||||
{
|
||||
"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": 210,
|
||||
"SelectedChildIndex": 48,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{e506b91c-c606-466a-90a9-123d1d1e12b3}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{387cb18d-6153-4156-9257-9ac3f9207bbe}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{e8b06f52-6d01-11d2-aa7d-00c04f990343}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{46c87f81-5a06-43a8-9e25-85d33bac49f8}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{269a02dc-6af8-11d3-bdc4-00c04f688e50}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{99b8fa2f-ab90-4f57-9c32-949f146f1914}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{c79b74ff-f1d7-4c94-aefa-4d22bfe1b1f9}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{13b12e3e-c1b4-4539-9371-4fe9a0d523fc}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:2:0:{34c7837f-3b3a-449c-bdf0-bdad86cbaf4a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{37aba9be-445a-11d3-9949-00c04f68fd0a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{dcc4ea97-1c0c-482b-b205-e541c0df9728}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{75188d03-9892-4ae2-abf1-207126247ce5}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{eefa5220-e298-11d0-8f78-00a0c9110057}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{4a9b7e51-aa16-11d0-a8c5-00a0c921a4d2}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:133:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:3:0:{34c7837f-3b3a-449c-bdf0-bdad86cbaf4a}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:153:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:154:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:152:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:151:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:150:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:148:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:149:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:136:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:144:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:147:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:145:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:146:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:143:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:142:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:141:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:140:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:139:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:138:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:137:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:135:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:134:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{13b12e3e-c1b4-4539-9371-4fe9a0d523fc}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:129:0:{75188d03-9892-4ae2-abf1-207126247ce5}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{cce594b6-0c39-4442-ba28-10c64ac7e89f}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{b1e99781-ab81-11d0-b683-00aa00a3ee26}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "MW_FloatingBarIcons.cs",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"RelativeToolTip": "Ink Canvas\\MainWindow_cs\\MW_FloatingBarIcons.cs",
|
||||
"ViewState": "AgIAAOgCAAAAAAAAAAAuwEoGAAAIAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-05-31T10:49:24.719Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "README.md",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\README.md",
|
||||
"RelativeDocumentMoniker": "README.md",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\README.md",
|
||||
"RelativeToolTip": "README.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-31T10:48:22.883Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 7,
|
||||
"Title": "MainWindow.xaml",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow.xaml",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow.xaml",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow.xaml",
|
||||
"RelativeToolTip": "Ink Canvas\\MainWindow.xaml",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
|
||||
"WhenOpened": "2025-05-24T13:22:56.715Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 9,
|
||||
"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": 6,
|
||||
"Title": "MW_PPT.cs",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
|
||||
"RelativeDocumentMoniker": "Ink Canvas\\MainWindow_cs\\MW_PPT.cs",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"Title": "README.md",
|
||||
"DocumentMoniker": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"RelativeDocumentMoniker": "..\\..\\..\\..\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"ToolTip": "C:\\Users\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"RelativeToolTip": "..\\..\\..\\..\\Administrator\\Desktop\\ICC CE\\icc-0610.2.3\\README.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-24T13:04:01.407Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "privacy.txt",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\privacy.txt",
|
||||
"RelativeDocumentMoniker": "privacy.txt",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\privacy.txt",
|
||||
"RelativeToolTip": "privacy.txt",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003109|",
|
||||
"WhenOpened": "2025-05-24T13:04:01.337Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "Manual.md",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Manual.md",
|
||||
"RelativeDocumentMoniker": "Manual.md",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Manual.md",
|
||||
"RelativeToolTip": "Manual.md",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
|
||||
"WhenOpened": "2025-05-24T13:04:00.986Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "LICENSE",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\LICENSE",
|
||||
"RelativeDocumentMoniker": "LICENSE",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\LICENSE",
|
||||
"RelativeToolTip": "LICENSE",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
||||
"WhenOpened": "2025-05-24T13:04:00.902Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "Ink Canvas.sln.DotSettings.user",
|
||||
"DocumentMoniker": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\Ink Canvas.sln.DotSettings.user",
|
||||
"RelativeDocumentMoniker": "Ink Canvas.sln.DotSettings.user",
|
||||
"ToolTip": "C:\\Users\\dubi906w\\source\\repos\\icc-ce\\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"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{d84ee353-0bef-5a41-a649-8f89aca5d84d}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockedWidth": 204,
|
||||
"SelectedChildIndex": -1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:1:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{590a070c-4fcd-52d9-87da-dfaa11710261}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockedWidth": 190,
|
||||
"SelectedChildIndex": -1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{f4fc5ff1-28ef-4b04-ad02-6b298310ccc7}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
""
|
||||
],
|
||||
"SelectedNode": "\\Ink Canvas.sln",
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,338 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
1.7.0.0
|
||||
@@ -0,0 +1,36 @@
|
||||
rev-1.0.0.0:
|
||||
1. 重写大部分代码中...
|
||||
|
||||
5.0.5.0:
|
||||
1. 支持自动收纳希沃轻白板5C,希沃白板3,鸿合轻量白板。
|
||||
2. 支持自动查杀鸿合屏幕书写。
|
||||
3. 带来FitToCurve,给平滑墨迹加上了开关。
|
||||
4. 修复了FitToCurve导致的部分形状绘制出错的问题也保留了其他墨迹的FitToCurve。
|
||||
5. 白板,浮动工具栏,子面板,设置UI几乎全部优化。
|
||||
6. 添加修改橡皮大小,橡皮形状的菜单。
|
||||
7. PPT现在会自动提示是否关闭自动播放和排练计时。
|
||||
8. 条件性的墨迹识别,可以关闭部分不需要的形状识别。可以修改是否为墨迹识别的三角形或矩形应用模拟压感值。
|
||||
9. 带来了荧光笔功能并为荧光笔适配了形状识别。
|
||||
10. 允许清空墨迹时可删除历史记录。
|
||||
11. 带来了Quick Panel。
|
||||
12. 浮动工具栏缩放调节,取消收纳按钮图标修改。
|
||||
13. 修复了多指书写StylusDown事件可能触发在工具栏而不是inkCanvas上导致的Bug。
|
||||
14. 修复了鼠标和触摸屏(无RealTimeStylus和非多指书写模式)的绘制时Pointer捕获Bug。
|
||||
15. Merge了Ink Canvas的新撤回行为
|
||||
16. 修复了白板模式下直接新增页面导致的TimeMachine不记录历史记录的Bug
|
||||
17. 添加了一个简陋的白板页面列表。
|
||||
18. 优化了墨迹重播,支持暂停,重新开始和倍速,拥有更人性化的UI。
|
||||
19. 优化自动收纳行为和FoldFloatingBar函数的相关Bug修复。
|
||||
20. 添加了EdgeGestureUtil实验性选项。
|
||||
21. 添加了ForceFullScreen实验性选项
|
||||
22. 添加了FullScreenHelper实验性选项。
|
||||
23. 添加了ResolutionChangeDetection和DPIChangeDetection实验性选项。
|
||||
24. 修复了同时打开ICC和ICA的冲突。
|
||||
25. 修复浮动工具栏手势按钮开启多指书写时InkCanvas的InkCanvasEditingMode被修改为None的Bug。
|
||||
26. 修复Merge ICA仓库代码后导致浮动工具栏批注按钮UI MouseLeave反馈的问题。
|
||||
27. 为大部分UI的按钮添加了lastBorderMouseDown的检测代码和MouseDown的视觉反馈。
|
||||
28. 支持自动收纳安道系列,艺云系列和 MAXHUB 白板书写。
|
||||
|
||||
4.5.8.0:
|
||||
1. 将ICA的代码换了个名字变成了InkCanvasForClass,万物起源。
|
||||
2. 优化了ICA的部分UI界面设计。
|
||||
@@ -1,128 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
QQ:2564608840.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
Before Width: | Height: | Size: 568 KiB |
@@ -3,7 +3,19 @@ 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}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InkCanvasForClassX", "InkCanvasForClassX\InkCanvasForClassX.csproj", "{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InkCanvasForClass", "InkCanvasForClass\InkCanvasForClass.csproj", "{2474F5B0-6FA7-4D70-8A00-167BBB03264D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClass.IACoreHelper", "InkCanvasForClass.IACoreHelper\InkCanvasForClass.IACoreHelper.csproj", "{693973B6-69C1-4A37-B329-F366A07BF60A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClass.PowerPoint.InteropHelper", "InkCanvasForClass.PowerPoint.InteropHelper\InkCanvasForClass.PowerPoint.InteropHelper.csproj", "{2D8A9217-465A-4F57-BD58-CE02450390C4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClass.PowerPoint.VstoPlugin", "InkCanvasForClass.PowerPoint.VstoPlugin\InkCanvasForClass.PowerPoint.VstoPlugin.csproj", "{8C593467-E54D-4FA7-881C-78F3CC48A867}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClass.IccInkCanvas", "InkCanvasForClass.IccInkCanvas\InkCanvasForClass.IccInkCanvas.csproj", "{43929D8F-5630-4786-B75D-E203EA3E992F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkCanvasForClass.IccInkCanvas.Demo", "InkCanvasForClass.IccInkCanvas.Demo\InkCanvasForClass.IccInkCanvas.Demo.csproj", "{94E97F70-CACD-453B-8114-08DFFDDA5A46}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -17,28 +29,223 @@ Global
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
x86 Debug|Any CPU = x86 Debug|Any CPU
|
||||
x86 Debug|ARM = x86 Debug|ARM
|
||||
x86 Debug|ARM64 = x86 Debug|ARM64
|
||||
x86 Debug|x64 = x86 Debug|x64
|
||||
x86 Debug|x86 = x86 Debug|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
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|x64.Build.0 = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.Release|x86.Build.0 = Release|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{98DF6AA1-DD4D-4C70-A0A2-4B2974D97D51}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|Any CPU.ActiveCfg = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|Any CPU.Build.0 = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|ARM.ActiveCfg = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|ARM.Build.0 = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|ARM64.ActiveCfg = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|ARM64.Build.0 = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|x64.ActiveCfg = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|x64.Build.0 = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|x86.ActiveCfg = x86 Debug|Any CPU
|
||||
{2474F5B0-6FA7-4D70-8A00-167BBB03264D}.x86 Debug|x86.Build.0 = x86 Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{693973B6-69C1-4A37-B329-F366A07BF60A}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2D8A9217-465A-4F57-BD58-CE02450390C4}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8C593467-E54D-4FA7-881C-78F3CC48A867}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{43929D8F-5630-4786-B75D-E203EA3E992F}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|x64.Build.0 = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.Release|x86.Build.0 = Release|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|x64.Build.0 = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94E97F70-CACD-453B-8114-08DFFDDA5A46}.x86 Debug|x86.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/PencilsConfiguration/ActualSeverity/@EntryValue">WARNING</s:String></wpf:ResourceDictionary>
|
||||
<s:String x:Key="/Default/CodeInspection/PencilsConfiguration/ActualSeverity/@EntryValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue"><AssemblyExplorer>
|
||||
<Assembly Path="D:\vs\ica\InkCanvasForClass\IAWinFX.dll" />
|
||||
</AssemblyExplorer></s:String></wpf:ResourceDictionary>
|
||||
@@ -1,803 +0,0 @@
|
||||
using Hardcodet.Wpf.TaskbarNotification;
|
||||
using Ink_Canvas.Helpers;
|
||||
using iNKORE.UI.WPF.Modern.Controls;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Microsoft.Win32;
|
||||
using System.Security; // 添加SecurityException所需命名空间
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using Window = System.Windows.Window;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
System.Threading.Mutex mutex;
|
||||
|
||||
public static string[] StartArgs = null;
|
||||
public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\";
|
||||
|
||||
// 新增:保存看门狗进程对象
|
||||
private static Process watchdogProcess = null;
|
||||
// 新增:标记是否为软件内主动退出
|
||||
public static bool IsAppExitByUser = false;
|
||||
// 新增:退出信号文件路径
|
||||
private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + System.Diagnostics.Process.GetCurrentProcess().Id + ".flag");
|
||||
|
||||
public App()
|
||||
{
|
||||
this.Startup += new StartupEventHandler(App_Startup);
|
||||
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
|
||||
StartHeartbeatMonitor();
|
||||
StartWatchdogIfNeeded();
|
||||
this.Exit += App_Exit; // 注册退出事件
|
||||
}
|
||||
|
||||
// 增加字段保存崩溃后操作设置
|
||||
public static CrashActionType CrashAction = CrashActionType.SilentRestart;
|
||||
|
||||
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;
|
||||
|
||||
// 修改:仅当非用户主动退出时才触发自动重启
|
||||
if (CrashAction == CrashActionType.SilentRestart && !IsAppExitByUser)
|
||||
{
|
||||
StartupCount.Increment();
|
||||
if (StartupCount.GetCount() >= 5)
|
||||
{
|
||||
MessageBox.Show("检测到程序已连续重启5次,已停止自动重启。请联系开发者或检查系统环境。", "重启次数过多", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
StartupCount.Reset();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
try
|
||||
{
|
||||
string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
||||
System.Diagnostics.Process.Start(exePath);
|
||||
}
|
||||
catch { }
|
||||
Environment.Exit(1);
|
||||
}
|
||||
// CrashActionType.NoAction 时不做处理
|
||||
}
|
||||
|
||||
private TaskbarIcon _taskbar;
|
||||
|
||||
void App_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
RunWatchdogIfNeeded();
|
||||
/*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;
|
||||
|
||||
// 新增:Office注册表检测
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("开始Office注册表检测");
|
||||
|
||||
// 检查Office安装
|
||||
if (!IsOfficeInstalled())
|
||||
{
|
||||
LogHelper.WriteLogToFile("未检测到Office安装", LogHelper.LogType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试获取所有可能的Office版本路径
|
||||
var officeVersions = GetOfficeVersions();
|
||||
if (officeVersions.Count == 0)
|
||||
{
|
||||
LogHelper.WriteLogToFile("未找到任何Office版本", LogHelper.LogType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var version in officeVersions)
|
||||
{
|
||||
string regPath = $"Software\\Microsoft\\Office\\{version}\\Common\\Security";
|
||||
LogHelper.WriteLogToFile($"正在处理Office版本 {version}, 注册表路径: {regPath}");
|
||||
|
||||
try
|
||||
{
|
||||
using (Microsoft.Win32.RegistryKey baseKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(regPath))
|
||||
{
|
||||
if (baseKey == null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"注册表路径不存在: {regPath}", LogHelper.LogType.Warning);
|
||||
// 尝试创建路径
|
||||
try
|
||||
{
|
||||
using (Microsoft.Win32.RegistryKey createKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||
{
|
||||
if (createKey != null)
|
||||
{
|
||||
createKey.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||||
LogHelper.WriteLogToFile($"创建并设置注册表路径: {regPath}", LogHelper.LogType.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception createEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"创建注册表路径失败: {createEx.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 备份路径更改为软件根目录下的saves/RegistryBackups文件夹
|
||||
string backupPath = Path.Combine(RootPath, "saves", "RegistryBackups");
|
||||
LogHelper.WriteLogToFile($"备份路径: {backupPath}");
|
||||
|
||||
if (!Directory.Exists(backupPath))
|
||||
{
|
||||
Directory.CreateDirectory(backupPath);
|
||||
LogHelper.WriteLogToFile($"创建备份目录: {backupPath}");
|
||||
}
|
||||
|
||||
string backupFile = Path.Combine(backupPath, $"SecurityBackup_{version}_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||
LogHelper.WriteLogToFile($"创建备份文件: {backupFile}");
|
||||
|
||||
// 使用UTF8编码写入注册表文件
|
||||
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||
{
|
||||
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]");
|
||||
|
||||
foreach (string valueName in baseKey.GetValueNames())
|
||||
{
|
||||
object value = baseKey.GetValue(valueName);
|
||||
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||
LogHelper.WriteLogToFile($"备份注册表值: {valueName} = {value}");
|
||||
}
|
||||
}
|
||||
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||
{
|
||||
// 仅在值不存在或不等于1时更新
|
||||
object currentValue = key.GetValue("DisableProtectedView");
|
||||
if (currentValue == null || (int)currentValue != 1)
|
||||
{
|
||||
key.SetValue("DisableProtectedView", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||||
LogHelper.WriteLogToFile($"Office {version} 注册表值已设置: DisableProtectedView = 1");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"Office {version} 注册表值已存在且无需更改: DisableProtectedView = 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"处理Office版本 {version} 时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理Office 365的特殊路径
|
||||
TryModifyOffice365Registry();
|
||||
}
|
||||
catch (SecurityException secEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"安全异常: {secEx.Message}", LogHelper.LogType.Error);
|
||||
ShowPermissionError();
|
||||
}
|
||||
catch (UnauthorizedAccessException authEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"访问被拒绝: {authEx.Message}", LogHelper.LogType.Error);
|
||||
ShowPermissionError();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"未知错误: {ex.GetType().FullName} - {ex.Message}", LogHelper.LogType.Error);
|
||||
LogHelper.WriteLogToFile(ex.StackTrace, LogHelper.LogType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
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 { }
|
||||
}
|
||||
|
||||
// 新增:用于设置崩溃后操作类型
|
||||
public enum CrashActionType
|
||||
{
|
||||
SilentRestart,
|
||||
NoAction
|
||||
}
|
||||
|
||||
// 心跳相关
|
||||
private static Timer heartbeatTimer;
|
||||
private static DateTime lastHeartbeat = DateTime.Now;
|
||||
private static Timer watchdogTimer;
|
||||
|
||||
private void StartHeartbeatMonitor()
|
||||
{
|
||||
// 主线程定时更新心跳
|
||||
heartbeatTimer = new Timer(_ => lastHeartbeat = DateTime.Now, null, 0, 1000);
|
||||
// 辅助线程检测心跳超时
|
||||
watchdogTimer = new Timer(_ =>
|
||||
{
|
||||
if ((DateTime.Now - lastHeartbeat).TotalSeconds > 10)
|
||||
{
|
||||
LogHelper.NewLog("检测到主线程无响应,自动重启。");
|
||||
if (CrashAction == CrashActionType.SilentRestart)
|
||||
{
|
||||
StartupCount.Increment();
|
||||
if (StartupCount.GetCount() >= 5)
|
||||
{
|
||||
MessageBox.Show("检测到程序已连续重启5次,已停止自动重启。请联系开发者或检查系统环境。", "重启次数过多", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
StartupCount.Reset();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
try
|
||||
{
|
||||
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
Process.Start(exePath);
|
||||
}
|
||||
catch { }
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
}, null, 0, 3000);
|
||||
}
|
||||
|
||||
// 看门狗进程
|
||||
private void StartWatchdogIfNeeded()
|
||||
{
|
||||
// 避免递归启动
|
||||
if (Environment.GetCommandLineArgs().Contains("--watchdog")) return;
|
||||
// 启动看门狗进程
|
||||
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = "--watchdog " + Process.GetCurrentProcess().Id + " \"" + watchdogExitSignalFile + "\"",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
};
|
||||
watchdogProcess = Process.Start(psi);
|
||||
}
|
||||
|
||||
// 看门狗主逻辑(在 Main 函数或 App_Startup 入口前加判断)
|
||||
public static void RunWatchdogIfNeeded()
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
if (args.Length >= 4 && args[1] == "--watchdog")
|
||||
{
|
||||
int pid = int.Parse(args[2]);
|
||||
string exitSignalFile = args[3];
|
||||
try
|
||||
{
|
||||
var proc = Process.GetProcessById(pid);
|
||||
while (!proc.HasExited)
|
||||
{
|
||||
// 检查退出信号文件
|
||||
if (File.Exists(exitSignalFile))
|
||||
{
|
||||
try { File.Delete(exitSignalFile); } catch { }
|
||||
Environment.Exit(0);
|
||||
}
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
// 主进程异常退出,自动重启
|
||||
StartupCount.Increment();
|
||||
if (StartupCount.GetCount() >= 5)
|
||||
{
|
||||
MessageBox.Show("检测到程序已连续重启5次,已停止自动重启。请联系开发者或检查系统环境。", "重启次数过多", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
StartupCount.Reset();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
Process.Start(exePath);
|
||||
}
|
||||
catch { }
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void App_Exit(object sender, ExitEventArgs e)
|
||||
{
|
||||
// 仅在软件内主动退出时关闭看门狗,并写入退出信号
|
||||
try
|
||||
{
|
||||
if (IsAppExitByUser)
|
||||
{
|
||||
// 写入退出信号文件,通知看门狗正常退出
|
||||
StartupCount.Reset();
|
||||
File.WriteAllText(watchdogExitSignalFile, "exit");
|
||||
if (watchdogProcess != null && !watchdogProcess.HasExited)
|
||||
{
|
||||
watchdogProcess.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查Office是否安装
|
||||
/// </summary>
|
||||
private bool IsOfficeInstalled()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查多个可能的注册表路径
|
||||
// 1. 检查传统的Office版本
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office"))
|
||||
{
|
||||
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到传统Office安装", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 检查64位注册表中的Office
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office"))
|
||||
{
|
||||
if (key != null && key.GetSubKeyNames().Any(name => name.Contains(".0")))
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到64位注册表中的Office安装", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 检查Office 365/Click-to-Run安装
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到Office 365 Click-to-Run", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 检查Office 365部署配置
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到Office 365 (15.0)", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到Office 365 (16.0)", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 检查Office 365零售订阅信息
|
||||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile("检测到Office 365配置", LogHelper.LogType.Info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile("未检测到任何Office安装", LogHelper.LogType.Warning);
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"检查Office安装时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示权限不足的错误提示
|
||||
/// </summary>
|
||||
private void ShowPermissionError()
|
||||
{
|
||||
const string message = "需要管理员权限才能完成此操作\n请以管理员身份重新启动应用程序";
|
||||
LogHelper.WriteLogToFile(message, LogHelper.LogType.Error);
|
||||
System.Windows.MessageBox.Show(message, "权限错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有已安装的Office版本
|
||||
/// </summary>
|
||||
private List<string> GetOfficeVersions()
|
||||
{
|
||||
var versions = new List<string>();
|
||||
try
|
||||
{
|
||||
// 检查HKLM
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
foreach (var subKeyName in key.GetSubKeyNames())
|
||||
{
|
||||
if (subKeyName.Contains(".0"))
|
||||
{
|
||||
versions.Add(subKeyName);
|
||||
LogHelper.WriteLogToFile($"在HKLM中找到Office版本: {subKeyName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查HKCU
|
||||
using (var key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Office"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
foreach (var subKeyName in key.GetSubKeyNames())
|
||||
{
|
||||
if (subKeyName.Contains(".0") && !versions.Contains(subKeyName))
|
||||
{
|
||||
versions.Add(subKeyName);
|
||||
LogHelper.WriteLogToFile($"在HKCU中找到Office版本: {subKeyName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查64位注册表
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\Microsoft\\Office"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
foreach (var subKeyName in key.GetSubKeyNames())
|
||||
{
|
||||
if (subKeyName.Contains(".0") && !versions.Contains(subKeyName))
|
||||
{
|
||||
versions.Add(subKeyName);
|
||||
LogHelper.WriteLogToFile($"在64位注册表中找到Office版本: {subKeyName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查Office 365的特殊路径
|
||||
CheckOffice365Versions(versions);
|
||||
|
||||
// 如果没有找到任何版本,添加默认的Office 365版本号
|
||||
if (versions.Count == 0 && IsOffice365Installed())
|
||||
{
|
||||
versions.Add("16.0");
|
||||
LogHelper.WriteLogToFile("未找到具体版本,添加默认Office 365版本: 16.0");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"获取Office版本时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 按版本号排序
|
||||
versions.Sort((a, b) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
double va = double.Parse(a.Replace(".0", ""));
|
||||
double vb = double.Parse(b.Replace(".0", ""));
|
||||
return vb.CompareTo(va); // 降序排列,最新版本在前
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测Office 365是否已安装
|
||||
/// </summary>
|
||||
private bool IsOffice365Installed()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查多个Office 365特定路径
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\15.0\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\16.0\\ClickToRun"))
|
||||
{
|
||||
if (key != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||
{
|
||||
if (key != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查Office 365特有的版本信息
|
||||
/// </summary>
|
||||
private void CheckOffice365Versions(List<string> versions)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查Click-to-Run版本路径
|
||||
using (var key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Office\\ClickToRun\\Configuration"))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
var platformVersion = key.GetValue("Platform") as string;
|
||||
var clickToRunVersion = key.GetValue("VersionToReport") as string;
|
||||
|
||||
if (!string.IsNullOrEmpty(platformVersion))
|
||||
{
|
||||
var majorVersion = platformVersion.Split('.').FirstOrDefault();
|
||||
if (!string.IsNullOrEmpty(majorVersion) && !versions.Contains($"{majorVersion}.0"))
|
||||
{
|
||||
versions.Add($"{majorVersion}.0");
|
||||
LogHelper.WriteLogToFile($"在Office 365配置中找到平台版本: {majorVersion}.0");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(clickToRunVersion))
|
||||
{
|
||||
var majorVersion = clickToRunVersion.Split('.').FirstOrDefault();
|
||||
if (!string.IsNullOrEmpty(majorVersion) && !versions.Contains($"{majorVersion}.0"))
|
||||
{
|
||||
versions.Add($"{majorVersion}.0");
|
||||
LogHelper.WriteLogToFile($"在Office 365配置中找到报告版本: {majorVersion}.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查安装路径来确认版本
|
||||
var possibleVersions = new[] { "15.0", "16.0" }; // Office 2013 (15.0) 和 Office 2016/2019/365 (16.0)
|
||||
foreach (var version in possibleVersions)
|
||||
{
|
||||
using (var key = Registry.LocalMachine.OpenSubKey($"Software\\Microsoft\\Office\\{version}\\Common\\InstallRoot"))
|
||||
{
|
||||
if (key != null && key.GetValue("Path") != null && !versions.Contains(version))
|
||||
{
|
||||
versions.Add(version);
|
||||
LogHelper.WriteLogToFile($"在InstallRoot中找到Office版本: {version}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"检查Office 365版本时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试修改Office 365的特殊注册表路径
|
||||
/// </summary>
|
||||
private void TryModifyOffice365Registry()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 准备备份目录
|
||||
string backupPath = Path.Combine(RootPath, "saves", "RegistryBackups");
|
||||
if (!Directory.Exists(backupPath))
|
||||
{
|
||||
Directory.CreateDirectory(backupPath);
|
||||
LogHelper.WriteLogToFile($"创建Office 365备份目录: {backupPath}");
|
||||
}
|
||||
|
||||
// 检查Office 365 Outlook和PowerPoint的特定路径
|
||||
string[] apps = { "outlook", "powerpoint" };
|
||||
|
||||
foreach (var app in apps)
|
||||
{
|
||||
// 检查用户级别的注册表
|
||||
string regPath = $"Software\\Microsoft\\Office\\16.0\\{app}\\Security";
|
||||
LogHelper.WriteLogToFile($"检查Office 365特定应用注册表: {regPath}");
|
||||
|
||||
try
|
||||
{
|
||||
// 先检查是否存在该路径
|
||||
using (var baseKey = Registry.CurrentUser.OpenSubKey(regPath))
|
||||
{
|
||||
// 如果路径存在,先备份
|
||||
if (baseKey != null)
|
||||
{
|
||||
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_{app}_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||
LogHelper.WriteLogToFile($"创建Office 365 {app}备份文件: {backupFile}");
|
||||
|
||||
// 使用UTF8编码写入注册表文件
|
||||
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||
{
|
||||
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{regPath}]");
|
||||
|
||||
foreach (string valueName in baseKey.GetValueNames())
|
||||
{
|
||||
object value = baseKey.GetValue(valueName);
|
||||
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||
LogHelper.WriteLogToFile($"备份Office 365 {app}注册表值: {valueName} = {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改或创建注册表项
|
||||
using (var key = Registry.CurrentUser.CreateSubKey(regPath, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
object currentValue = key.GetValue("DisableProtectedView");
|
||||
if (currentValue == null || (int)currentValue != 1)
|
||||
{
|
||||
key.SetValue("DisableProtectedView", 1, RegistryValueKind.DWord);
|
||||
LogHelper.WriteLogToFile($"Office 365 {app} 注册表值已设置: DisableProtectedView = 1");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"Office 365 {app} 注册表值已存在且无需更改");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"修改 {app} 注册表时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试通过Office信任中心路径修改
|
||||
string trustCenterPath = "Software\\Microsoft\\Office\\16.0\\Common\\Security\\FileValidation";
|
||||
LogHelper.WriteLogToFile($"检查信任中心路径: {trustCenterPath}");
|
||||
|
||||
try
|
||||
{
|
||||
// 先检查是否存在该路径
|
||||
using (var baseKey = Registry.CurrentUser.OpenSubKey(trustCenterPath))
|
||||
{
|
||||
// 如果路径存在,先备份
|
||||
if (baseKey != null)
|
||||
{
|
||||
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_TrustCenter_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||
LogHelper.WriteLogToFile($"创建信任中心备份文件: {backupFile}");
|
||||
|
||||
// 使用UTF8编码写入注册表文件
|
||||
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||
{
|
||||
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{trustCenterPath}]");
|
||||
|
||||
foreach (string valueName in baseKey.GetValueNames())
|
||||
{
|
||||
object value = baseKey.GetValue(valueName);
|
||||
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||
LogHelper.WriteLogToFile($"备份信任中心注册表值: {valueName} = {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (var key = Registry.CurrentUser.CreateSubKey(trustCenterPath, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
key.SetValue("DisableEditFromPV", 1, RegistryValueKind.DWord);
|
||||
LogHelper.WriteLogToFile("已禁用受保护视图中的编辑");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"修改信任中心路径时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 尝试修改EnableEditWhileViewingPolicy
|
||||
string policyPath = "Software\\Policies\\Microsoft\\Office\\16.0\\Common\\Security";
|
||||
try
|
||||
{
|
||||
// 先检查是否存在该路径
|
||||
using (var baseKey = Registry.CurrentUser.OpenSubKey(policyPath))
|
||||
{
|
||||
// 如果路径存在,先备份
|
||||
if (baseKey != null)
|
||||
{
|
||||
string backupFile = Path.Combine(backupPath, $"SecurityBackup_365_Policy_{DateTime.Now:yyyyMMddHHmmss}.reg");
|
||||
LogHelper.WriteLogToFile($"创建策略备份文件: {backupFile}");
|
||||
|
||||
// 使用UTF8编码写入注册表文件
|
||||
using (StreamWriter sw = new StreamWriter(backupFile, false, System.Text.Encoding.UTF8))
|
||||
{
|
||||
sw.WriteLine("Windows Registry Editor Version 5.00\n");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine($"[{Microsoft.Win32.Registry.CurrentUser.Name}\\{policyPath}]");
|
||||
|
||||
foreach (string valueName in baseKey.GetValueNames())
|
||||
{
|
||||
object value = baseKey.GetValue(valueName);
|
||||
sw.WriteLine($"\"{valueName}\"=dword:{((int)value):x8}");
|
||||
LogHelper.WriteLogToFile($"备份策略注册表值: {valueName} = {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (var key = Registry.CurrentUser.CreateSubKey(policyPath, true))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
key.SetValue("EnableEditWhileViewingPolicy", 1, RegistryValueKind.DWord);
|
||||
LogHelper.WriteLogToFile("已启用查看时编辑策略");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"修改策略路径时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"修改Office 365注册表时发生未知错误: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,985 +0,0 @@
|
||||
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;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
internal class AutoUpdateHelper
|
||||
{
|
||||
// 定义超时时间为10秒
|
||||
private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
public static async Task<string> CheckForUpdates(string proxy = null, UpdateChannel channel = UpdateChannel.Release)
|
||||
{
|
||||
try
|
||||
{
|
||||
string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Local version: {localVersion}");
|
||||
|
||||
string remoteAddress = proxy;
|
||||
|
||||
// 根据通道选择URL
|
||||
string primaryUrl, fallbackUrl;
|
||||
|
||||
if (channel == UpdateChannel.Release)
|
||||
{
|
||||
// Release通道版本信息地址
|
||||
primaryUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/AutomaticUpdateVersionControl.txt";
|
||||
fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Beta通道版本信息地址
|
||||
primaryUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt";
|
||||
fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt";
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Checking for updates on {channel} channel");
|
||||
|
||||
// 先尝试主地址
|
||||
remoteAddress += primaryUrl;
|
||||
string remoteVersion = await GetRemoteVersion(remoteAddress);
|
||||
|
||||
// 如果主地址失败,尝试备用地址
|
||||
if (remoteVersion == null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Primary URL failed, trying fallback URL");
|
||||
remoteVersion = await GetRemoteVersion(proxy + fallbackUrl);
|
||||
}
|
||||
|
||||
if (remoteVersion != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Remote version: {remoteVersion}");
|
||||
Version local = new Version(localVersion);
|
||||
Version remote = new Version(remoteVersion);
|
||||
if (remote > local)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {remoteVersion}");
|
||||
return remoteVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Current version is up to date");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve remote version from both URLs.", LogHelper.LogType.Error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error in CheckForUpdates: {ex.Message}", LogHelper.LogType.Error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetRemoteVersion(string fileUrl)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 设置超时时间为10秒
|
||||
client.Timeout = RequestTimeout;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}");
|
||||
|
||||
// 使用带超时的Task.WhenAny来确保请求不会无限期等待
|
||||
var downloadTask = client.GetAsync(fileUrl);
|
||||
var timeoutTask = Task.Delay(RequestTimeout);
|
||||
|
||||
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out after {RequestTimeout.TotalSeconds} seconds", LogHelper.LogType.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 请求完成,检查结果
|
||||
HttpResponseMessage response = await downloadTask;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
// Trim any whitespace, newlines, etc.
|
||||
content = content.Trim();
|
||||
|
||||
// If the content contains HTML (likely the GitHub view page instead of raw content),
|
||||
// try to extract the version number
|
||||
if (content.Contains("<html") || content.Contains("<!DOCTYPE"))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Received HTML content instead of raw version number - trying to extract version");
|
||||
// Try to extract version from GitHub page - look for text content in the file
|
||||
int startPos = content.IndexOf("<table");
|
||||
if (startPos > 0)
|
||||
{
|
||||
int endPos = content.IndexOf("</table>", startPos);
|
||||
if (endPos > startPos)
|
||||
{
|
||||
string tableContent = content.Substring(startPos, endPos - startPos);
|
||||
// Look for the version number pattern (like 1.2.3 or 1.2.3.4)
|
||||
var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)");
|
||||
if (match.Success)
|
||||
{
|
||||
content = match.Groups[1].Value;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Extracted version from HTML: {content}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Could not extract version from HTML content");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Response content: {content}");
|
||||
return content;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {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(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||||
private static string statusFilePath = null;
|
||||
|
||||
public static async Task<bool> DownloadSetupFileAndSaveStatus(string version, string proxy = "", UpdateChannel channel = UpdateChannel.Release)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Ensure update directory exists
|
||||
if (!Directory.Exists(updatesFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(updatesFolderPath);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Created updates directory: {updatesFolderPath}");
|
||||
}
|
||||
|
||||
// 根据通道选择下载地址
|
||||
string primaryUrl, fallbackUrl;
|
||||
|
||||
if (channel == UpdateChannel.Release)
|
||||
{
|
||||
// Release通道下载地址
|
||||
primaryUrl = $"{proxy}https://github.com/InkCanvasForClass/community/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
|
||||
fallbackUrl = $"{proxy}https://bgithub.xyz/InkCanvasForClass/community/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Beta通道下载地址
|
||||
primaryUrl = $"{proxy}https://github.com/InkCanvasForClass/community-beta/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
|
||||
fallbackUrl = $"{proxy}https://bgithub.xyz/InkCanvasForClass/community-beta/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Primary download URL: {primaryUrl}");
|
||||
|
||||
SaveDownloadStatus(false);
|
||||
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Target file path: {zipFilePath}");
|
||||
|
||||
// 先尝试主地址下载
|
||||
bool downloadSuccess = await DownloadFile(primaryUrl, zipFilePath);
|
||||
|
||||
// 如果主地址下载失败,尝试备用地址
|
||||
if (!downloadSuccess)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Primary download failed, trying fallback URL: {fallbackUrl}");
|
||||
downloadSuccess = await DownloadFile(fallbackUrl, zipFilePath);
|
||||
}
|
||||
|
||||
if (downloadSuccess)
|
||||
{
|
||||
SaveDownloadStatus(true);
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded.");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Failed to download the update file from both URLs.", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading update: {ex.Message}", LogHelper.LogType.Error);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
SaveDownloadStatus(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<bool> DownloadFile(string fileUrl, string destinationPath)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Configure client
|
||||
client.Timeout = TimeSpan.FromMinutes(5); // 下载文件需要更长的超时时间
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Downloading from: {fileUrl}");
|
||||
|
||||
// 创建临时文件路径
|
||||
string tempFilePath = destinationPath + ".tmp";
|
||||
|
||||
// 确保目标目录存在
|
||||
string directory = Path.GetDirectoryName(destinationPath);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// 使用带超时的Task.WhenAny来确保请求不会无限期等待
|
||||
var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead);
|
||||
var initialTimeoutTask = Task.Delay(RequestTimeout); // 使用全局定义的10秒超时
|
||||
|
||||
var completedTask = await Task.WhenAny(downloadTask, initialTimeoutTask);
|
||||
if (completedTask == initialTimeoutTask)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Initial connection timed out after 30 seconds", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 请求完成,检查结果
|
||||
HttpResponseMessage response = await downloadTask;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// 获取文件总大小
|
||||
long? totalBytes = response.Content.Headers.ContentLength;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | File size: {(totalBytes.HasValue ? (totalBytes.Value / 1024.0 / 1024.0).ToString("F2") + " MB" : "Unknown")}");
|
||||
|
||||
// 创建临时文件流
|
||||
using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
// 获取下载流
|
||||
using (var downloadStream = await response.Content.ReadAsStreamAsync())
|
||||
{
|
||||
byte[] buffer = new byte[8192]; // 8KB buffer
|
||||
long totalBytesRead = 0;
|
||||
int bytesRead;
|
||||
DateTime lastProgressUpdate = DateTime.Now;
|
||||
|
||||
// 设置下载超时 - 如果60秒内没有数据传输,则认为下载超时
|
||||
var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60));
|
||||
var readTask = Task.Run(async () => {
|
||||
while ((bytesRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
||||
totalBytesRead += bytesRead;
|
||||
|
||||
// 每5秒更新一次进度
|
||||
if ((DateTime.Now - lastProgressUpdate).TotalSeconds >= 5)
|
||||
{
|
||||
if (totalBytes.HasValue)
|
||||
{
|
||||
double percentage = (double)totalBytesRead / totalBytes.Value * 100;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Download progress: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Downloaded: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
||||
}
|
||||
lastProgressUpdate = DateTime.Now;
|
||||
|
||||
// 重置下载超时
|
||||
downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// 等待下载完成或超时
|
||||
if (await Task.WhenAny(readTask, downloadTimeoutTask) == downloadTimeoutTask)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Download timed out after 60 seconds of inactivity", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确保下载任务完成
|
||||
bool downloadCompleted = await readTask;
|
||||
|
||||
if (downloadCompleted)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Download completed: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果临时文件存在,则将其移动到目标位置
|
||||
if (File.Exists(tempFilePath))
|
||||
{
|
||||
// 如果目标文件已存在,先删除
|
||||
if (File.Exists(destinationPath))
|
||||
{
|
||||
File.Delete(destinationPath);
|
||||
}
|
||||
|
||||
File.Move(tempFilePath, destinationPath);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | File saved to: {destinationPath}");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Download timed out: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading file: {ex.Message}", LogHelper.LogType.Error);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 清理临时文件
|
||||
try
|
||||
{
|
||||
string tempFilePath = destinationPath + ".tmp";
|
||||
if (File.Exists(tempFilePath))
|
||||
{
|
||||
File.Delete(tempFilePath);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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 zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Checking for ZIP file: {zipFilePath}");
|
||||
|
||||
if (!File.Exists(zipFilePath))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file not found: {zipFilePath}", LogHelper.LogType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify ZIP file size and validity
|
||||
FileInfo fileInfo = new FileInfo(zipFilePath);
|
||||
if (fileInfo.Length == 0)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file is empty, cannot continue", LogHelper.LogType.Error);
|
||||
return;
|
||||
}
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file size: {fileInfo.Length} bytes");
|
||||
|
||||
// 获取当前应用程序路径和进程ID
|
||||
string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
int currentProcessId = Process.GetCurrentProcess().Id;
|
||||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Current application directory: {currentAppDir}");
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Current process ID: {currentProcessId}");
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Silent update mode: {isInSilence}");
|
||||
|
||||
// 创建批处理文件来执行更新操作
|
||||
string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Creating update batch file: {batchFilePath}");
|
||||
|
||||
// 构建批处理文件内容
|
||||
StringBuilder batchContent = new StringBuilder();
|
||||
batchContent.AppendLine("@echo off");
|
||||
|
||||
// 使窗口隐藏(使用VBS脚本运行隐藏窗口)
|
||||
batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\"");
|
||||
batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\"");
|
||||
batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\"");
|
||||
|
||||
// 创建真正的更新批处理文件
|
||||
string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||||
batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\"");
|
||||
|
||||
// 写入等待进程退出的代码到更新批处理文件
|
||||
batchContent.AppendLine($"echo set PROC_ID={currentProcessId} >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo :CHECK_PROCESS >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo tasklist /fi \"PID eq %PROC_ID%\" ^| find \"%PROC_ID%\" ^> nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% == 0 ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo timeout /t 1 /nobreak ^> nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||||
|
||||
// 应用程序已关闭,开始更新操作
|
||||
batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\"");
|
||||
|
||||
// 创建临时解压目录
|
||||
string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}");
|
||||
batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\"");
|
||||
|
||||
// PowerShell解压ZIP文件(因为批处理不直接支持ZIP解压)
|
||||
batchContent.AppendLine($"echo powershell -command \"Expand-Archive -Path '{zipFilePath.Replace("'", "''")}' -DestinationPath '{extractPath.Replace("'", "''")}' -Force\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||||
|
||||
// 复制文件到应用程序目录
|
||||
batchContent.AppendLine($"echo echo Copying updated files to application directory... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo xcopy /s /y /e \"{extractPath}\\*\" \"{currentAppDir}\\\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||||
|
||||
// 清理临时文件
|
||||
batchContent.AppendLine($"echo echo Cleaning up temporary files... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if exist \"{zipFilePath}\" del /f /q \"{zipFilePath}\" >> \"{updateBatPath}\"");
|
||||
|
||||
// 启动更新后的应用程序
|
||||
batchContent.AppendLine($"echo echo Update completed successfully! >> \"{updateBatPath}\"");
|
||||
|
||||
// 根据是否为静默更新模式决定是否自动启动应用程序
|
||||
if (isInSilence)
|
||||
{
|
||||
// 静默更新模式下,自动启动应用程序
|
||||
batchContent.AppendLine($"echo echo 自动启动应用程序... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非静默模式下,检查应用程序是否已经在运行
|
||||
batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo ) else ( >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo echo 应用程序已经在运行,不再重复启动 >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||||
}
|
||||
|
||||
batchContent.AppendLine($"echo exit /b 0 >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\"");
|
||||
|
||||
// 错误退出处理
|
||||
if (isInSilence)
|
||||
{
|
||||
// 静默模式下,不显示错误提示
|
||||
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo echo Update failed! >> \"%temp%\\icc_update_error.log\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非静默模式下,显示错误提示
|
||||
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
|
||||
}
|
||||
|
||||
// 删除批处理文件自身
|
||||
batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\"");
|
||||
batchContent.AppendLine($"echo exit >> \"{updateBatPath}\"");
|
||||
|
||||
// 使用VBS脚本执行更新批处理文件(隐藏窗口)
|
||||
batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\"");
|
||||
batchContent.AppendLine("del \"%temp%\\hideme.vbs\"");
|
||||
batchContent.AppendLine("exit");
|
||||
|
||||
// 写入批处理文件
|
||||
File.WriteAllText(batchFilePath, batchContent.ToString());
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Created update batch file");
|
||||
|
||||
// 启动批处理文件(隐藏窗口)
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = batchFilePath,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
});
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Started update batch process with hidden window");
|
||||
|
||||
// 应用程序将由用户手动关闭或由MainWindow中的代码关闭
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error preparing update installation: {ex.Message}", LogHelper.LogType.Error);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CopyDirectory(string sourceDir, string destinationDir)
|
||||
{
|
||||
bool allCopiesSuccessful = true;
|
||||
|
||||
try
|
||||
{
|
||||
// 创建目标目录(如果不存在)
|
||||
Directory.CreateDirectory(destinationDir);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Created/verified destination directory: {destinationDir}");
|
||||
|
||||
// 复制所有文件
|
||||
foreach (string filePath in Directory.GetFiles(sourceDir))
|
||||
{
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
string destPath = Path.Combine(destinationDir, fileName);
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Copying file: {fileName}");
|
||||
|
||||
// 如果目标文件存在,先删除
|
||||
if (File.Exists(destPath))
|
||||
{
|
||||
File.Delete(destPath);
|
||||
}
|
||||
|
||||
File.Copy(filePath, destPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
allCopiesSuccessful = false;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error copying file {fileName}: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 递归复制所有子目录
|
||||
foreach (string subDirPath in Directory.GetDirectories(sourceDir))
|
||||
{
|
||||
string subDirName = Path.GetFileName(subDirPath);
|
||||
string destSubDir = Path.Combine(destinationDir, subDirName);
|
||||
|
||||
bool subDirCopyResult = CopyDirectory(subDirPath, destSubDir);
|
||||
if (!subDirCopyResult)
|
||||
{
|
||||
allCopiesSuccessful = false;
|
||||
}
|
||||
}
|
||||
|
||||
return allCopiesSuccessful;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error copying directory {sourceDir}: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RestartApplication()
|
||||
{
|
||||
try
|
||||
{
|
||||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Restarting application: {appPath}");
|
||||
|
||||
// Create a batch file to wait briefly and then start the application
|
||||
// This allows the current process to fully exit before starting the new instance
|
||||
string batchFilePath = Path.Combine(Path.GetTempPath(), "RestartICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||||
|
||||
string batchContent =
|
||||
"@echo off\r\n" +
|
||||
"timeout /t 2 /nobreak >nul\r\n" +
|
||||
":: 检查应用程序是否已经在运行\r\n" +
|
||||
"tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul\r\n" +
|
||||
"if %ERRORLEVEL% neq 0 (\r\n" +
|
||||
" echo 启动应用程序...\r\n" +
|
||||
$" start \"\" \"{appPath}\"\r\n" +
|
||||
") else (\r\n" +
|
||||
" echo 应用程序已经在运行,不再重复启动\r\n" +
|
||||
")\r\n" +
|
||||
"timeout /t 1 /nobreak >nul\r\n" +
|
||||
"del \"%~f0\"\r\n" +
|
||||
"exit\r\n"; // 确保批处理进程结束
|
||||
|
||||
File.WriteAllText(batchFilePath, batchContent);
|
||||
|
||||
// Start the batch file
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/c start \"\" \"{batchFilePath}\"",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
});
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Created restart script at {batchFilePath}");
|
||||
|
||||
// Shutdown the application
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Shutting down application for restart");
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error restarting application: {ex.Message}", LogHelper.LogType.Error);
|
||||
|
||||
// Fallback direct restart approach
|
||||
try
|
||||
{
|
||||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Attempting direct restart: {appPath}");
|
||||
|
||||
// 检查是否已有实例运行
|
||||
Process[] processes = Process.GetProcessesByName("Ink Canvas");
|
||||
if (processes.Length <= 1) // 只有当前进程
|
||||
{
|
||||
Process.Start(appPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Application already running, not starting a new instance");
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
});
|
||||
}
|
||||
catch (Exception fallbackEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Fallback restart also failed: {fallbackEx.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteCommandLine(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/c {command} & exit", // 添加exit确保cmd进程退出
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (Process process = new Process { StartInfo = processStartInfo })
|
||||
{
|
||||
process.Start();
|
||||
// 设置一个超时时间
|
||||
bool exited = process.WaitForExit(500); // 等待500毫秒
|
||||
if (!exited)
|
||||
{
|
||||
// 不等待进程完成,让它在后台运行
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Command is running in background");
|
||||
}
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error executing command: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteUpdatesFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(updatesFolderPath))
|
||||
{
|
||||
// Try to delete all files first in case of locking issues
|
||||
foreach (string file in Directory.GetFiles(updatesFolderPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(file);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted file: {file}");
|
||||
}
|
||||
catch (Exception fileEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete file {file}: {fileEx.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
// Then try to delete subdirectories
|
||||
foreach (string dir in Directory.GetDirectories(updatesFolderPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted directory: {dir}");
|
||||
}
|
||||
catch (Exception dirEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete directory {dir}: {dirEx.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally try to delete the main directory
|
||||
try
|
||||
{
|
||||
Directory.Delete(updatesFolderPath, true);
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted updates folder: {updatesFolderPath}");
|
||||
}
|
||||
catch (Exception mainDirEx)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Could not completely delete updates folder: {mainDirEx.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Updates folder does not exist: {updatesFolderPath}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error deleting updates folder: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:版本修复方法,强制下载并安装指定通道的最新版本
|
||||
public static async Task<bool> FixVersion(UpdateChannel channel = UpdateChannel.Release)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Starting version fix for {channel} channel");
|
||||
|
||||
// 获取当前通道的最新版本
|
||||
string latestVersion = await CheckForUpdates(null, channel);
|
||||
|
||||
if (string.IsNullOrEmpty(latestVersion))
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | No newer version found for fixing", LogHelper.LogType.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 下载最新版本
|
||||
bool downloadResult = await DownloadSetupFileAndSaveStatus(latestVersion, "", channel);
|
||||
|
||||
if (!downloadResult)
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Failed to download update for fixing", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行安装,非静默模式
|
||||
InstallNewVersionApp(latestVersion, false);
|
||||
|
||||
// 设置为用户主动退出,避免被看门狗判定为崩溃
|
||||
App.IsAppExitByUser = true;
|
||||
|
||||
// 关闭应用程序
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
Application.Current.Shutdown();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error in FixVersion: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取更新日志
|
||||
public static async Task<string> GetUpdateLog(UpdateChannel channel = UpdateChannel.Release)
|
||||
{
|
||||
try
|
||||
{
|
||||
string primaryUrl, fallbackUrl;
|
||||
|
||||
if (channel == UpdateChannel.Release)
|
||||
{
|
||||
// Release通道更新日志地址
|
||||
primaryUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/UpdateLog.txt";
|
||||
fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.txt";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Beta通道更新日志地址
|
||||
primaryUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.txt";
|
||||
fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.txt";
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Getting update log from {channel} channel");
|
||||
|
||||
// 先尝试主地址
|
||||
string updateLog = await GetRemoteContent(primaryUrl);
|
||||
|
||||
// 如果主地址失败,尝试备用地址
|
||||
if (string.IsNullOrEmpty(updateLog))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Primary URL failed for update log, trying fallback URL");
|
||||
updateLog = await GetRemoteContent(fallbackUrl);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(updateLog))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Successfully retrieved update log");
|
||||
return updateLog;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve update log from both URLs.", LogHelper.LogType.Error);
|
||||
return $"# 无法获取更新日志\n\n无法从服务器获取更新日志信息,请检查网络连接后重试。";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error in GetUpdateLog: {ex.Message}", LogHelper.LogType.Error);
|
||||
return $"# 获取更新日志时发生错误\n\n错误信息: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
// 获取远程内容的通用方法
|
||||
private static async Task<string> GetRemoteContent(string fileUrl)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 设置超时时间为10秒
|
||||
client.Timeout = RequestTimeout;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}");
|
||||
|
||||
// 使用带超时的Task.WhenAny来确保请求不会无限期等待
|
||||
var downloadTask = client.GetAsync(fileUrl);
|
||||
var timeoutTask = Task.Delay(RequestTimeout);
|
||||
|
||||
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out after {RequestTimeout.TotalSeconds} seconds", LogHelper.LogType.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 请求完成,检查结果
|
||||
HttpResponseMessage response = await downloadTask;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
return content;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AutoUpdateWithSilenceTimeComboBox
|
||||
{
|
||||
public static ObservableCollection<string> Hours { get; set; } = new ObservableCollection<string>();
|
||||
public static ObservableCollection<string> Minutes { get; set; } = new ObservableCollection<string>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 防止窗口进入全屏状态的辅助类
|
||||
/// </summary>
|
||||
public static partial class AvoidFullScreenHelper
|
||||
{
|
||||
private static readonly DependencyProperty IsAvoidFullScreenEnabledProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsAvoidFullScreenEnabled",
|
||||
typeof(bool),
|
||||
typeof(AvoidFullScreenHelper));
|
||||
|
||||
private static bool _isBoardMode = false;
|
||||
public static void SetBoardMode(bool isBoardMode)
|
||||
{
|
||||
_isBoardMode = isBoardMode;
|
||||
}
|
||||
|
||||
public static void StartAvoidFullScreen(Window window)
|
||||
{
|
||||
if (window == null)
|
||||
throw new ArgumentNullException(nameof(window));
|
||||
|
||||
if (!(bool)window.GetValue(IsAvoidFullScreenEnabledProperty))
|
||||
{
|
||||
var hwndSource = PresentationSource.FromVisual(window) as HwndSource;
|
||||
if (hwndSource != null)
|
||||
{
|
||||
hwndSource.AddHook(KeepInWorkingAreaHook);
|
||||
window.SetValue(IsAvoidFullScreenEnabledProperty, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void StopAvoidFullScreen(Window window)
|
||||
{
|
||||
if (window == null)
|
||||
throw new ArgumentNullException(nameof(window));
|
||||
|
||||
if ((bool)window.GetValue(IsAvoidFullScreenEnabledProperty))
|
||||
{
|
||||
var hwndSource = PresentationSource.FromVisual(window) as HwndSource;
|
||||
if (hwndSource != null)
|
||||
{
|
||||
hwndSource.RemoveHook(KeepInWorkingAreaHook);
|
||||
window.ClearValue(IsAvoidFullScreenEnabledProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetIsAvoidFullScreenEnabled(DependencyObject obj) => (bool)obj.GetValue(IsAvoidFullScreenEnabledProperty);
|
||||
public static void SetIsAvoidFullScreenEnabled(DependencyObject obj, bool value) => obj.SetValue(IsAvoidFullScreenEnabledProperty, value);
|
||||
|
||||
private static IntPtr KeepInWorkingAreaHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
// 只拦截主画布窗口的全屏(最大化)操作
|
||||
var window = HwndSource.FromHwnd(hwnd)?.RootVisual as Window;
|
||||
if (window == null) return IntPtr.Zero;
|
||||
// 这里假设主画布窗口类名为MainWindow(如有不同请调整)
|
||||
if (window.GetType().Name != "MainWindow") return IntPtr.Zero;
|
||||
|
||||
if (_isBoardMode)
|
||||
{
|
||||
// 画板模式下允许全屏/最大化,不拦截
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
const int WM_WINDOWPOSCHANGING = 0x0046;
|
||||
const int WM_SYSCOMMAND = 0x0112;
|
||||
const int SC_MAXIMIZE = 0xF030;
|
||||
if (msg == WM_SYSCOMMAND && wParam.ToInt32() == SC_MAXIMIZE)
|
||||
{
|
||||
// 拦截最大化命令,强制还原窗口并调整到工作区
|
||||
window.WindowState = WindowState.Normal;
|
||||
var workingArea = GetWorkingArea(new Rect(window.Left, window.Top, window.Width, window.Height));
|
||||
window.Left = workingArea.Left;
|
||||
window.Top = workingArea.Top;
|
||||
window.Width = workingArea.Width;
|
||||
window.Height = workingArea.Height;
|
||||
handled = true;
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
if (msg != WM_WINDOWPOSCHANGING)
|
||||
return IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
var pos = (WindowPosition)Marshal.PtrToStructure(lParam, typeof(WindowPosition));
|
||||
if ((pos.Flags & (WindowPositionFlags.SWP_NOMOVE | WindowPositionFlags.SWP_NOSIZE)) != 0)
|
||||
return IntPtr.Zero;
|
||||
// 只处理主画布窗口
|
||||
// 计算目标矩形
|
||||
var targetRect = new Rect(
|
||||
(pos.Flags & WindowPositionFlags.SWP_NOMOVE) == 0 ? pos.X : window.Left,
|
||||
(pos.Flags & WindowPositionFlags.SWP_NOMOVE) == 0 ? pos.Y : window.Top,
|
||||
(pos.Flags & WindowPositionFlags.SWP_NOSIZE) == 0 ? pos.Width : window.Width,
|
||||
(pos.Flags & WindowPositionFlags.SWP_NOSIZE) == 0 ? pos.Height : window.Height);
|
||||
var workingArea = GetWorkingArea(targetRect);
|
||||
var adjustedRect = AdjustRectToWorkingArea(targetRect, workingArea);
|
||||
pos.X = (int)adjustedRect.Left;
|
||||
pos.Y = (int)adjustedRect.Top;
|
||||
pos.Width = (int)adjustedRect.Width;
|
||||
pos.Height = (int)adjustedRect.Height;
|
||||
pos.Flags &= ~(WindowPositionFlags.SWP_NOSIZE | WindowPositionFlags.SWP_NOMOVE | WindowPositionFlags.SWP_NOREDRAW);
|
||||
pos.Flags |= WindowPositionFlags.SWP_NOCOPYBITS;
|
||||
Marshal.StructureToPtr(pos, lParam, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"窗口位置调整失败: {ex.Message}");
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private static Rect GetWorkingArea(Rect windowRect)
|
||||
{
|
||||
// 获取所有显示器
|
||||
var screens = System.Windows.Forms.Screen.AllScreens;
|
||||
|
||||
// 确定窗口主要位于哪个显示器上
|
||||
System.Windows.Forms.Screen targetScreen = null;
|
||||
double maxIntersection = 0;
|
||||
|
||||
foreach (var screen in screens)
|
||||
{
|
||||
var screenRect = new Rect(
|
||||
screen.WorkingArea.X,
|
||||
screen.WorkingArea.Y,
|
||||
screen.WorkingArea.Width,
|
||||
screen.WorkingArea.Height);
|
||||
|
||||
var intersection = Rect.Intersect(windowRect, screenRect);
|
||||
if (intersection.Width * intersection.Height > maxIntersection)
|
||||
{
|
||||
maxIntersection = intersection.Width * intersection.Height;
|
||||
targetScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没找到,使用主显示器
|
||||
if (targetScreen == null)
|
||||
targetScreen = System.Windows.Forms.Screen.PrimaryScreen;
|
||||
|
||||
return new Rect(
|
||||
targetScreen.WorkingArea.X,
|
||||
targetScreen.WorkingArea.Y,
|
||||
targetScreen.WorkingArea.Width,
|
||||
targetScreen.WorkingArea.Height);
|
||||
}
|
||||
|
||||
private static Rect AdjustRectToWorkingArea(Rect windowRect, Rect workingArea)
|
||||
{
|
||||
// 调整尺寸以适应工作区域
|
||||
if (windowRect.Width > workingArea.Width)
|
||||
windowRect.Width = workingArea.Width;
|
||||
|
||||
if (windowRect.Height > workingArea.Height)
|
||||
windowRect.Height = workingArea.Height;
|
||||
|
||||
// 调整位置以确保窗口完全在工作区域内
|
||||
if (windowRect.Left < workingArea.Left)
|
||||
windowRect.X = workingArea.Left;
|
||||
else if (windowRect.Right > workingArea.Right)
|
||||
windowRect.X = workingArea.Right - windowRect.Width;
|
||||
|
||||
if (windowRect.Top < workingArea.Top)
|
||||
windowRect.Y = workingArea.Top;
|
||||
else if (windowRect.Bottom > workingArea.Bottom)
|
||||
windowRect.Y = workingArea.Bottom - windowRect.Height;
|
||||
|
||||
return windowRect;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用WPF原生类型替代Win32结构
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct WindowPosition
|
||||
{
|
||||
public IntPtr Hwnd;
|
||||
public IntPtr HwndInsertAfter;
|
||||
public int X;
|
||||
public int Y;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public WindowPositionFlags Flags;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum WindowPositionFlags : uint
|
||||
{
|
||||
SWP_NOSIZE = 0x0001,
|
||||
SWP_NOMOVE = 0x0002,
|
||||
SWP_NOZORDER = 0x0004,
|
||||
SWP_NOREDRAW = 0x0008,
|
||||
SWP_NOACTIVATE = 0x0010,
|
||||
SWP_FRAMECHANGED = 0x0020,
|
||||
SWP_SHOWWINDOW = 0x0040,
|
||||
SWP_HIDEWINDOW = 0x0080,
|
||||
SWP_NOCOPYBITS = 0x0100,
|
||||
SWP_NOOWNERZORDER = 0x0200,
|
||||
SWP_NOSENDCHANGING = 0x0400,
|
||||
}
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
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);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
private static extern IntPtr SHAppBarMessage(uint dwMessage, ref APPBARDATA pData);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
|
||||
|
||||
private const uint ABM_GETTASKBARPOS = 0x00000005;
|
||||
private const uint ABM_GETSTATE = 0x00000004;
|
||||
private const int SPI_GETWORKAREA = 0x0030;
|
||||
private const uint MONITOR_DEFAULTTOPRIMARY = 1;
|
||||
private const int ABS_AUTOHIDE = 0x0000001;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct MONITORINFO
|
||||
{
|
||||
public int cbSize;
|
||||
public RECT rcMonitor;
|
||||
public RECT rcWork;
|
||||
public uint dwFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct APPBARDATA
|
||||
{
|
||||
public int cbSize;
|
||||
public IntPtr hWnd;
|
||||
public uint uCallbackMessage;
|
||||
public uint uEdge;
|
||||
public RECT rc;
|
||||
public IntPtr lParam;
|
||||
}
|
||||
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Windows任务栏的高度(仅计算任务栏,不包括其他应用的停靠栏)
|
||||
/// </summary>
|
||||
/// <param name="screen">当前屏幕</param>
|
||||
/// <param name="dpiScaleY">DPI缩放Y值</param>
|
||||
/// <returns>任务栏高度</returns>
|
||||
public static double GetTaskbarHeight(System.Windows.Forms.Screen screen, double dpiScaleY)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 创建APPBARDATA结构
|
||||
var abd = new APPBARDATA();
|
||||
abd.cbSize = Marshal.SizeOf(abd);
|
||||
|
||||
// 获取任务栏状态
|
||||
IntPtr state = SHAppBarMessage(ABM_GETSTATE, ref abd);
|
||||
bool isAutoHide = (state.ToInt32() & ABS_AUTOHIDE) == ABS_AUTOHIDE;
|
||||
|
||||
// 如果任务栏是自动隐藏的,返回0
|
||||
if (isAutoHide)
|
||||
{
|
||||
LogHelper.WriteLogToFile("任务栏处于自动隐藏状态", LogHelper.LogType.Info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取任务栏信息
|
||||
IntPtr result = SHAppBarMessage(ABM_GETTASKBARPOS, ref abd);
|
||||
if (result != IntPtr.Zero)
|
||||
{
|
||||
// 获取当前屏幕的工作区
|
||||
RECT workArea = new RECT();
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, Marshal.AllocHGlobal(Marshal.SizeOf(workArea)), 0);
|
||||
|
||||
// 根据任务栏位置计算高度
|
||||
int taskbarHeight = 0;
|
||||
|
||||
// 任务栏的uEdge: 0=左, 1=上, 2=右, 3=下
|
||||
switch (abd.uEdge)
|
||||
{
|
||||
case 1: // 上
|
||||
taskbarHeight = abd.rc.Height;
|
||||
break;
|
||||
case 3: // 下
|
||||
taskbarHeight = abd.rc.Height;
|
||||
break;
|
||||
case 0: // 左
|
||||
case 2: // 右
|
||||
// 水平任务栏不影响高度
|
||||
taskbarHeight = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// 考虑DPI缩放
|
||||
return taskbarHeight / dpiScaleY;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"获取任务栏高度出错: {ex.Message}");
|
||||
LogHelper.WriteLogToFile($"获取任务栏高度出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 如果获取失败,回退到通用方法
|
||||
return (screen.Bounds.Height - screen.WorkingArea.Height) / dpiScaleY;
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
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)
|
||||
{
|
||||
if (ex == null) return;
|
||||
var stackTrace = ex.StackTrace ?? "<no stack trace>";
|
||||
var msg = $"[Exception] Type: {ex.GetType().FullName}\nMessage: {ex.Message}\nStackTrace: {stackTrace}";
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
msg += $"\nInnerException: {ex.InnerException.GetType().FullName} - {ex.InnerException.Message}\n{ex.InnerException.StackTrace}";
|
||||
}
|
||||
WriteLogToFile(msg, LogType.Error);
|
||||
}
|
||||
|
||||
public static void WriteLogToFile(string str, LogType logType = LogType.Info)
|
||||
{
|
||||
string strLogType = logType.ToString();
|
||||
try
|
||||
{
|
||||
var file = App.RootPath + LogFile;
|
||||
if (!Directory.Exists(App.RootPath))
|
||||
{
|
||||
Directory.CreateDirectory(App.RootPath);
|
||||
}
|
||||
var threadId = Thread.CurrentThread.ManagedThreadId;
|
||||
var callingMethod = new StackTrace(2, true).GetFrame(0);
|
||||
string callerInfo = "<unknown>";
|
||||
if (callingMethod != null)
|
||||
{
|
||||
var method = callingMethod.GetMethod();
|
||||
if (method != null)
|
||||
{
|
||||
var className = method.DeclaringType != null ? method.DeclaringType.FullName : "<no class>";
|
||||
callerInfo = $"{className}.{method.Name}";
|
||||
}
|
||||
}
|
||||
string logLine = string.Format("{0} [T{1}] [{2}] [{3}] {4}", DateTime.Now.ToString("O"), threadId, strLogType, callerInfo, str);
|
||||
using (StreamWriter sw = new StreamWriter(file, true))
|
||||
{
|
||||
sw.WriteLine(logLine);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
internal static void WriteLogToFile(string v, object warning)
|
||||
{
|
||||
WriteLogToFile($"[Warning] {v}", LogType.Warning);
|
||||
}
|
||||
|
||||
public enum LogType
|
||||
{
|
||||
Info,
|
||||
Trace,
|
||||
Error,
|
||||
Event,
|
||||
Warning
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
public static class StartupCount
|
||||
{
|
||||
private static readonly string CountFilePath = Path.Combine(App.RootPath, "startup-count");
|
||||
private static readonly object fileLock = new object();
|
||||
|
||||
public static int GetCount()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(CountFilePath))
|
||||
{
|
||||
var text = File.ReadAllText(CountFilePath).Trim();
|
||||
if (int.TryParse(text, out int count))
|
||||
return count;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void Increment()
|
||||
{
|
||||
lock (fileLock)
|
||||
{
|
||||
int count = GetCount() + 1;
|
||||
try
|
||||
{
|
||||
File.WriteAllText(CountFilePath, count.ToString());
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
lock (fileLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(CountFilePath))
|
||||
File.Delete(CountFilePath);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,561 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<PropertyGroup>
|
||||
<RuntimeIdentifiers>win;win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Ink_Canvas</RootNamespace>
|
||||
<AssemblyName>InkCanvasForClass</AssemblyName>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>2</ApplicationRevision>
|
||||
<ApplicationVersion>2.0.2.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Configurations>Debug;Release;x86 Debug</Configurations>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86 Debug|AnyCPU'">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\icc.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86 Debug|x86'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<Title>InkCanvasForClass</Title>
|
||||
<Version>5.0.4</Version>
|
||||
<Authors>Dubi906w</Authors>
|
||||
<Product>InkCanvasForClass</Product>
|
||||
<Copyright>© Copyright HARKOTEK Studio 2024-now</Copyright>
|
||||
<PackageProjectUrl>https://icc.bliemhax.com</PackageProjectUrl>
|
||||
<FileVersion>bundled</FileVersion>
|
||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86 Debug|ARM64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86 Debug|x64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="IACore">
|
||||
<HintPath>.\IACore.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="IALoader">
|
||||
<HintPath>.\IALoader.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="IAWinFX">
|
||||
<HintPath>.\IAWinFX.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="netstandard" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="UIAutomationClient" />
|
||||
<Reference Include="UIAutomationTypes" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
|
||||
<PackageReference Include="iNKORE.UI.WPF.Modern" Version="0.9.27" />
|
||||
<PackageReference Include="MdXaml" Version="1.27.0" />
|
||||
<PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1018" />
|
||||
<PackageReference Include="MicrosoftOfficeCore" Version="15.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
|
||||
<PackageReference Include="OSVersionExt" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="stdole">
|
||||
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>
|
||||
<VersionMajor>2</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>primary</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="VBIDE">
|
||||
<Guid>{0002E157-0000-0000-C000-000000000046}</Guid>
|
||||
<VersionMajor>5</VersionMajor>
|
||||
<VersionMinor>3</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>primary</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\TimerDownNotice.wav" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\Cursor.cur" />
|
||||
<Resource Include="Resources\Cursors\Pen.cur" />
|
||||
<Resource Include="Resources\DeveloperAvatars\aaaaaaccd.jpg" />
|
||||
<Resource Include="Resources\DeveloperAvatars\Alan-CRL.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\NetheriteBowl.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\NotYoojun.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\RaspberryKan.jpg" />
|
||||
<Resource Include="Resources\DeveloperAvatars\wwei.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\yuwenhui2020.png" />
|
||||
<Resource Include="Resources\icc.ico" />
|
||||
<Resource Include="Resources\Icons-png\AdmoxBooth.png" />
|
||||
<Resource Include="Resources\Icons-png\AdmoxWhiteboard.png" />
|
||||
<Resource Include="Resources\Icons-png\check-box-background.png" />
|
||||
<Resource Include="Resources\Icons-png\Donview.png" />
|
||||
<Resource Include="Resources\Icons-png\EasiNote3.png" />
|
||||
<Resource Include="Resources\Icons-png\eraser-line.png" />
|
||||
<Resource Include="Resources\Icons-png\eraser-outline.png" />
|
||||
<Resource Include="Resources\Icons-png\HiteLightBoard.png" />
|
||||
<Resource Include="Resources\Icons-png\ica.png" />
|
||||
<Resource Include="Resources\Icons-png\icc-transparent-dark-small.png" />
|
||||
<Resource Include="Resources\Icons-png\icc-transparent-dark.png" />
|
||||
<Resource Include="Resources\Icons-png\icc-transparent.png" />
|
||||
<Resource Include="Resources\Icons-png\icc.png" />
|
||||
<Resource Include="Resources\Icons-png\InkCanvas.png" />
|
||||
<Resource Include="Resources\Icons-png\kuanciya.png" />
|
||||
<Resource Include="Resources\Icons-png\kuandogeyuanliangwo.png" />
|
||||
<Resource Include="Resources\Icons-png\kuandoujiyanhuaji.png" />
|
||||
<Resource Include="Resources\Icons-png\kuanneikuhuaji.png" />
|
||||
<Resource Include="Resources\Icons-png\kuanshounvhuaji.png" />
|
||||
<Resource Include="Resources\Icons-png\MaxHubWhiteboard.png" />
|
||||
<Resource Include="Resources\Icons-png\playCircle.png" />
|
||||
<Resource Include="Resources\Icons-png\redo.png" />
|
||||
<Resource Include="Resources\Icons-png\Seewo2Annotation.png" />
|
||||
<Resource Include="Resources\Icons-png\setting.png" />
|
||||
<Resource Include="Resources\Icons-png\tiebahuaji.png" />
|
||||
<Resource Include="Resources\Icons-png\transparent-grid.png" />
|
||||
<Resource Include="Resources\Icons-png\undo.png" />
|
||||
<Resource Include="Resources\Icons-png\minimize.png" />
|
||||
<Resource Include="Resources\Icons-png\penUpright.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\twoFingelMove-Blue.png" />
|
||||
<Resource Include="Resources\Icons-png\twoFingelMove.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\close-circle.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\DeveloperAvatars\ChangSakura.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\clover-yan.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\CN-Ironegg.jpg" />
|
||||
<Resource Include="Resources\DeveloperAvatars\jiajiaxd.jpg" />
|
||||
<Resource Include="Resources\DeveloperAvatars\kengwang.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\STBBRD.png" />
|
||||
<Resource Include="Resources\DeveloperAvatars\WXRIW.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\down.png" />
|
||||
<Resource Include="Resources\Icons-png\up.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\EasiCamera.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\Desmos.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_cursor_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_lasso_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_settings_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_whiteboard_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_dark_theme_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_dual_screen_span_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_timer_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_delete_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_cursorWITHdelete_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_arrow_circle_left_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_arrow_circle_right_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_weather_moon_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_weather_sunny_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_signature_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_save_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_camera_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_copy_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_copy_add_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_add_circle_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_flip_horizontal_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_flip_vertical_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_edit_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_folder_open_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_people_money_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_person_money_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_arrow_rotate_clockwise_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_scale_fit_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_scales_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_arrow_clockwise_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_calendar_sync_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_dismiss_circle_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_drag_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_shapes_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_power_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_clock_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_book_question_mark_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_keyboard_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_control_button_24_regular.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\ic_fluent_people_24_regular.png" />
|
||||
<Resource Include="Resources\Icons-png\VComYouJiao.png" />
|
||||
<Resource Include="Resources\Icons-png\WenXiang.png" />
|
||||
<Resource Include="Resources\Icons-png\YiYunVisualPresenter.png" />
|
||||
<Resource Include="Resources\Icons-png\YiYunWhiteboard.png" />
|
||||
<Resource Include="Resources\new-icons\chevron-left.png" />
|
||||
<Resource Include="Resources\new-icons\end-slides-show.png">
|
||||
<CopyToOutputDirectory></CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\new-icons\eye.png" />
|
||||
<Resource Include="Resources\new-icons\hand-move.png" />
|
||||
<Resource Include="Resources\new-icons\highlighter-white.png" />
|
||||
<Resource Include="Resources\new-icons\multi-touch.png" />
|
||||
<Resource Include="Resources\new-icons\osu-lazer-triangles.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\pen-lined.png" />
|
||||
<Resource Include="Resources\new-icons\pen-solid.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\cursor-lined.png" />
|
||||
<Resource Include="Resources\new-icons\cursor-solid.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\eraser-lined.png" />
|
||||
<Resource Include="Resources\new-icons\eraser-solid.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\circle-eraser-lined.png" />
|
||||
<Resource Include="Resources\new-icons\circle-eraser-solid.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\lasso-select-lined.png" />
|
||||
<Resource Include="Resources\new-icons\lasso-select-solid.png" />
|
||||
<Resource Include="Resources\new-icons\pen-white.png" />
|
||||
<Resource Include="Resources\new-icons\rotate.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\trash.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\shapes.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\eye-off.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\grid.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\blackboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\cursor-clear.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\DeveloperAvatars\dubi906w.jpg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\gesture.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\gesture-enabled.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\close-white.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\checked-white.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\checked-black.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\pressdown-background.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\arrow.png" />
|
||||
<Resource Include="Resources\Icons-png\geo-icons\dashed-line.png" />
|
||||
<Resource Include="Resources\Icons-png\geo-icons\dotted-line.png" />
|
||||
<Resource Include="Resources\Icons-png\geo-icons\line.png" />
|
||||
<Resource Include="Resources\Icons-png\geo-icons\paralle-lines.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\centered-square.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\centered-circle.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\centered-circle-dashed.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\centered-oval.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\square.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\cylinder.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\cone.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\geo-icons\cube.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\EasiNote.png" />
|
||||
<Resource Include="Resources\Icons-png\EasiNote3C.png" />
|
||||
<Resource Include="Resources\Icons-png\EasiNote5C.png" />
|
||||
<Resource Include="Resources\Icons-png\SeewoPinco.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\HiteBoard.png" />
|
||||
<Resource Include="Resources\Icons-png\HiteCamera.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\Whiteboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\Powerpoint.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\PPTTools.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\WPS.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\hatsune-miku1.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-Fluent\party.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\redo.png" />
|
||||
<Resource Include="Resources\new-icons\undo.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\new-icons\unfold-chevron.png" />
|
||||
<Resource Include="Resources\new-icons\zoom.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="MainWindow.xaml~RF6c3144.TMP" />
|
||||
<None Remove="Resources\Cursors\Cursor.cur" />
|
||||
<None Remove="Resources\Cursors\Pen.cur" />
|
||||
<None Remove="Resources\DeveloperAvatars\aaaaaaccd.jpg" />
|
||||
<None Remove="Resources\DeveloperAvatars\Alan-CRL.png" />
|
||||
<None Remove="Resources\DeveloperAvatars\NetheriteBowl.png" />
|
||||
<None Remove="Resources\DeveloperAvatars\NotYoojun.png" />
|
||||
<None Remove="Resources\DeveloperAvatars\RaspberryKan.jpg" />
|
||||
<None Remove="Resources\DeveloperAvatars\wwei.png" />
|
||||
<None Remove="Resources\DeveloperAvatars\yuwenhui2020.png" />
|
||||
<None Remove="Resources\icc.ico" />
|
||||
<None Remove="Resources\Icons-png\AdmoxBooth.png" />
|
||||
<None Remove="Resources\Icons-png\AdmoxWhiteboard.png" />
|
||||
<None Remove="Resources\Icons-png\Donview.png" />
|
||||
<None Remove="Resources\Icons-png\EasiNote3.png" />
|
||||
<None Remove="Resources\Icons-png\HiteAnnotation.png" />
|
||||
<None Remove="Resources\Icons-png\HiteLightBoard.png" />
|
||||
<None Remove="Resources\Icons-png\ica.png" />
|
||||
<None Remove="Resources\Icons-png\icc-transparent-dark-small.png" />
|
||||
<None Remove="Resources\Icons-png\icc-transparent-dark.png" />
|
||||
<None Remove="Resources\Icons-png\icc-transparent.png" />
|
||||
<None Remove="Resources\Icons-png\icc.png" />
|
||||
<None Remove="Resources\Icons-png\idt.png" />
|
||||
<None Remove="Resources\Icons-png\InkCanvas.png" />
|
||||
<None Remove="Resources\Icons-png\kuanciya.png" />
|
||||
<None Remove="Resources\Icons-png\kuandogeyuanliangwo.png" />
|
||||
<None Remove="Resources\Icons-png\kuandoujiyanhuaji.png" />
|
||||
<None Remove="Resources\Icons-png\kuanneikuhuaji.png" />
|
||||
<None Remove="Resources\Icons-png\kuanshounvhuaji.png" />
|
||||
<None Remove="Resources\Icons-png\MaxHubWhiteboard.png" />
|
||||
<None Remove="Resources\Icons-png\Seewo2Annotation.png" />
|
||||
<None Remove="Resources\Icons-png\tiebahuaji.png" />
|
||||
<None Remove="Resources\Icons-png\transparent-grid.png" />
|
||||
<None Remove="Resources\Icons-png\VComYouJiao.png" />
|
||||
<None Remove="Resources\Icons-png\WenXiang.png" />
|
||||
<None Remove="Resources\Icons-png\YiYunVisualPresenter.png" />
|
||||
<None Remove="Resources\Icons-png\YiYunWhiteboard.png" />
|
||||
<None Remove="Resources\new-icons\chevron-left.png" />
|
||||
<None Remove="Resources\new-icons\end-slides-show.png" />
|
||||
<None Remove="Resources\new-icons\eye.png" />
|
||||
<None Remove="Resources\new-icons\hand-move.png" />
|
||||
<None Remove="Resources\new-icons\highlighter-white.png" />
|
||||
<None Remove="Resources\new-icons\multi-touch.png" />
|
||||
<None Remove="Resources\new-icons\osu-lazer-triangles.png" />
|
||||
<None Remove="Resources\new-icons\pen-white.png" />
|
||||
<None Remove="Resources\new-icons\rotate.png" />
|
||||
<None Remove="Resources\new-icons\unfold-chevron.png" />
|
||||
<None Remove="Resources\new-icons\zoom.png" />
|
||||
<None Remove="Resources\PresentationExample\bottombar-dark.png" />
|
||||
<None Remove="Resources\PresentationExample\bottombar-white.png" />
|
||||
<None Remove="Resources\PresentationExample\page.jpg" />
|
||||
<None Remove="Resources\PresentationExample\sidebar-dark.png" />
|
||||
<None Remove="Resources\PresentationExample\sidebar-white.png" />
|
||||
<None Remove="Resources\PresentationExample\toolbar.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\idt.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\HiteAnnotation.png" />
|
||||
<Resource Include="Resources\PresentationExample\bottombar-dark.png" />
|
||||
<Resource Include="Resources\PresentationExample\bottombar-white.png" />
|
||||
<Resource Include="Resources\PresentationExample\page.jpg" />
|
||||
<Resource Include="Resources\PresentationExample\sidebar-dark.png" />
|
||||
<Resource Include="Resources\PresentationExample\sidebar-white.png" />
|
||||
<Resource Include="Resources\PresentationExample\toolbar.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_LastSelectedProfileId>D:\vs\ica\Ink Canvas\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,812 +0,0 @@
|
||||
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;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Reflection;
|
||||
|
||||
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;
|
||||
var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
|
||||
ViewboxFloatingBar.Margin = new Thickness(
|
||||
(workingArea.Width - 284) / 2,
|
||||
workingArea.Bottom - 60 - workingArea.Top,
|
||||
-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();
|
||||
|
||||
// 注册输入事件
|
||||
inkCanvas.PreviewMouseDown += inkCanvas_PreviewMouseDown;
|
||||
inkCanvas.StylusDown += inkCanvas_StylusDown;
|
||||
inkCanvas.TouchDown += inkCanvas_TouchDown;
|
||||
inkCanvas.TouchUp += inkCanvas_TouchUp;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas1);
|
||||
|
||||
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;
|
||||
// 自动收纳到侧边栏
|
||||
if (Settings.Startup.IsFoldAtStartup)
|
||||
{
|
||||
FoldFloatingBar_MouseUp(null, null);
|
||||
}
|
||||
|
||||
// 恢复崩溃后操作设置
|
||||
if (App.CrashAction == App.CrashActionType.SilentRestart)
|
||||
RadioCrashSilentRestart.IsChecked = true;
|
||||
else
|
||||
RadioCrashNoAction.IsChecked = true;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 检查是否有待安装的更新
|
||||
CheckPendingUpdates();
|
||||
}
|
||||
|
||||
private void CheckPendingUpdates()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 如果有可用的更新版本且启用了自动更新
|
||||
if (AvailableLatestVersion != null && Settings.Startup.IsAutoUpdate)
|
||||
{
|
||||
// 检查更新文件是否已下载
|
||||
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||||
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
|
||||
|
||||
if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Installing pending update v{AvailableLatestVersion} on application close");
|
||||
|
||||
// 设置为用户主动退出,避免被看门狗判定为崩溃
|
||||
App.IsAppExitByUser = true;
|
||||
|
||||
// 创建批处理脚本并启动,软件关闭后会执行更新操作
|
||||
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error checking pending updates: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void AutoUpdate() {
|
||||
// 使用当前选择的更新通道检查更新
|
||||
AvailableLatestVersion = await AutoUpdateHelper.CheckForUpdates(null, Settings.Startup.UpdateChannel);
|
||||
|
||||
// 声明下载状态变量,用于整个方法
|
||||
bool isDownloadSuccessful = false;
|
||||
|
||||
if (AvailableLatestVersion != null) {
|
||||
// 检测到新版本
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {AvailableLatestVersion}");
|
||||
|
||||
// 检查是否是用户选择跳过的版本
|
||||
if (!string.IsNullOrEmpty(Settings.Startup.SkippedVersion) &&
|
||||
Settings.Startup.SkippedVersion == AvailableLatestVersion) {
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Version {AvailableLatestVersion} was marked to be skipped by the user");
|
||||
return; // 跳过此版本,不执行更新操作
|
||||
}
|
||||
|
||||
// 如果检测到的版本与跳过的版本不同,则清除跳过版本记录
|
||||
// 这确保用户只能跳过当前最新版本,而不是永久跳过所有更新
|
||||
if (!string.IsNullOrEmpty(Settings.Startup.SkippedVersion) &&
|
||||
Settings.Startup.SkippedVersion != AvailableLatestVersion) {
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Detected new version {AvailableLatestVersion} different from skipped version {Settings.Startup.SkippedVersion}, clearing skip record");
|
||||
Settings.Startup.SkippedVersion = "";
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
// 获取当前版本
|
||||
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
|
||||
// 如果启用了静默更新,则自动下载更新而不显示提示
|
||||
if (Settings.Startup.IsAutoUpdateWithSilence) {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Silent update enabled, downloading update automatically without notification");
|
||||
|
||||
// 静默下载更新,传递当前选择的更新通道
|
||||
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion, "", Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful) {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when conditions are met");
|
||||
|
||||
// 启动检查定时器,定期检查是否可以安装
|
||||
timerCheckAutoUpdateWithSilence.Start();
|
||||
} else {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Silent update download failed", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有启用静默更新,则显示常规更新窗口
|
||||
string releaseDate = DateTime.Now.ToString("yyyy年MM月dd日");
|
||||
|
||||
// 从服务器获取更新日志
|
||||
string releaseNotes = await AutoUpdateHelper.GetUpdateLog(Settings.Startup.UpdateChannel);
|
||||
|
||||
// 如果获取失败,使用默认文本
|
||||
if (string.IsNullOrEmpty(releaseNotes))
|
||||
{
|
||||
releaseNotes = $@"# InkCanvasForClass v{AvailableLatestVersion}更新
|
||||
|
||||
无法获取更新日志,但新版本已准备就绪。";
|
||||
}
|
||||
|
||||
// 创建并显示更新窗口
|
||||
HasNewUpdateWindow updateWindow = new HasNewUpdateWindow(currentVersion, AvailableLatestVersion, releaseDate, releaseNotes);
|
||||
bool? dialogResult = updateWindow.ShowDialog();
|
||||
|
||||
// 如果窗口被关闭但没有点击按钮,则不执行任何操作
|
||||
if (dialogResult != true) {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update dialog closed without selection");
|
||||
return;
|
||||
}
|
||||
|
||||
// 不再从更新窗口获取自动更新设置
|
||||
|
||||
// 根据用户选择处理更新
|
||||
switch (updateWindow.Result) {
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateNow:
|
||||
// 立即更新:显示下载进度,下载完成后立即安装
|
||||
LogHelper.WriteLogToFile("AutoUpdate | User chose to update now");
|
||||
|
||||
// 显示下载进度提示
|
||||
MessageBox.Show("开始下载更新,请稍候...", "正在更新", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
// 下载更新文件,传递当前选择的更新通道
|
||||
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion, "", Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful) {
|
||||
// 下载成功,提示用户准备安装
|
||||
MessageBoxResult result = MessageBox.Show("更新已下载完成,点击确定后将关闭软件并安装新版本!", "安装更新", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
|
||||
// 只有当用户点击确定按钮后才关闭软件
|
||||
if (result == MessageBoxResult.OK) {
|
||||
// 设置为用户主动退出,避免被看门狗判定为崩溃
|
||||
App.IsAppExitByUser = true;
|
||||
|
||||
// 准备批处理脚本
|
||||
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, false);
|
||||
|
||||
// 关闭软件,让安装程序接管
|
||||
Application.Current.Shutdown();
|
||||
} else {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | User cancelled update installation");
|
||||
}
|
||||
} else {
|
||||
// 下载失败
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateLater:
|
||||
// 稍后更新:静默下载,在软件关闭时自动安装
|
||||
LogHelper.WriteLogToFile("AutoUpdate | User chose to update later");
|
||||
|
||||
// 不管设置如何,都进行下载
|
||||
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileAndSaveStatus(AvailableLatestVersion, "", Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful) {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when application closes");
|
||||
|
||||
// 设置标志,在应用程序关闭时安装
|
||||
Settings.Startup.IsAutoUpdate = true;
|
||||
Settings.Startup.IsAutoUpdateWithSilence = true;
|
||||
|
||||
// 启动检查定时器
|
||||
timerCheckAutoUpdateWithSilence.Start();
|
||||
|
||||
// 通知用户
|
||||
MessageBox.Show("更新已下载完成,将在软件关闭时自动安装。", "更新已准备就绪", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
} else {
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update download failed", LogHelper.LogType.Error);
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.SkipVersion:
|
||||
// 跳过该版本:记录到设置中
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | User chose to skip version {AvailableLatestVersion}");
|
||||
|
||||
// 记录要跳过的版本号
|
||||
Settings.Startup.SkippedVersion = AvailableLatestVersion;
|
||||
|
||||
// 保存设置到文件
|
||||
SaveSettingsToFile();
|
||||
|
||||
// 通知用户
|
||||
MessageBox.Show($"已设置跳过版本 {AvailableLatestVersion},在下次发布新版本之前不会再提示更新。",
|
||||
"已跳过此版本",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
AutoUpdateHelper.DeleteUpdatesFolder();
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:崩溃后操作设置按钮事件
|
||||
private void RadioCrashAction_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (RadioCrashSilentRestart != null && RadioCrashSilentRestart.IsChecked == true)
|
||||
{
|
||||
App.CrashAction = App.CrashActionType.SilentRestart;
|
||||
}
|
||||
else if (RadioCrashNoAction != null && RadioCrashNoAction.IsChecked == true)
|
||||
{
|
||||
App.CrashAction = App.CrashActionType.NoAction;
|
||||
}
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
// 添加一个辅助方法,根据当前编辑模式设置光标
|
||||
private void SetCursorBasedOnEditingMode(InkCanvas canvas)
|
||||
{
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
canvas.UseCustomCursor = true;
|
||||
canvas.ForceCursor = true;
|
||||
|
||||
// 根据编辑模式设置不同的光标
|
||||
if (canvas.EditingMode == InkCanvasEditingMode.EraseByPoint) {
|
||||
canvas.Cursor = Cursors.Cross;
|
||||
} else if (canvas.EditingMode == InkCanvasEditingMode.Ink) {
|
||||
var sri = Application.GetResourceStream(new Uri("Resources/Cursors/Pen.cur", UriKind.Relative));
|
||||
if (sri != null)
|
||||
canvas.Cursor = new Cursor(sri.Stream);
|
||||
} else if (canvas.EditingMode == InkCanvasEditingMode.Select) {
|
||||
canvas.Cursor = Cursors.Cross;
|
||||
}
|
||||
|
||||
// 确保光标可见,无论是鼠标、触控还是手写笔
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
|
||||
// 强制应用光标设置
|
||||
canvas.ForceCursor = true;
|
||||
|
||||
// 确保手写笔模式下也能显示光标
|
||||
if (Tablet.TabletDevices.Count > 0) {
|
||||
foreach (TabletDevice device in Tablet.TabletDevices) {
|
||||
if (device.Type == TabletDeviceType.Stylus) {
|
||||
// 手写笔设备存在,强制显示光标
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
canvas.UseCustomCursor = false;
|
||||
canvas.ForceCursor = false;
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
}
|
||||
}
|
||||
|
||||
// 鼠标输入
|
||||
private void inkCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
}
|
||||
|
||||
// 手写笔输入
|
||||
private void inkCanvas_StylusDown(object sender, StylusDownEventArgs e)
|
||||
{
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
}
|
||||
|
||||
// 触摸输入,不隐藏光标
|
||||
private void inkCanvas_TouchDown(object sender, TouchEventArgs e)
|
||||
{
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
}
|
||||
|
||||
// 触摸结束,恢复光标
|
||||
private void inkCanvas_TouchUp(object sender, TouchEventArgs e)
|
||||
{
|
||||
// 使用辅助方法设置光标
|
||||
SetCursorBasedOnEditingMode(inkCanvas);
|
||||
|
||||
// 确保光标可见
|
||||
if (Settings.Canvas.IsShowCursor) {
|
||||
inkCanvas.ForceCursor = true;
|
||||
inkCanvas.UseCustomCursor = true;
|
||||
System.Windows.Forms.Cursor.Show();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Definations and Loading
|
||||
|
||||
#region Navigation Sidebar Methods
|
||||
|
||||
// 侧边栏导航按钮事件处理
|
||||
private void NavStartup_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到启动设置页面
|
||||
ShowSettingsSection("startup");
|
||||
}
|
||||
|
||||
private void NavCanvas_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到画布设置页面
|
||||
ShowSettingsSection("canvas");
|
||||
}
|
||||
|
||||
private void NavGesture_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到手势设置页面
|
||||
ShowSettingsSection("gesture");
|
||||
}
|
||||
|
||||
private void NavInkRecognition_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到墨迹识别设置页面
|
||||
ShowSettingsSection("inkrecognition");
|
||||
}
|
||||
|
||||
private void NavCrashAction_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到崩溃处理设置页面
|
||||
ShowSettingsSection("crashaction");
|
||||
}
|
||||
|
||||
private void NavPPT_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到PPT设置页面
|
||||
ShowSettingsSection("ppt");
|
||||
}
|
||||
|
||||
private void NavAdvanced_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到高级设置页面
|
||||
ShowSettingsSection("advanced");
|
||||
}
|
||||
|
||||
private void NavAutomation_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到自动化设置页面
|
||||
ShowSettingsSection("automation");
|
||||
}
|
||||
|
||||
private void NavRandomWindow_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到随机窗口设置页面
|
||||
ShowSettingsSection("randomwindow");
|
||||
}
|
||||
|
||||
private void NavAbout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到关于页面
|
||||
ShowSettingsSection("about");
|
||||
}
|
||||
|
||||
// 新增:个性化设置
|
||||
private void NavTheme_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到个性化设置页面
|
||||
ShowSettingsSection("theme");
|
||||
}
|
||||
|
||||
// 新增:快捷键设置
|
||||
private void NavShortcuts_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到快捷键设置页面
|
||||
ShowSettingsSection("shortcuts");
|
||||
// 如果设置部分尚未快捷键
|
||||
MessageBox.Show("设置功能正在开发中", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private void BtnCloseSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 关闭设置面板
|
||||
BorderSettings.Visibility = Visibility.Collapsed;
|
||||
// 设置蒙版为不可点击,并清除背景
|
||||
BorderSettingsMask.IsHitTestVisible = false;
|
||||
BorderSettingsMask.Background = null; // 确保清除蒙层背景
|
||||
}
|
||||
|
||||
// 新增:折叠侧边栏
|
||||
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 折叠/展开侧边栏
|
||||
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
|
||||
if (columnDefinitions[0].Width.Value == 50)
|
||||
{
|
||||
// 折叠侧边栏
|
||||
columnDefinitions[0].Width = new GridLength(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 展开侧边栏
|
||||
columnDefinitions[0].Width = new GridLength(50);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:显示侧边栏
|
||||
private void ShowNavSidebar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 确保侧边栏展开
|
||||
var columnDefinitions = ((Grid)BorderSettings.Child).ColumnDefinitions;
|
||||
columnDefinitions[0].Width = new GridLength(50);
|
||||
}
|
||||
|
||||
// 辅助方法:显示指定的设置部分
|
||||
private void ShowSettingsSection(string sectionTag)
|
||||
{
|
||||
// 显示设置面板
|
||||
BorderSettings.Visibility = Visibility.Visible;
|
||||
// 设置蒙版为可点击,并添加半透明背景
|
||||
BorderSettingsMask.IsHitTestVisible = true;
|
||||
BorderSettingsMask.Background = new SolidColorBrush(System.Windows.Media.Color.FromArgb(1, 0, 0, 0));
|
||||
|
||||
// 获取SettingsPanelScrollViewer中的所有GroupBox
|
||||
var stackPanel = SettingsPanelScrollViewer.Content as StackPanel;
|
||||
if (stackPanel == null) return;
|
||||
|
||||
// 首先隐藏所有GroupBox
|
||||
foreach (var child in stackPanel.Children)
|
||||
{
|
||||
if (child is GroupBox groupBox)
|
||||
{
|
||||
groupBox.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据传入的sectionTag显示相应的设置部分
|
||||
switch (sectionTag.ToLower())
|
||||
{
|
||||
case "startup":
|
||||
// 显示启动设置
|
||||
ShowGroupBoxByHeader(stackPanel, "启动");
|
||||
break;
|
||||
case "canvas":
|
||||
// 显示画板和墨迹设置
|
||||
ShowGroupBoxByHeader(stackPanel, "画板和墨迹");
|
||||
break;
|
||||
case "gesture":
|
||||
// 显示手势设置
|
||||
ShowGroupBoxByHeader(stackPanel, "手势");
|
||||
break;
|
||||
case "inkrecognition":
|
||||
// 显示墨迹纠正设置
|
||||
ShowGroupBoxByHeader(stackPanel, "墨迹纠正");
|
||||
if (GroupBoxInkRecognition != null)
|
||||
GroupBoxInkRecognition.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "crashaction":
|
||||
// 显示崩溃后操作设置
|
||||
ShowGroupBoxByHeader(stackPanel, "崩溃后操作");
|
||||
break;
|
||||
case "ppt":
|
||||
// 显示PPT联动设置
|
||||
ShowGroupBoxByHeader(stackPanel, "PPT联动");
|
||||
break;
|
||||
case "advanced":
|
||||
// 显示高级设置
|
||||
// 这里可能需要根据实际情况调整
|
||||
break;
|
||||
case "automation":
|
||||
// 显示自动化设置
|
||||
// 这里可能需要根据实际情况调整
|
||||
break;
|
||||
case "randomwindow":
|
||||
// 显示随机窗口设置
|
||||
if (GroupBoxRandWindow != null)
|
||||
GroupBoxRandWindow.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "theme":
|
||||
// 显示主题设置
|
||||
if (GroupBoxAppearanceNewUI != null)
|
||||
GroupBoxAppearanceNewUI.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "shortcuts":
|
||||
// 显示快捷键设置
|
||||
// 快捷键设置部分可能尚未实现
|
||||
break;
|
||||
case "about":
|
||||
// 显示关于页面
|
||||
ShowGroupBoxByHeader(stackPanel, "关于");
|
||||
break;
|
||||
default:
|
||||
// 默认显示第一个GroupBox
|
||||
if (stackPanel.Children.Count > 0 && stackPanel.Children[0] is GroupBox firstGroupBox)
|
||||
{
|
||||
firstGroupBox.Visibility = Visibility.Visible;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 滚动到顶部
|
||||
SettingsPanelScrollViewer.ScrollToTop();
|
||||
}
|
||||
|
||||
// 根据Header文本查找并显示GroupBox
|
||||
private void ShowGroupBoxByHeader(StackPanel parent, string headerText)
|
||||
{
|
||||
foreach (var child in parent.Children)
|
||||
{
|
||||
if (child is GroupBox groupBox)
|
||||
{
|
||||
// 查找GroupBox的Header
|
||||
if (groupBox.Header is TextBlock headerTextBlock &&
|
||||
headerTextBlock.Text != null &&
|
||||
headerTextBlock.Text.Contains(headerText))
|
||||
{
|
||||
groupBox.Visibility = Visibility.Visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Navigation Sidebar Methods
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
internal class ConfigHelper
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
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}";
|
||||
|
||||
bool isLastPage = CurrentWhiteboardIndex == WhiteboardTotalCount;
|
||||
bool isMaxPage = WhiteboardTotalCount >= 99;
|
||||
|
||||
// 设置按钮文本
|
||||
BtnLeftWhiteBoardSwitchNextLabel.Text = isLastPage ? "新页面" : "下一页";
|
||||
BtnRightWhiteBoardSwitchNextLabel.Text = isLastPage ? "新页面" : "下一页";
|
||||
|
||||
// 始终允许点击“下一页/新页面”按钮(除非已达最大页数)
|
||||
BtnWhiteBoardSwitchNext.IsEnabled = !isMaxPage;
|
||||
|
||||
// 保持按钮常亮(高亮)
|
||||
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;
|
||||
|
||||
BtnWhiteBoardSwitchPrevious.IsEnabled = true;
|
||||
|
||||
if (CurrentWhiteboardIndex == 1) {
|
||||
BtnWhiteBoardSwitchPrevious.IsEnabled = false;
|
||||
BtnLeftWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
|
||||
BtnLeftWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
|
||||
BtnRightWhiteBoardSwitchPreviousGeometry.Brush = new SolidColorBrush(Color.FromArgb(127, 24, 24, 27));
|
||||
BtnRightWhiteBoardSwitchPreviousLabel.Opacity = 0.5;
|
||||
} 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;
|
||||
}
|
||||
|
||||
BtnWhiteBoardDelete.IsEnabled = WhiteboardTotalCount != 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
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;
|
||||
|
||||
// 使用统一的方法应用橡皮擦形状,确保一致性
|
||||
ApplyCurrentEraserShape();
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
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<Window>().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 { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
// 新增双重目录检查
|
||||
Directory.CreateDirectory(directory); // 防止多线程场景下的竞争条件
|
||||
bitmap.Save(savePath, ImageFormat.Png);
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException ||
|
||||
ex is UnauthorizedAccessException ||
|
||||
ex is ExternalException) { // 新增GDI+异常捕获
|
||||
// 改进备用路径处理
|
||||
var docPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||||
"Auto Saved - Screenshots",
|
||||
DateTime.Now.ToString("yyyyMMdd"),
|
||||
Path.GetFileNameWithoutExtension(savePath) + "_retry.png"); // 添加重试后缀
|
||||
|
||||
try {
|
||||
var docDir = Path.GetDirectoryName(docPath);
|
||||
Directory.CreateDirectory(docDir);
|
||||
bitmap.Save(docPath, ImageFormat.Png);
|
||||
savePath = docPath;
|
||||
}
|
||||
catch (Exception fallbackEx) {
|
||||
// 最终错误处理
|
||||
if (!isHideNotification) {
|
||||
ShowNotification($"截图保存失败: {fallbackEx.Message}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isHideNotification) {
|
||||
try {
|
||||
ShowNotification($"截图成功保存至 {savePath}");
|
||||
}
|
||||
catch {
|
||||
// 防止通知系统自身异常导致崩溃
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日期文件夹路径
|
||||
private string GetDateFolderPath(string fileName) {
|
||||
var basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Saves");
|
||||
var dateFolder = DateTime.Now.ToString("yyyyMMdd");
|
||||
var fullPath = Path.Combine(basePath, "Auto Saved - Screenshots", dateFolder);
|
||||
|
||||
try {
|
||||
if (!Directory.Exists(fullPath)) {
|
||||
Directory.CreateDirectory(fullPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when
|
||||
(ex is IOException ||
|
||||
ex is UnauthorizedAccessException)
|
||||
{
|
||||
// 如果创建失败则使用软件根目录作为最终备选
|
||||
basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
fullPath = Path.Combine(basePath, "Auto Saved - Screenshots", dateFolder);
|
||||
|
||||
Directory.CreateDirectory(fullPath);
|
||||
}
|
||||
|
||||
return Path.Combine(fullPath, $"{fileName}.png");
|
||||
}
|
||||
|
||||
private string GetDefaultFolderPath() {
|
||||
var basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Saves");
|
||||
var screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots");
|
||||
|
||||
try {
|
||||
if (!Directory.Exists(screenshotsFolder)) {
|
||||
Directory.CreateDirectory(screenshotsFolder);
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
// 如果创建失败则使用文档目录
|
||||
basePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots");
|
||||
Directory.CreateDirectory(screenshotsFolder);
|
||||
}
|
||||
|
||||
return Path.Combine(
|
||||
screenshotsFolder,
|
||||
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
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) {
|
||||
// 如果发送者是 RandomDrawPanel 或 SingleDrawPanel,且它们被隐藏,则不处理事件
|
||||
if (sender is SimpleStackPanel panel) {
|
||||
if ((panel == RandomDrawPanel || panel == SingleDrawPanel) &&
|
||||
panel.Visibility != Visibility.Visible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
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<Stroke, Tuple<DrawingAttributes, DrawingAttributes>>();
|
||||
foreach (var item in DrawingAttributesHistoryFlag)
|
||||
{
|
||||
item.Value.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GridInkCanvasSelectionCover_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) {
|
||||
// 手掌擦时禁止移动/缩放
|
||||
if (isLastTouchEraser || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint)
|
||||
return;
|
||||
// 三指及以上禁止缩放
|
||||
bool disableScale = dec.Count >= 3;
|
||||
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); // 移动
|
||||
if (!disableScale)
|
||||
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);
|
||||
}
|
||||
else {
|
||||
// 新增:启动套索选择模式
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.Select;
|
||||
inkCanvas.Select(new StrokeCollection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,999 +0,0 @@
|
||||
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<Circle> circles = new List<Circle>();
|
||||
private const double LINE_STRAIGHTEN_THRESHOLD = 0.20; // 默认灵敏度阈值,与UI默认值对应
|
||||
|
||||
private void inkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) {
|
||||
if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false;
|
||||
|
||||
try {
|
||||
inkCanvas.Opacity = 1;
|
||||
|
||||
// 应用屏蔽压感功能 - 如果启用,所有笔画都使用统一粗细
|
||||
if (Settings.Canvas.DisablePressure) {
|
||||
var uniformPoints = new StylusPointCollection();
|
||||
foreach (StylusPoint point in e.Stroke.StylusPoints) {
|
||||
StylusPoint newPoint = new StylusPoint(point.X, point.Y, 0.5f); // 统一压感值为0.5
|
||||
uniformPoints.Add(newPoint);
|
||||
}
|
||||
e.Stroke.StylusPoints = uniformPoints;
|
||||
}
|
||||
// 应用压感触屏模式 - 如果启用并且检测到触屏输入
|
||||
else if (Settings.Canvas.EnablePressureTouchMode) {
|
||||
bool isTouchInput = true;
|
||||
foreach (StylusPoint point in e.Stroke.StylusPoints) {
|
||||
// 检测是否为压感笔输入(压感笔的PressureFactor不等于0.5或0)
|
||||
if ((point.PressureFactor > 0.501 || point.PressureFactor < 0.5) && point.PressureFactor != 0) {
|
||||
isTouchInput = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是触屏输入,则应用模拟压感
|
||||
if (isTouchInput) {
|
||||
switch (Settings.Canvas.InkStyle) {
|
||||
case 1:
|
||||
if (penType == 0)
|
||||
try {
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = e.Stroke.StylusPoints.Count - 1;
|
||||
|
||||
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());
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply line straightening and endpoint snapping if ink-to-shape is enabled
|
||||
if (Settings.InkToShape.IsInkToShapeEnabled) {
|
||||
// 检查是否启用了直线自动拉直功能
|
||||
if (Settings.Canvas.AutoStraightenLine && IsPotentialStraightLine(e.Stroke)) {
|
||||
// Get start and end points of the stroke
|
||||
Point startPoint = e.Stroke.StylusPoints[0].ToPoint();
|
||||
Point endPoint = e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1].ToPoint();
|
||||
|
||||
// 记录是否需要拉直线条,默认不拉直
|
||||
bool shouldStraighten = false;
|
||||
bool snapped = false;
|
||||
|
||||
// 首先检查是否应该拉直线条(使用灵敏度设置),这是主要判断条件
|
||||
// 读取实际的灵敏度设置值
|
||||
double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
|
||||
System.Diagnostics.Debug.WriteLine($"当前灵敏度值: {sensitivity}");
|
||||
|
||||
// 将灵敏度值传递给判断函数
|
||||
shouldStraighten = ShouldStraightenLine(e.Stroke);
|
||||
|
||||
// 输出一些调试信息,帮助理解灵敏度设置的效果
|
||||
System.Diagnostics.Debug.WriteLine($"LineStraightenSensitivity: {Settings.InkToShape.LineStraightenSensitivity}, ShouldStraighten: {shouldStraighten}");
|
||||
|
||||
// 再检查端点吸附功能,这是独立的可选功能
|
||||
if (Settings.Canvas.LineEndpointSnapping) {
|
||||
// 只有在启用了形状识别(矩形或三角形)时才执行端点吸附
|
||||
if (Settings.InkToShape.IsInkToShapeRectangle || Settings.InkToShape.IsInkToShapeTriangle) {
|
||||
Point[] snappedPoints = GetSnappedEndpoints(startPoint, endPoint);
|
||||
if (snappedPoints != null) {
|
||||
startPoint = snappedPoints[0];
|
||||
endPoint = snappedPoints[1];
|
||||
snapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果满足任一条件(需要拉直或成功吸附),则创建直线
|
||||
// 这确保灵敏度设置独立于端点吸附功能发挥作用
|
||||
if (shouldStraighten || snapped) {
|
||||
StylusPointCollection straightLinePoints = CreateStraightLine(startPoint, endPoint);
|
||||
Stroke straightStroke = new Stroke(straightLinePoints) {
|
||||
DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone()
|
||||
};
|
||||
|
||||
// Replace the original stroke with the straightened one
|
||||
SetNewBackupOfStroke();
|
||||
_currentCommitType = CommitReason.ShapeRecognition;
|
||||
inkCanvas.Strokes.Remove(e.Stroke);
|
||||
inkCanvas.Strokes.Add(straightStroke);
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
|
||||
// We can't modify e.Stroke directly, but we need to update newStrokes
|
||||
// to ensure proper shape recognition for the straightened line
|
||||
if (newStrokes.Contains(e.Stroke)) {
|
||||
newStrokes.Remove(e.Stroke);
|
||||
newStrokes.Add(straightStroke);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// New method: Checks if a stroke is potentially a straight line
|
||||
private bool IsPotentialStraightLine(Stroke stroke) {
|
||||
// 确保有足够的点来进行线条分析
|
||||
if (stroke.StylusPoints.Count < 5)
|
||||
return false;
|
||||
|
||||
Point start = stroke.StylusPoints.First().ToPoint();
|
||||
Point end = stroke.StylusPoints.Last().ToPoint();
|
||||
double lineLength = GetDistance(start, end);
|
||||
|
||||
// 线条必须足够长才考虑拉直,使用设置中的阈值
|
||||
if (lineLength < Settings.Canvas.AutoStraightenLineThreshold)
|
||||
return false;
|
||||
|
||||
// 获取用户设置的灵敏度值,确保使用正确的设置
|
||||
double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
|
||||
|
||||
// 输出当前灵敏度值(调试用)
|
||||
System.Diagnostics.Debug.WriteLine($"IsPotentialStraightLine - sensitivity: {sensitivity}, length: {lineLength}");
|
||||
|
||||
// 根据灵敏度调整快速检查阈值
|
||||
double quickThreshold;
|
||||
|
||||
// 如果灵敏度超过1.0,使用更宽松的快速检查标准
|
||||
if (sensitivity > 1.0) {
|
||||
// 高灵敏度模式 - 使用更宽松的阈值
|
||||
quickThreshold = Math.Min(0.2 + (sensitivity - 1.0) * 0.3, 0.5); // 映射到0.2-0.5范围
|
||||
} else {
|
||||
// 常规灵敏度模式
|
||||
quickThreshold = Math.Min(sensitivity * 1.5, 0.20);
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"使用快速检查阈值: {quickThreshold}");
|
||||
|
||||
// 快速检查:计算几个关键点与直线的距离
|
||||
if (stroke.StylusPoints.Count >= 10) {
|
||||
// 取中点和1/4、3/4位置的点,快速检查偏差
|
||||
int quarterIdx = stroke.StylusPoints.Count / 4;
|
||||
int midIdx = stroke.StylusPoints.Count / 2;
|
||||
int threeQuarterIdx = quarterIdx * 3;
|
||||
|
||||
Point quarterPoint = stroke.StylusPoints[quarterIdx].ToPoint();
|
||||
Point midPoint = stroke.StylusPoints[midIdx].ToPoint();
|
||||
Point threeQuarterPoint = stroke.StylusPoints[threeQuarterIdx].ToPoint();
|
||||
|
||||
double quarterDeviation = DistanceFromLineToPoint(start, end, quarterPoint);
|
||||
double midDeviation = DistanceFromLineToPoint(start, end, midPoint);
|
||||
double threeQuarterDeviation = DistanceFromLineToPoint(start, end, threeQuarterPoint);
|
||||
|
||||
// 使用相对偏差:偏差与线长的比例,并使用灵敏度进行调整
|
||||
double quickRelativeThreshold = lineLength * quickThreshold;
|
||||
|
||||
// 记录检测到的偏差(调试用)
|
||||
System.Diagnostics.Debug.WriteLine($"Deviations: q={quarterDeviation}, m={midDeviation}, tq={threeQuarterDeviation}, threshold={quickRelativeThreshold}");
|
||||
|
||||
// 如果灵敏度超过1.5,则即使有一个点满足条件也认为可能是直线
|
||||
if (sensitivity > 1.5) {
|
||||
// 超高灵敏度模式:只要有一个关键点偏差小,就认为可能是直线
|
||||
if (quarterDeviation <= quickRelativeThreshold ||
|
||||
midDeviation <= quickRelativeThreshold ||
|
||||
threeQuarterDeviation <= quickRelativeThreshold) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// 常规判断:如果任一点偏离太大,直接排除
|
||||
if (quarterDeviation > quickRelativeThreshold ||
|
||||
midDeviation > quickRelativeThreshold ||
|
||||
threeQuarterDeviation > quickRelativeThreshold) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// New method: Determines if a stroke should be straightened into a line
|
||||
private bool ShouldStraightenLine(Stroke stroke) {
|
||||
// Basic implementation: check if points roughly follow a straight line
|
||||
Point start = stroke.StylusPoints.First().ToPoint();
|
||||
Point end = stroke.StylusPoints.Last().ToPoint();
|
||||
|
||||
// Calculate max deviation from the straight line between start and end
|
||||
double maxDeviation = 0;
|
||||
double lineLength = GetDistance(start, end);
|
||||
|
||||
// 如果线条太短,不进行拉直处理,使用设置中的阈值
|
||||
if (lineLength < Settings.Canvas.AutoStraightenLineThreshold) {
|
||||
// 显示调试信息 - 线条长度不足
|
||||
// MessageBox.Show($"线条太短: {lineLength} < {Settings.Canvas.AutoStraightenLineThreshold}", "调试信息");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取用户设置的灵敏度值,确保使用正确的值进行后续判断
|
||||
double sensitivity = Settings.InkToShape.LineStraightenSensitivity;
|
||||
|
||||
// 输出详细的调试信息
|
||||
System.Diagnostics.Debug.WriteLine($"ShouldStraightenLine - sensitivity: {sensitivity}, length: {lineLength}");
|
||||
|
||||
// 临时:显示调试消息框
|
||||
// MessageBox.Show($"灵敏度值: {sensitivity}", "调试信息");
|
||||
|
||||
// 计算点与直线的偏差
|
||||
double totalDeviation = 0;
|
||||
int pointCount = 0;
|
||||
|
||||
// Calculate deviation for each point
|
||||
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||
Point p = sp.ToPoint();
|
||||
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||
totalDeviation += deviation;
|
||||
pointCount++;
|
||||
}
|
||||
|
||||
// 计算平均偏差
|
||||
double avgDeviation = totalDeviation / pointCount;
|
||||
|
||||
// 更详细的调试信息
|
||||
System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}");
|
||||
|
||||
// 支持更广泛的灵敏度范围 (0.05-2.0)
|
||||
|
||||
// 如果灵敏度高于1.0,使用更宽松的判断标准
|
||||
if (sensitivity > 1.0) {
|
||||
// 高灵敏度模式 - 允许更大的偏差
|
||||
double adjustedSensitivity = 0.5 + (sensitivity - 1.0) * 1.5; // 映射到0.5-2.0范围
|
||||
|
||||
// 只判断平均偏差和相对偏差
|
||||
if (maxDeviation / lineLength < adjustedSensitivity && avgDeviation < lineLength * 0.1 * adjustedSensitivity) {
|
||||
System.Diagnostics.Debug.WriteLine("接受拉直 (高灵敏度模式)");
|
||||
return true;
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("拒绝拉直 (高灵敏度模式)");
|
||||
return false;
|
||||
}
|
||||
// 否则使用常规判断标准
|
||||
else {
|
||||
// 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲
|
||||
double deviationVariance = 0;
|
||||
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||
Point p = sp.ToPoint();
|
||||
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||
}
|
||||
deviationVariance /= pointCount;
|
||||
|
||||
// 输出更多调试信息
|
||||
System.Diagnostics.Debug.WriteLine($"Deviation variance: {deviationVariance}, Threshold: {sensitivity * lineLength * 0.05}");
|
||||
|
||||
// 如果最大偏差超过线长的阈值比例,或者偏差方差较大(表示不均匀弯曲),则不拉直
|
||||
// 灵敏度越大,容许的偏差越大,更容易将线条识别为直线
|
||||
if ((maxDeviation / lineLength) > sensitivity) {
|
||||
System.Diagnostics.Debug.WriteLine("拒绝拉直:最大偏差过大");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果偏差方差大,说明线条弯曲不均匀
|
||||
// 灵敏度越大,容许的偏差方差越大
|
||||
if (deviationVariance > (sensitivity * lineLength * 0.05)) {
|
||||
System.Diagnostics.Debug.WriteLine("拒绝拉直:偏差方差过大");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查中点偏离情况 - 针对弧形线条特别有效
|
||||
if (stroke.StylusPoints.Count > 10) {
|
||||
int midIndex = stroke.StylusPoints.Count / 2;
|
||||
Point midPoint = stroke.StylusPoints[midIndex].ToPoint();
|
||||
double midDeviation = DistanceFromLineToPoint(start, end, midPoint);
|
||||
|
||||
// 输出中点偏差信息
|
||||
System.Diagnostics.Debug.WriteLine($"Mid deviation: {midDeviation}, Threshold: {lineLength * sensitivity * 0.8}");
|
||||
|
||||
// 如果中点偏离过大,不拉直
|
||||
// 使用灵敏度作为判断基准,灵敏度越大,容许的中点偏离越大
|
||||
if (midDeviation > (lineLength * sensitivity * 0.8)) {
|
||||
System.Diagnostics.Debug.WriteLine("拒绝拉直:中点偏差过大");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("接受拉直");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// New method: Creates a straight line stroke between two points
|
||||
private StylusPointCollection CreateStraightLine(Point start, Point end) {
|
||||
StylusPointCollection points = new StylusPointCollection();
|
||||
|
||||
// 根据是否启用压感触屏模式决定如何设置压感
|
||||
// 如果未启用压感触屏模式,则使用均匀粗细
|
||||
if (!Settings.Canvas.EnablePressureTouchMode || Settings.Canvas.DisablePressure ||
|
||||
Settings.InkToShape.IsInkToShapeNoFakePressureRectangle == true || penType == 1) {
|
||||
// 使用均匀粗细(所有点压感值都是0.5f)
|
||||
points.Add(new StylusPoint(start.X, start.Y, 0.5f));
|
||||
|
||||
// 可以添加一些额外的中间点使线条更平滑(均匀粗细)
|
||||
double distance = GetDistance(start, end);
|
||||
if (distance > 100) {
|
||||
// 对于较长的线条,添加几个中间点
|
||||
for (int i = 1; i < 3; i++) {
|
||||
double ratio = i / 3.0;
|
||||
Point midPoint = new Point(
|
||||
start.X + (end.X - start.X) * ratio,
|
||||
start.Y + (end.Y - start.Y) * ratio);
|
||||
points.Add(new StylusPoint(midPoint.X, midPoint.Y, 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
points.Add(new StylusPoint(end.X, end.Y, 0.5f));
|
||||
} else {
|
||||
// 启用了压感触屏模式,使用变化的粗细(原有行为)
|
||||
points.Add(new StylusPoint(start.X, start.Y, 0.4f));
|
||||
|
||||
// 添加中点,压感值较高,使线条中间较粗
|
||||
Point midPoint = new Point((start.X + end.X) / 2, (start.Y + end.Y) / 2);
|
||||
points.Add(new StylusPoint(midPoint.X, midPoint.Y, 0.8f));
|
||||
|
||||
points.Add(new StylusPoint(end.X, end.Y, 0.4f));
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
// New method: Gets distance from point to a line defined by two points
|
||||
private double DistanceFromLineToPoint(Point lineStart, Point lineEnd, Point point) {
|
||||
// Calculate distance from point to line defined by lineStart and lineEnd
|
||||
double lineLength = GetDistance(lineStart, lineEnd);
|
||||
if (lineLength == 0) return GetDistance(point, lineStart);
|
||||
|
||||
// Calculate the cross product to get the perpendicular distance
|
||||
double distance = Math.Abs((lineEnd.Y - lineStart.Y) * point.X -
|
||||
(lineEnd.X - lineStart.X) * point.Y +
|
||||
lineEnd.X * lineStart.Y - lineEnd.Y * lineStart.X) / lineLength;
|
||||
return distance;
|
||||
}
|
||||
|
||||
// New method: Attempts to snap endpoints to existing stroke endpoints
|
||||
private Point[] GetSnappedEndpoints(Point start, Point end) {
|
||||
// 如果端点吸附功能关闭,直接返回null
|
||||
// 这里不再返回原始点,因为调用此方法的地方会判断返回值是否为null
|
||||
if (!Settings.Canvas.LineEndpointSnapping)
|
||||
return null;
|
||||
|
||||
bool startSnapped = false;
|
||||
bool endSnapped = false;
|
||||
Point snappedStart = start;
|
||||
Point snappedEnd = end;
|
||||
|
||||
// 使用设置中的吸附距离阈值
|
||||
double snapThreshold = Settings.Canvas.LineEndpointSnappingThreshold;
|
||||
|
||||
// Check all strokes in canvas for potential snap points
|
||||
foreach (Stroke stroke in inkCanvas.Strokes) {
|
||||
if (stroke.StylusPoints.Count == 0) continue;
|
||||
|
||||
// Get stroke endpoints
|
||||
Point strokeStart = stroke.StylusPoints.First().ToPoint();
|
||||
Point strokeEnd = stroke.StylusPoints.Last().ToPoint();
|
||||
|
||||
// Check if start point should snap to an endpoint
|
||||
if (!startSnapped) {
|
||||
if (GetDistance(start, strokeStart) < snapThreshold) {
|
||||
snappedStart = strokeStart;
|
||||
startSnapped = true;
|
||||
} else if (GetDistance(start, strokeEnd) < snapThreshold) {
|
||||
snappedStart = strokeEnd;
|
||||
startSnapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if end point should snap to an endpoint
|
||||
if (!endSnapped) {
|
||||
if (GetDistance(end, strokeStart) < snapThreshold) {
|
||||
snappedEnd = strokeStart;
|
||||
endSnapped = true;
|
||||
} else if (GetDistance(end, strokeEnd) < snapThreshold) {
|
||||
snappedEnd = strokeEnd;
|
||||
endSnapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If both endpoints are snapped, we're done
|
||||
if (startSnapped && endSnapped) break;
|
||||
}
|
||||
|
||||
// Return snapped points if any snapping occurred
|
||||
if (startSnapped || endSnapped) {
|
||||
return new Point[] { snappedStart, snappedEnd };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 347 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 439 B |
|
Before Width: | Height: | Size: 439 B |
|
Before Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 190 KiB |
@@ -1,84 +0,0 @@
|
||||
<Window x:Class="Ink_Canvas.HasNewUpdateWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Ink_Canvas"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
|
||||
mc:Ignorable="d"
|
||||
ui:WindowHelper.UseModernWindowStyle = "True"
|
||||
ui:WindowHelper.SystemBackdropType="Mica"
|
||||
ui:TitleBar.Height="36"
|
||||
Title="InkCanvasForClass CE有新版本可用" Height="600" Width="850" ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<Grid Background="#fafafa" Margin="0,0,0,30">
|
||||
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0">
|
||||
<!-- 标题栏 -->
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" Background="#2563eb" Margin="0,0,0,0">
|
||||
<ui:SimpleStackPanel Orientation="Vertical" Width="735" Margin="24,18,0,12" Spacing="2">
|
||||
<TextBlock Text="InkCanvasForClass CE新版本来了!" FontSize="24" FontWeight="Bold" Foreground="White" TextAlignment="Left"/>
|
||||
<TextBlock Text="希望您能喜欢我们的新版本 :-)" FontSize="20" TextAlignment="Left" Foreground="White"/>
|
||||
</ui:SimpleStackPanel>
|
||||
<Image Source="/Resources/Icons-fluent/party.png" Width="72" Height="72"/>
|
||||
</ui:SimpleStackPanel>
|
||||
|
||||
<!-- 更新内容 -->
|
||||
<Border BorderBrush="#3f3f46" Background="White" BorderThickness="1" CornerRadius="4" Margin="24,16,24,0">
|
||||
<ui:ScrollViewerEx Margin="0" VerticalScrollBarVisibility="Auto" Height="180" PanningMode="VerticalOnly">
|
||||
<mdxam:MarkdownScrollViewer x:Name="markdownContent" xml:space="preserve" Foreground="Black" MarkdownStyleName="GithubLike">
|
||||
# InkCanvasForClass v5.0.2更新
|
||||
|
||||
你好,旅行者们,本次InkCanvasForClass Community Edition更新带来了如下新功能供您探索:
|
||||
|
||||
1. 全新设计的UI界面,包括浮动工具栏和白板页面均经过重新设计,更加现代化的UI让您在使用的过程中更加舒适。
|
||||
2. 带来了实时修改橡皮大小和橡皮形状的菜单。您可以选择使用圆形橡皮,方形橡皮,和类似希沃白板的真实黑板擦(矩形)橡皮。
|
||||
3. 白板页面支持显示当前时间和日期
|
||||
4. 自动收纳新增对希沃轻白板、智绘教、鸿合屏幕书写等软件的支持,自动查杀新增对鸿合屏幕书写、希沃轻白板等软件的支持。
|
||||
5. 为设置界面重写了全新的UI。
|
||||
6. 重写了随机抽选模块,现在支持更丰富的抽选机制和自定义选项。
|
||||
7. 修复了部分小Bug,提升了整体的用户体验。
|
||||
8. 带来了基于FitToCurve的笔迹平滑,基于贝塞尔曲线平滑,让墨迹线条更加优美好看。
|
||||
</mdxam:MarkdownScrollViewer>
|
||||
</ui:ScrollViewerEx>
|
||||
</Border>
|
||||
|
||||
<!-- 版本信息 -->
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="16" Margin="0,16,0,0">
|
||||
<TextBlock x:Name="updateVersionInfo" Text="本次更新: 4.9.1 -> 5.9.1" FontWeight="Bold" FontSize="15" TextAlignment="Center"/>
|
||||
<TextBlock x:Name="updateDateInfo" Text="2024年8月4日发布更新" FontSize="15" TextAlignment="Center"/>
|
||||
</ui:SimpleStackPanel>
|
||||
|
||||
<!-- 更新按钮组 -->
|
||||
<Border Background="#f1f5f9" BorderBrush="#e2e8f0" BorderThickness="1" CornerRadius="4" Margin="24,16,24,20">
|
||||
<ui:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Center" Spacing="14" Margin="0,16,0,16">
|
||||
<TextBlock Text="请选择更新方式" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" Margin="0,0,0,6"/>
|
||||
|
||||
<!-- 立即更新按钮 -->
|
||||
<Button x:Name="UpdateNowButton" Content="立刻下载并安装" Foreground="White" FontSize="15" FontWeight="SemiBold"
|
||||
Padding="20,10" Width="360" Height="48" HorizontalAlignment="Center"
|
||||
Click="UpdateNowButton_Click" ToolTip="立即下载更新并在完成后安装" Visibility="Visible" IsEnabled="True">
|
||||
<Button.Resources>
|
||||
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundKey}" Color="#15803d"/>
|
||||
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPointerOverKey}" Color="#15803d"/>
|
||||
<SolidColorBrush x:Key="{x:Static ui:ThemeKeys.ButtonBackgroundPressedKey}" Color="#166534"/>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
|
||||
<!-- 稍后更新按钮 -->
|
||||
<Button x:Name="UpdateLaterButton" Content="下载并在软件关闭时安装" Foreground="Black" FontSize="15"
|
||||
Padding="20,10" Width="360" Height="48" HorizontalAlignment="Center"
|
||||
Click="UpdateLaterButton_Click" Background="#e2e8f0" BorderBrush="#cbd5e1"
|
||||
ToolTip="后台下载更新,在软件关闭时自动安装" Visibility="Visible" IsEnabled="True"/>
|
||||
|
||||
<!-- 跳过版本按钮 -->
|
||||
<Button x:Name="SkipVersionButton" Content="跳过该版本" HorizontalAlignment="Center" Foreground="#71717a"
|
||||
FontSize="15" Padding="20,10" Width="360" Height="48" Click="SkipVersionButton_Click"
|
||||
Background="#f8fafc" BorderBrush="#cbd5e1" ToolTip="跳过此版本更新" Visibility="Visible" IsEnabled="True"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</Border>
|
||||
</ui:SimpleStackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Window>
|
||||
@@ -1,292 +0,0 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using iNKORE.UI.WPF.Modern.Controls.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// HasNewUpdateWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
///
|
||||
|
||||
|
||||
public partial class HasNewUpdateWindow : Window
|
||||
{
|
||||
|
||||
[DllImport("dwmapi.dll")]
|
||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
|
||||
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
|
||||
private static bool UseImmersiveDarkMode(IntPtr handle, bool enabled)
|
||||
{
|
||||
if (IsWindows10OrGreater(17763))
|
||||
{
|
||||
var attribute = DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
|
||||
if (IsWindows10OrGreater(18985))
|
||||
{
|
||||
attribute = DWMWA_USE_IMMERSIVE_DARK_MODE;
|
||||
}
|
||||
|
||||
int useImmersiveDarkMode = enabled ? 1 : 0;
|
||||
return DwmSetWindowAttribute(handle, attribute, ref useImmersiveDarkMode, sizeof(int)) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsWindows10OrGreater(int build = -1)
|
||||
{
|
||||
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build;
|
||||
}
|
||||
|
||||
// 存储更新版本信息
|
||||
public string CurrentVersion { get; set; }
|
||||
public string NewVersion { get; set; }
|
||||
public string ReleaseDate { get; set; }
|
||||
public string ReleaseNotes { get; set; }
|
||||
|
||||
// 更新按钮结果
|
||||
public enum UpdateResult
|
||||
{
|
||||
UpdateNow,
|
||||
UpdateLater,
|
||||
SkipVersion
|
||||
}
|
||||
|
||||
public UpdateResult Result { get; private set; } = UpdateResult.UpdateLater;
|
||||
|
||||
public HasNewUpdateWindow(string currentVersion, string newVersion, string releaseDate, string releaseNotes = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 设置版本信息
|
||||
CurrentVersion = currentVersion;
|
||||
NewVersion = newVersion;
|
||||
ReleaseDate = releaseDate;
|
||||
ReleaseNotes = releaseNotes;
|
||||
|
||||
// 更新UI
|
||||
updateVersionInfo.Text = $"本次更新: {CurrentVersion} -> {NewVersion}";
|
||||
updateDateInfo.Text = $"{ReleaseDate}发布更新";
|
||||
|
||||
// 如果有发布说明,设置到Markdown内容中
|
||||
if (!string.IsNullOrEmpty(ReleaseNotes))
|
||||
{
|
||||
markdownContent.Markdown = ReleaseNotes;
|
||||
}
|
||||
|
||||
// 自动更新和静默更新设置已移至设置界面,此处不再需要
|
||||
|
||||
// 确保按钮可见且可用
|
||||
EnsureButtonsVisibility();
|
||||
|
||||
// 显示窗口动画
|
||||
AnimationsHelper.ShowWithFadeIn(this, 0.25);
|
||||
|
||||
// 设置深色模式
|
||||
UseImmersiveDarkMode(new WindowInteropHelper(this).Handle, true);
|
||||
|
||||
// 窗口加载完成后再次确保按钮可见
|
||||
this.Loaded += HasNewUpdateWindow_Loaded;
|
||||
}
|
||||
|
||||
private void HasNewUpdateWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 窗口加载完成后再次确保按钮可见
|
||||
EnsureButtonsVisibility();
|
||||
|
||||
// 调整窗口大小以适应屏幕分辨率
|
||||
AdjustWindowSizeForScreenResolution();
|
||||
}
|
||||
|
||||
// 确保按钮可见并启用
|
||||
private void EnsureButtonsVisibility()
|
||||
{
|
||||
// 确保立即更新按钮可见
|
||||
UpdateNowButton.Visibility = Visibility.Visible;
|
||||
UpdateNowButton.IsEnabled = true;
|
||||
|
||||
// 确保稍后更新按钮可见
|
||||
UpdateLaterButton.Visibility = Visibility.Visible;
|
||||
UpdateLaterButton.IsEnabled = true;
|
||||
|
||||
// 确保跳过版本按钮可见
|
||||
SkipVersionButton.Visibility = Visibility.Visible;
|
||||
SkipVersionButton.IsEnabled = true;
|
||||
|
||||
// 强制刷新UI
|
||||
UpdateLayout();
|
||||
|
||||
// 记录日志
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update dialog buttons visibility ensured");
|
||||
}
|
||||
|
||||
private void UpdateNowButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update Now button clicked");
|
||||
|
||||
// 设置结果为立即更新
|
||||
Result = UpdateResult.UpdateNow;
|
||||
|
||||
// 关闭窗口,返回到MainWindow处理后续下载和安装流程
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void UpdateLaterButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update Later button clicked");
|
||||
|
||||
// 设置结果为稍后更新
|
||||
Result = UpdateResult.UpdateLater;
|
||||
|
||||
// 关闭窗口
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void SkipVersionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Skip Version button clicked");
|
||||
|
||||
// 设置结果为跳过该版本
|
||||
Result = UpdateResult.SkipVersion;
|
||||
|
||||
// 关闭窗口
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 根据屏幕分辨率调整窗口大小
|
||||
private void AdjustWindowSizeForScreenResolution()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取主屏幕分辨率
|
||||
double screenWidth = SystemParameters.PrimaryScreenWidth;
|
||||
double screenHeight = SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Screen resolution: {screenWidth}x{screenHeight}");
|
||||
|
||||
// 始终确保窗口不超过屏幕大小的85%
|
||||
double maxHeight = screenHeight * 0.85;
|
||||
double maxWidth = screenWidth * 0.85;
|
||||
|
||||
bool needsAdjustment = false;
|
||||
|
||||
// 如果窗口高度超过最大允许高度,调整窗口高度
|
||||
if (this.Height > maxHeight)
|
||||
{
|
||||
this.Height = maxHeight;
|
||||
needsAdjustment = true;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window height to: {this.Height}");
|
||||
}
|
||||
|
||||
// 如果窗口宽度超过最大允许宽度,调整窗口宽度
|
||||
if (this.Width > maxWidth)
|
||||
{
|
||||
this.Width = maxWidth;
|
||||
needsAdjustment = true;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Adjusted window width to: {this.Width}");
|
||||
}
|
||||
|
||||
// 如果屏幕分辨率较低,调整更多UI元素
|
||||
if (screenHeight < 768 || screenWidth < 1024 || needsAdjustment)
|
||||
{
|
||||
// 查找相关控件并调整大小
|
||||
var markdownViewer = this.FindName("markdownContent") as MdXaml.MarkdownScrollViewer;
|
||||
var updateNowButton = this.FindName("UpdateNowButton") as Button;
|
||||
var updateLaterButton = this.FindName("UpdateLaterButton") as Button;
|
||||
var skipVersionButton = this.FindName("SkipVersionButton") as Button;
|
||||
|
||||
// 查找包含ScrollViewer的边框控件,减小其高度
|
||||
var contentBorders = this.FindVisualChildren<Border>().ToList();
|
||||
foreach (var border in contentBorders)
|
||||
{
|
||||
if (border.Child is ScrollViewer || border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx)
|
||||
{
|
||||
// 减小内容显示区域的高度
|
||||
if (border.Height > 180)
|
||||
{
|
||||
border.Height = 160;
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Reduced content area height");
|
||||
}
|
||||
else if (border.Child is iNKORE.UI.WPF.Modern.Controls.ScrollViewerEx scrollViewer && scrollViewer.Height > 160)
|
||||
{
|
||||
scrollViewer.Height = 160;
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Reduced scroll viewer height");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 调整按钮大小
|
||||
if (updateNowButton != null && updateLaterButton != null && skipVersionButton != null)
|
||||
{
|
||||
updateNowButton.Height = 42;
|
||||
updateLaterButton.Height = 42;
|
||||
skipVersionButton.Height = 42;
|
||||
updateNowButton.Padding = new Thickness(15, 8, 15, 8);
|
||||
updateLaterButton.Padding = new Thickness(15, 8, 15, 8);
|
||||
skipVersionButton.Padding = new Thickness(15, 8, 15, 8);
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Reduced button sizes for small screen");
|
||||
}
|
||||
}
|
||||
|
||||
// 确保窗口在屏幕范围内
|
||||
if (this.Left < 0) this.Left = 0;
|
||||
if (this.Top < 0) this.Top = 0;
|
||||
if (this.Left + this.Width > screenWidth) this.Left = screenWidth - this.Width;
|
||||
if (this.Top + this.Height > screenHeight) this.Top = screenHeight - this.Height;
|
||||
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Final window size: {this.Width}x{this.Height}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error adjusting window size: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// 递归查找指定类型的所有子控件
|
||||
private IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj = null) where T : DependencyObject
|
||||
{
|
||||
if (depObj == null)
|
||||
depObj = this;
|
||||
|
||||
if (depObj != null)
|
||||
{
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
|
||||
if (child != null && child is T)
|
||||
{
|
||||
yield return (T)child;
|
||||
}
|
||||
|
||||
foreach (T childOfChild in FindVisualChildren<T>(child))
|
||||
{
|
||||
yield return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{693973B6-69C1-4A37-B329-F366A07BF60A}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>InkCanvasForClass.IACoreHelper</RootNamespace>
|
||||
<AssemblyName>InkCanvasForClass.IACoreHelper</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace InkCanvasForClass.IACoreHelper {
|
||||
internal class Program {
|
||||
static void Main(string[] args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("InkCanvasForClass.IACoreHelper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("InkCanvasForClass.IACoreHelper")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("693973b6-69c1-4a37-b329-f366a07bf60a")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,3 @@
|
||||
# InkCanvasForClass.IACoreHelper
|
||||
|
||||
该项目实现了基于 .NET Framework 4.7.2 和 x86 运行环境的墨迹识别库 IACore 的封装
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -0,0 +1,9 @@
|
||||
<Application x:Class="InkCanvasForClass.IccInkCanvas.Demo.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:InkCanvasForClass.IccInkCanvas.Demo"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas.Demo {
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{94E97F70-CACD-453B-8114-08DFFDDA5A46}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>InkCanvasForClass.IccInkCanvas.Demo</RootNamespace>
|
||||
<AssemblyName>InkCanvasForClass.IccInkCanvas.Demo</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\InkCanvasForClass.IccInkCanvas\InkCanvasForClass.IccInkCanvas.csproj">
|
||||
<Project>{43929d8f-5630-4786-b75d-e203ea3e992f}</Project>
|
||||
<Name>InkCanvasForClass.IccInkCanvas</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,71 @@
|
||||
<Window x:Class="InkCanvasForClass.IccInkCanvas.Demo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:InkCanvasForClass.IccInkCanvas.Demo"
|
||||
xmlns:iccInkCanvas="clr-namespace:InkCanvasForClass.IccInkCanvas;assembly=InkCanvasForClass.IccInkCanvas"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="950" Width="800">
|
||||
<Grid>
|
||||
<TabControl>
|
||||
<TabItem Header="IccInkCanvasOld">
|
||||
<StackPanel Orientation="Vertical" Margin="8">
|
||||
<TextBlock FontSize="24">IccInkCanvasDemo</TextBlock>
|
||||
<iccInkCanvas:IccBoard EditingMode="None" Name="IccBoard" Width="512" Height="512"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="EditingMode = None" Click="EditingModeChangeToNone_ButtonClick"/>
|
||||
<Button Content="EditingMode = Writing" Click="EditingModeChangeToWriting_ButtonClick"/>
|
||||
<Button Content="EditingMode = GeometryErasing" Click="EditingModeChangeToGeometryErasing_ButtonClick"/>
|
||||
<Button Content="EditingMode = AreaErasing" Click="EditingModeChangeToAreaErasing_ButtonClick"/>
|
||||
<Button Content="EditingMode = RoamingMode" Click="EditingModeChangeToRoamingMode_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
<TextBlock Name="BoardSettingsTextBlock"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="BoardSettings.NibSize = 2" Click="BoardSettingsNibSizeChangeTo2_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibSize = 4" Click="BoardSettingsNibSizeChangeTo4_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibSize = 6" Click="BoardSettingsNibSizeChangeTo6_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibColor = Red" Click="BoardSettingsNibColorChangeToRed_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibColor = Blue" Click="BoardSettingsNibColorChangeToBlue_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibColor = Green" Click="BoardSettingsNibColorChangeToGreen_ButtonClick"/>
|
||||
<Button Content="BoardSettings.NibColor = Black" Click="BoardSettingsNibColorChangeToBlack_ButtonClick"/>
|
||||
<Button Content="BoardSettings.StrokeNibStyle = Solid" Click="BoardSettingsStrokeNibStyleChangeToSolid_ButtonClick"/>
|
||||
<Button Content="BoardSettings.StrokeNibStyle = Beautiful" Click="BoardSettingsStrokeNibStyleChangeToBeautiful_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
<TextBlock Name="BoardPageTextBlock"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="AddPage" Click="AddPage_ButtonClick"/>
|
||||
<Button Content="SwitchToPreviousPage" Click="SwitchToPreviousPage_ButtonClick"/>
|
||||
<Button Content="SwitchToNextPage" Click="SwitchToNextPage_ButtonClick"/>
|
||||
<Button Content="RemoveCurrentPage" Click="RemoveCurrentPage_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="BoardSettings.EraserSize = 16" Click="BoardSettingsEraserSizeChangeTo16_ButtonClick"/>
|
||||
<Button Content="BoardSettings.EraserSize = 32" Click="BoardSettingsEraserSizeChangeTo32_ButtonClick"/>
|
||||
<Button Content="BoardSettings.EraserSize = 48" Click="BoardSettingsEraserSizeChangeTo48_ButtonClick"/>
|
||||
<Button Content="BoardSettings.EraserSize = 64" Click="BoardSettingsEraserSizeChangeTo64_ButtonClick"/>
|
||||
<Button Content="BoardSettings.EraserType = Rectangle" Click="BoardSettingsEraserTypeChangeToRectangle_ButtonClick"/>
|
||||
<Button Content="BoardSettings.EraserType = Ellipse" Click="BoardSettingsEraserTypeChangeToEllipse_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
<TextBlock Name="TimeMachineTextBlock"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="Undo" Click="Undo_ButtonClick"/>
|
||||
<Button Content="Undo 2" Click="Undo2_ButtonClick"/>
|
||||
<Button Content="Redo" Click="Redo_ButtonClick"/>
|
||||
<Button Content="Redo 2" Click="Redo2_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
<TextBlock Text="TimeMachineV2 Test"/>
|
||||
<TextBlock Name="TimeMachineV2Status"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Content="PushTestAction" Click="PushTestAction_TimeMachineV2_ButtonClick"/>
|
||||
<Button Content="Undo" Click="Undo_TimeMachineV2_ButtonClick"/>
|
||||
<Button Content="Redo" Click="Redo_TimeMachineV2_ButtonClick"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
<TabItem Header="IccInkCanvasNew">
|
||||
<iccInkCanvas:InkBoard Width="269" Height="269"/>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using InkCanvasForClass.IccInkCanvas.Settings;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas.Demo {
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window {
|
||||
private TimeMachineV2 tm = new TimeMachineV2();
|
||||
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
RegisterEventsForBoardSettings();
|
||||
UpdateBoardSettingsTextBlock();
|
||||
|
||||
IccBoard.CurrentPageChanged += (sender, args) => {
|
||||
Trace.WriteLine("Page Counter Updated");
|
||||
BoardPageTextBlock.Text = $"{IccBoard.CurrentPage+1}/{IccBoard.PagesCount} IsLast:{IccBoard.IsCurrentLastPage} IsFirst:{IccBoard.IsCurrentFirstPage}";
|
||||
};
|
||||
IccBoard.UndoRedoStateChanged += (sender, args) => {
|
||||
TimeMachineTextBlock.Text = $"CurrentPageHistoriesCount:{IccBoard.CurrentPageHistoriesCount} CanUndo:{IccBoard.CanUndo} CanRedo:{IccBoard.CanRedo}";
|
||||
};
|
||||
|
||||
TimeMachineV2Status.Text = $"Current: {tm.CurrentIndex} Count: {tm.ActionsCount}";
|
||||
tm.UndoRedoStateChanged += (_, __) => {
|
||||
TimeMachineV2Status.Text = $"Current: {tm.CurrentIndex} Count: {tm.ActionsCount}";
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateBoardSettingsTextBlock() {
|
||||
BoardSettingsTextBlock.Text =
|
||||
$@"Width:{IccBoard.BoardSettings.NibWidth} Height:{IccBoard.BoardSettings.NibHeight} Color:{IccBoard.BoardSettings.NibColor.ToString()}";
|
||||
}
|
||||
|
||||
private void RegisterEventsForBoardSettings() {
|
||||
IccBoard.BoardSettings.NibWidthChanged += (s, e) => UpdateBoardSettingsTextBlock();
|
||||
IccBoard.BoardSettings.NibHeightChanged += (s, e) => UpdateBoardSettingsTextBlock();
|
||||
IccBoard.BoardSettings.NibColorChanged += (s, e) => UpdateBoardSettingsTextBlock();
|
||||
}
|
||||
|
||||
private void EditingModeChangeToNone_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.EditingMode = EditingMode.NoneWithHitTest;
|
||||
}
|
||||
private void EditingModeChangeToWriting_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.EditingMode = EditingMode.Writing;
|
||||
}
|
||||
private void EditingModeChangeToGeometryErasing_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.EditingMode = EditingMode.GeometryErasing;
|
||||
}
|
||||
private void EditingModeChangeToAreaErasing_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.EditingMode = EditingMode.AreaErasing;
|
||||
}
|
||||
private void EditingModeChangeToRoamingMode_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.EditingMode = EditingMode.RoamingMode;
|
||||
}
|
||||
private void BoardSettingsNibSizeChangeTo2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibWidth = 2;
|
||||
IccBoard.BoardSettings.NibHeight = 2;
|
||||
}
|
||||
private void BoardSettingsNibSizeChangeTo4_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibWidth = 4;
|
||||
IccBoard.BoardSettings.NibHeight = 4;
|
||||
}
|
||||
private void BoardSettingsNibSizeChangeTo6_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibWidth = 6;
|
||||
IccBoard.BoardSettings.NibHeight = 6;
|
||||
}
|
||||
private void BoardSettingsNibColorChangeToRed_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibColor = Color.FromRgb(220, 38, 38);
|
||||
}
|
||||
private void BoardSettingsNibColorChangeToBlue_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibColor = Color.FromRgb(37, 99, 235);
|
||||
}
|
||||
private void BoardSettingsNibColorChangeToGreen_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibColor = Color.FromRgb(34, 197, 94);
|
||||
}
|
||||
private void BoardSettingsNibColorChangeToBlack_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.NibColor = Colors.Black;
|
||||
}
|
||||
private void BoardSettingsStrokeNibStyleChangeToSolid_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.StrokeNibStyle = StrokeNibStyle.Solid;
|
||||
}
|
||||
private void BoardSettingsStrokeNibStyleChangeToBeautiful_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.StrokeNibStyle = StrokeNibStyle.Beautiful;
|
||||
}
|
||||
private void AddPage_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.AddPage();
|
||||
}
|
||||
private void SwitchToPreviousPage_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.GoToPreviousPage();
|
||||
}
|
||||
private void SwitchToNextPage_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.GoToNextPage();
|
||||
}
|
||||
private async void RemoveCurrentPage_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
await IccBoard.RemovePage();
|
||||
}
|
||||
private void BoardSettingsEraserSizeChangeTo16_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserSize = 16;
|
||||
}
|
||||
private void BoardSettingsEraserSizeChangeTo32_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserSize = 32;
|
||||
}
|
||||
private void BoardSettingsEraserSizeChangeTo48_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserSize = 48;
|
||||
}
|
||||
private void BoardSettingsEraserSizeChangeTo64_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserSize = 64;
|
||||
}
|
||||
private void BoardSettingsEraserTypeChangeToRectangle_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserType = EraserType.Rectangle;
|
||||
}
|
||||
private void BoardSettingsEraserTypeChangeToEllipse_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.BoardSettings.EraserType = EraserType.Ellipse;
|
||||
}
|
||||
|
||||
private void Undo_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.Undo();
|
||||
}
|
||||
private void Redo_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.Redo();
|
||||
}
|
||||
private void Undo2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.Undo(2);
|
||||
}
|
||||
private void Redo2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
IccBoard.Redo(2);
|
||||
}
|
||||
|
||||
private void PushTestAction_TimeMachineV2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
tm.PushTestAction();
|
||||
}
|
||||
|
||||
private void Undo_TimeMachineV2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
tm.Undo(false);
|
||||
}
|
||||
private void Redo_TimeMachineV2_ButtonClick(object sender, RoutedEventArgs e) {
|
||||
tm.Redo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("InkCanvasForClass.IccInkCanvas.Demo")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("InkCanvasForClass.IccInkCanvas.Demo")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//若要开始生成可本地化的应用程序,请设置
|
||||
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||
//在 <PropertyGroup> 中。例如,如果你使用的是美国英语。
|
||||
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,62 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能导致不正确的行为,如果
|
||||
// 重新生成代码,则所做更改将丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas.Demo.Properties {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强类型资源类,用于查找本地化字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.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() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if ((resourceMan == null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("InkCanvasForClass.IccInkCanvas.Demo.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 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.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas.Demo.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using InkCanvasForClass.IccInkCanvas.Utils.Threading;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas {
|
||||
|
||||
/// <summary>
|
||||
/// 基于 InkPresenter 优化和魔改的 InkBoard 控件
|
||||
/// </summary>
|
||||
public class InkBoard : FrameworkElement {
|
||||
private readonly VisualCollection _children;
|
||||
// Tuple 1为Dispatcher的Guid,2为对应Dispatcher
|
||||
private List<Tuple<Guid, Dispatcher>> _asyncDispatchers;
|
||||
|
||||
private const int HalfIntMax = 1073741823;
|
||||
private const float HalfFloatMax = 1073741823f;
|
||||
private const int QuarterSInt = 536756397;
|
||||
private const float QuarterSFloat = 536756397f;
|
||||
|
||||
public InkBoard() {
|
||||
VisualCacheMode = new BitmapCache(0);
|
||||
ClipToBounds = true;
|
||||
_children = new VisualCollection(this);
|
||||
|
||||
test();
|
||||
|
||||
}
|
||||
|
||||
#region Dispatchers 管理
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个 Dispatcher
|
||||
/// </summary>
|
||||
/// <param name="customWorkerDispatcherName">如果可用,会使用这个名字创建Dispatcher(但是不会忽略GUID)</param>
|
||||
/// <returns>Tuple,1为Guid,2为Dispatcher</returns>
|
||||
private async Task<Tuple<Guid, Dispatcher>> CreateDispathcer(string customWorkerDispatcherName = "IccInkCanvas") {
|
||||
var guid = Guid.NewGuid();
|
||||
var dispatcher = await UIDispatcher.RunNewAsync($"{customWorkerDispatcherName}_" + guid);
|
||||
return new Tuple<Guid, Dispatcher>(guid, dispatcher);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册一个新的 Dispatcher,这将会把 Dispatcher 给记录到 _asyncDispatchers 中
|
||||
/// </summary>
|
||||
/// <param name="customWorkerDispatcherName">如果可用,会使用这个名字创建Dispatcher(但是不会忽略GUID)</param>
|
||||
private async void RegisterNewDispatcher(string customWorkerDispatcherName = "IccInkCanvas") {
|
||||
var dispatcher = await CreateDispathcer(customWorkerDispatcherName);
|
||||
_asyncDispatchers.Add(dispatcher);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 让一个 Dispatcher 停止工作并销毁
|
||||
/// </summary>
|
||||
/// <param name="dispatcher"></param>
|
||||
private void DisposeDispatcher(Dispatcher dispatcher) {
|
||||
dispatcher.BeginInvokeShutdown(DispatcherPriority.Send);
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断一个 Dispatcher 是否被挂起
|
||||
/// </summary>
|
||||
/// <param name="dispatcher"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task<bool> CheckDispatcherHangAsync(Dispatcher dispatcher)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<bool>();
|
||||
_ = dispatcher.InvokeAsync(() => taskCompletionSource.TrySetResult(true));
|
||||
await Task.WhenAny(taskCompletionSource.Task, Task.Delay(TimeSpan.FromMilliseconds(1500)));
|
||||
return taskCompletionSource.Task.IsCompleted is false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 创建跨线程 InkPresenter,使用传入的 Dispatcher
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task CreateInkPresenterWithDispatcher() {
|
||||
await UIDispatcher.RunNewAsync("IccInkCanvas_" + Guid.NewGuid());
|
||||
}
|
||||
|
||||
private async Task test() {
|
||||
var di = new IccDispatcherInkCanvasInfo();
|
||||
await di.InitDispatcher();
|
||||
var control = await di.Dispatcher.InvokeAsync(() => new TextBlock() {
|
||||
Text = "Helloworld!",
|
||||
Foreground = new SolidColorBrush(Colors.Black),
|
||||
FontSize = 24,
|
||||
});
|
||||
var dc = new DispatcherContainer();
|
||||
await dc.SetChildAsync(control);
|
||||
_children.Add(dc);
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
protected override int VisualChildrenCount {
|
||||
get { return _children.Count; }
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index) {
|
||||
if (index < 0 || index >= _children.Count) new ArgumentOutOfRangeException();
|
||||
return _children[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<UserControl x:Class="InkCanvasForClass.IccInkCanvas.IccBoard"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:InkCanvasForClass.IccInkCanvas"
|
||||
mc:Ignorable="d" d:DesignHeight="512" d:DesignWidth="512">
|
||||
<UserControl.Resources>
|
||||
<DrawingImage x:Key="RectangleEraserImageSource">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V56 H38 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FFF2EEEB" Geometry="F1 M38,56z M0,0z M0,4C0,1.79086,1.79086,0,4,0L34,0C36.2091,0,38,1.79086,38,4L38,52C38,54.2091,36.2091,56,34,56L4,56C1.79086,56,0,54.2091,0,52L0,4z" />
|
||||
<GeometryDrawing Brush="#FFCDCDCD" Geometry="F0 M38,56z M0,0z M34,1L4,1C2.34315,1,1,2.34315,1,4L1,52C1,53.6569,2.34315,55,4,55L34,55C35.6569,55,37,53.6569,37,52L37,4C37,2.34315,35.6569,1,34,1z M4,0C1.79086,0,0,1.79086,0,4L0,52C0,54.2091,1.79086,56,4,56L34,56C36.2091,56,38,54.2091,38,52L38,4C38,1.79086,36.2091,0,34,0L4,0z" />
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M38,56z M0,0z M12,19.5C12,18.1193,13.1193,17,14.5,17L14.5,17C15.8807,17,17,18.1193,17,19.5L17,36.5C17,37.8807,15.8807,39,14.5,39L14.5,39C13.1193,39,12,37.8807,12,36.5L12,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M38,56z M0,0z M11.5,19.5C11.5,17.8431 12.8431,16.5 14.5,16.5 16.1569,16.5 17.5,17.8431 17.5,19.5L17.5,36.5C17.5,38.1569 16.1569,39.5 14.5,39.5 12.8431,39.5 11.5,38.1569 11.5,36.5L11.5,19.5z M14.5,17.5C13.3954,17.5,12.5,18.3954,12.5,19.5L12.5,36.5C12.5,37.6046 13.3954,38.5 14.5,38.5 15.6046,38.5 16.5,37.6046 16.5,36.5L16.5,19.5C16.5,18.3954,15.6046,17.5,14.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M38,56z M0,0z M21,19.5C21,18.1193,22.1193,17,23.5,17L23.5,17C24.8807,17,26,18.1193,26,19.5L26,36.5C26,37.8807,24.8807,39,23.5,39L23.5,39C22.1193,39,21,37.8807,21,36.5L21,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M38,56z M0,0z M20.5,19.5C20.5,17.8431 21.8431,16.5 23.5,16.5 25.1569,16.5 26.5,17.8431 26.5,19.5L26.5,36.5C26.5,38.1569 25.1569,39.5 23.5,39.5 21.8431,39.5 20.5,38.1569 20.5,36.5L20.5,19.5z M23.5,17.5C22.3954,17.5,21.5,18.3954,21.5,19.5L21.5,36.5C21.5,37.6046 22.3954,38.5 23.5,38.5 24.6046,38.5 25.5,37.6046 25.5,36.5L25.5,19.5C25.5,18.3954,24.6046,17.5,23.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
<DrawingImage x:Key="EllipseEraserImageSource">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V56 H56 V0 H0 Z">
|
||||
<GeometryDrawing Brush="#FFF2EEEB" Geometry="F1 M56,56z M0,0z M0,28C0,12.536,12.536,0,28,0L28,0C43.464,0,56,12.536,56,28L56,28C56,43.464,43.464,56,28,56L28,56C12.536,56,0,43.464,0,28L0,28z" />
|
||||
<GeometryDrawing Brush="#FFCDCDCD" Geometry="F0 M56,56z M0,0z M1,28C1,42.9117 13.0883,55 28,55 42.9117,55 55,42.9117 55,28 55,13.0883 42.9117,1 28,1 13.0883,1 1,13.0883 1,28z M28,0C12.536,0 0,12.536 0,28 0,43.464 12.536,56 28,56 43.464,56 56,43.464 56,28 56,12.536 43.464,0 28,0z" />
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M56,56z M0,0z M21,19.5C21,18.1193,22.1193,17,23.5,17L23.5,17C24.8807,17,26,18.1193,26,19.5L26,36.5C26,37.8807,24.8807,39,23.5,39L23.5,39C22.1193,39,21,37.8807,21,36.5L21,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M56,56z M0,0z M20.5,19.5C20.5,17.8431 21.8431,16.5 23.5,16.5 25.1569,16.5 26.5,17.8431 26.5,19.5L26.5,36.5C26.5,38.1569 25.1569,39.5 23.5,39.5 21.8431,39.5 20.5,38.1569 20.5,36.5L20.5,19.5z M23.5,17.5C22.3954,17.5,21.5,18.3954,21.5,19.5L21.5,36.5C21.5,37.6046 22.3954,38.5 23.5,38.5 24.6046,38.5 25.5,37.6046 25.5,36.5L25.5,19.5C25.5,18.3954,24.6046,17.5,23.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FFD1CFCD" Geometry="F1 M56,56z M0,0z M30,19.5C30,18.1193,31.1193,17,32.5,17L32.5,17C33.8807,17,35,18.1193,35,19.5L35,36.5C35,37.8807,33.8807,39,32.5,39L32.5,39C31.1193,39,30,37.8807,30,36.5L30,19.5z" />
|
||||
<GeometryDrawing Geometry="F0 M56,56z M0,0z M29.5,19.5C29.5,17.8431 30.8431,16.5 32.5,16.5 34.1569,16.5 35.5,17.8431 35.5,19.5L35.5,36.5C35.5,38.1569 34.1569,39.5 32.5,39.5 30.8431,39.5 29.5,38.1569 29.5,36.5L29.5,19.5z M32.5,17.5C31.3954,17.5,30.5,18.3954,30.5,19.5L30.5,36.5C30.5,37.6046 31.3954,38.5 32.5,38.5 33.6046,38.5 34.5,37.6046 34.5,36.5L34.5,19.5C34.5,18.3954,33.6046,17.5,32.5,17.5z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FF6F6F6F" Opacity="0.25" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
</UserControl.Resources>
|
||||
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}">
|
||||
<Canvas Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}"
|
||||
ClipToBounds="True" x:Name="InkCanvasHostCanvas" x:FieldModifier="private" Loaded="HostCanvas_Loaded" SizeChanged="HostCanvas_SizeChanged">
|
||||
<Canvas.Clip>
|
||||
<CombinedGeometry GeometryCombineMode="Exclude" x:Name="HostCanvasClipGeometry" x:FieldModifier="private">
|
||||
<CombinedGeometry.Geometry1>
|
||||
<RectangleGeometry x:Name="HostCanvasClipGeometry1" x:FieldModifier="private"/>
|
||||
</CombinedGeometry.Geometry1>
|
||||
</CombinedGeometry>
|
||||
</Canvas.Clip>
|
||||
</Canvas>
|
||||
<Canvas Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}"
|
||||
ClipToBounds="True" x:Name="InkCanvasWrapperCanvas" x:FieldModifier="private" Visibility="Visible">
|
||||
<local:IccInkCanvas x:Name="WrapperInkCanvas" Background="Transparent" x:FieldModifier="private" Loaded="WrapperInkCanvas_Loaded">
|
||||
<local:IccInkCanvas.RenderTransform>
|
||||
<MatrixTransform x:Name="WrapperInkCanvasMatrixTransform" x:FieldModifier="private"/>
|
||||
</local:IccInkCanvas.RenderTransform>
|
||||
</local:IccInkCanvas>
|
||||
</Canvas>
|
||||
<Canvas Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}"
|
||||
ClipToBounds="True" Loaded="EraserOverlayCanvas_Loaded" x:Name="EraserCanvas" Background="Transparent" x:FieldModifier="private">
|
||||
<Image Canvas.Left="0" Canvas.Top="0" RenderTransformOrigin="0,0" Width="0" x:Name="EraserFeedback" x:FieldModifier="private">
|
||||
<Image.RenderTransform>
|
||||
<TranslateTransform x:Name="EraserFeedbackTranslateTransform" x:FieldModifier="private"/>
|
||||
</Image.RenderTransform>
|
||||
</Image>
|
||||
</Canvas>
|
||||
<Canvas Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}"
|
||||
ClipToBounds="True" Loaded="RectangleAreaEraserCanvas_Loaded" x:Name="RectangleAreaEraserCanvas" Background="Transparent" x:FieldModifier="private">
|
||||
<Border Visibility="Collapsed" x:Name="AreaErasingFeedback" x:FieldModifier="private" Width="128" Height="128" BorderBrush="#9971717a" BorderThickness="1" Background="#3371717a">
|
||||
<Border VerticalAlignment="Center" HorizontalAlignment="Center" Width="68" Height="22" CornerRadius="10" Background="#b91c1c">
|
||||
<TextBlock Margin="8,2" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White">区域擦除</TextBlock>
|
||||
</Border>
|
||||
</Border>
|
||||
</Canvas>
|
||||
<Border Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}}, Path=ActualHeight}"
|
||||
x:Name="RoamingHitTestBorder" x:FieldModifier="private" Background="Transparent" Loaded="RoamingHitTestBorder_Loaded"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,21 @@
|
||||
using InkCanvasForClass.IccInkCanvas.Utils.Threading;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas {
|
||||
public class IccBoardPage {
|
||||
public Guid GUID { get; set; }
|
||||
public Dispatcher Dispatcher { get; set; }
|
||||
public DispatcherContainer Container { get; set; }
|
||||
public InkCanvas InkCanvas { get; set; }
|
||||
public TimeMachine TimeMachine { get; set; } = new TimeMachine();
|
||||
public long LastStrokeID { get; set; } = 0;
|
||||
public Matrix TransformMatrix { get; set; } = new Matrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using InkCanvasForClass.IccInkCanvas.Utils.Threading;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas {
|
||||
public class IccDispatcherInkCanvasInfo {
|
||||
|
||||
public Dispatcher Dispatcher { get; private set; }
|
||||
|
||||
public Guid GUID { get; private set; } = Guid.NewGuid();
|
||||
|
||||
public async Task InitDispatcher() {
|
||||
Dispatcher = await UIDispatcher.RunNewAsync("IccInkCanvas_" + GUID.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
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.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Input.StylusPlugIns;
|
||||
using System.Windows.Media;
|
||||
using InkCanvasForClass.IccInkCanvas.Settings;
|
||||
|
||||
namespace InkCanvasForClass.IccInkCanvas {
|
||||
class CustomDynamicRenderer : DynamicRenderer {
|
||||
|
||||
private class StylusProcessedCallbackData {
|
||||
public int StylusDeviceID;
|
||||
public int TabletDeviceID;
|
||||
}
|
||||
|
||||
private Point prevPoint;
|
||||
|
||||
private IccInkCanvas _inkCanvas;
|
||||
|
||||
private List<StylusPoint> pointsList = new List<StylusPoint>();
|
||||
|
||||
private StylusProcessedCallbackData _stylusProcessedCallbackData;
|
||||
|
||||
public InputtingDeviceType InputType = InputtingDeviceType.None;
|
||||
|
||||
private void ClearPointsList() {
|
||||
pointsList.Clear();
|
||||
}
|
||||
|
||||
private void PushPoint(StylusPoint point) {
|
||||
pointsList.Add(point);
|
||||
if (pointsList.Count > 15) {
|
||||
pointsList.RemoveRange(0,pointsList.Count - 15);
|
||||
}
|
||||
}
|
||||
|
||||
public CustomDynamicRenderer(IccInkCanvas iccInkCanvas) {
|
||||
_inkCanvas = iccInkCanvas;
|
||||
}
|
||||
|
||||
protected override void OnStylusDown(RawStylusInput rawStylusInput) {
|
||||
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
|
||||
ClearPointsList();
|
||||
|
||||
// 判断当前设备类型
|
||||
var styDevice = rawStylusInput.StylusDeviceId;
|
||||
var tabletDevice = rawStylusInput.TabletDeviceId;
|
||||
|
||||
var pts = rawStylusInput.GetStylusPoints();
|
||||
if (pts.Count == 1) {
|
||||
PushPoint(pts.Single());
|
||||
} else if (pts.Count > 1) {
|
||||
PushPoint(pts[pts.Count-1]);
|
||||
}
|
||||
|
||||
base.OnStylusDown(rawStylusInput);
|
||||
|
||||
_stylusProcessedCallbackData = new StylusProcessedCallbackData() {
|
||||
StylusDeviceID = styDevice,
|
||||
TabletDeviceID = tabletDevice,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnStylusDownProcessed(object callbackData, bool targetVerified) {
|
||||
var data = _stylusProcessedCallbackData;
|
||||
var tabletDevices = Tablet.TabletDevices;
|
||||
if (data.StylusDeviceID == 0 && data.TabletDeviceID == 0) InputType = InputtingDeviceType.Mouse;
|
||||
foreach (TabletDevice tabletDevice in tabletDevices) {
|
||||
if (tabletDevice.Id == data.TabletDeviceID && tabletDevice.Type == TabletDeviceType.Stylus)
|
||||
InputType = InputtingDeviceType.Stylus;
|
||||
if (tabletDevice.Id == data.TabletDeviceID && tabletDevice.Type == TabletDeviceType.Touch)
|
||||
InputType = InputtingDeviceType.Touch;
|
||||
}
|
||||
|
||||
base.OnStylusDownProcessed(callbackData, targetVerified);
|
||||
}
|
||||
|
||||
protected override void OnStylusMove(RawStylusInput rawStylusInput) {
|
||||
base.OnStylusMove(rawStylusInput);
|
||||
var pts = rawStylusInput.GetStylusPoints();
|
||||
if (pts.Count == 1) {
|
||||
PushPoint(pts.Single());
|
||||
} else if (pts.Count > 1) {
|
||||
if (InputType != InputtingDeviceType.Stylus) PushPoint(pts[pts.Count-1]);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStylusUpProcessed(object callbackData, bool targetVerified) {
|
||||
//InputType = InputtingDeviceType.None;
|
||||
// TODO: 触摸支持
|
||||
base.OnStylusUpProcessed(callbackData, targetVerified);
|
||||
}
|
||||
|
||||
private void DrawBeautifulNibStroke(DrawingContext drawingContext) {
|
||||
try {
|
||||
var sp = new StylusPointCollection();
|
||||
var n = pointsList.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 = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.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 = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.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 = pointsList[i].X;
|
||||
point.Y = pointsList[i].Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
var da = DrawingAttributes.Clone();
|
||||
da.Width -= 0.5;
|
||||
da.Height -= 0.5;
|
||||
var stk = new Stroke(sp, da);
|
||||
stk.Draw(drawingContext);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private void DrawSolidNibStroke(DrawingContext drawingContext) {
|
||||
try {
|
||||
var sp = new StylusPointCollection();
|
||||
foreach (var pt in pointsList) {
|
||||
var point = new StylusPoint();
|
||||
point.PressureFactor = (float)0.5;
|
||||
point.X = pt.X;
|
||||
point.Y = pt.Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
var da = DrawingAttributes.Clone();
|
||||
da.Width -= 0.5;
|
||||
da.Height -= 0.5;
|
||||
var stk = new Stroke(sp, da);
|
||||
stk.Draw(drawingContext);
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
private void DrawSolidNibStrokeForStylus(StylusPointCollection stylusPoints, DrawingContext drawingContext) {
|
||||
try {
|
||||
var sp = new StylusPointCollection();
|
||||
foreach (var pt in stylusPoints) {
|
||||
var point = new StylusPoint();
|
||||
point.PressureFactor = (float)0.5;
|
||||
point.X = pt.X;
|
||||
point.Y = pt.Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
var da = DrawingAttributes.Clone();
|
||||
var stk = new Stroke(sp, da);
|
||||
stk.Draw(drawingContext);
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
protected override void OnDraw(DrawingContext drawingContext,
|
||||
StylusPointCollection stylusPoints,
|
||||
Geometry geometry, Brush fillBrush) {
|
||||
if (_inkCanvas.BoardSettings.StrokeNibStyle == StrokeNibStyle.Beautiful && InputType != InputtingDeviceType.Stylus) {
|
||||
DrawBeautifulNibStroke(drawingContext);
|
||||
} else if (_inkCanvas.BoardSettings.StrokeNibStyle == StrokeNibStyle.Solid && InputType != InputtingDeviceType.Stylus) {
|
||||
DrawSolidNibStroke(drawingContext);
|
||||
} else if (_inkCanvas.BoardSettings.StrokeNibStyle == StrokeNibStyle.Solid && InputType == InputtingDeviceType.Stylus) {
|
||||
DrawSolidNibStrokeForStylus(stylusPoints, drawingContext);
|
||||
} else if (_inkCanvas.BoardSettings.StrokeNibStyle == StrokeNibStyle.Default) {
|
||||
base.OnDraw(drawingContext, stylusPoints, geometry, fillBrush);
|
||||
} else {
|
||||
base.OnDraw(drawingContext, stylusPoints, geometry, fillBrush);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class IccInkCanvas : InkCanvas {
|
||||
|
||||
CustomDynamicRenderer customDynamicRenderer;
|
||||
|
||||
public BoardSettings BoardSettings { get; set; } = new BoardSettings();
|
||||
|
||||
public IccInkCanvas() {
|
||||
customDynamicRenderer = new CustomDynamicRenderer(this);
|
||||
DynamicRenderer = customDynamicRenderer;
|
||||
|
||||
// 通过反射移除InkCanvas自带的默认 Delete按键事件
|
||||
var commandBindingsField =
|
||||
typeof(CommandManager).GetField("_classCommandBindings", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var bnds = commandBindingsField.GetValue(null) as HybridDictionary;
|
||||
var inkCanvasBindings = bnds[typeof(InkCanvas)] as CommandBindingCollection;
|
||||
var enumerator = inkCanvasBindings.GetEnumerator();
|
||||
while (enumerator.MoveNext()) {
|
||||
var item = (CommandBinding)enumerator.Current;
|
||||
if (item.Command == ApplicationCommands.Delete) {
|
||||
var executedField =
|
||||
typeof(CommandBinding).GetField("Executed", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var canExecuteField =
|
||||
typeof(CommandBinding).GetField("CanExecute", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
executedField.SetValue(item, new ExecutedRoutedEventHandler((sender, args) => { }));
|
||||
canExecuteField.SetValue(item, new CanExecuteRoutedEventHandler((sender, args) => { }));
|
||||
}
|
||||
}
|
||||
|
||||
// 为IccInkCanvas注册自定义的 Delete按键Command并Invoke OnDeleteCommandFired。
|
||||
CommandManager.RegisterClassCommandBinding(typeof(IccInkCanvas), new CommandBinding(ApplicationCommands.Delete,
|
||||
(sender, args) => {
|
||||
DeleteKeyCommandFired?.Invoke(this, new RoutedEventArgs());
|
||||
}, (sender, args) => {
|
||||
args.CanExecute = GetSelectedStrokes().Count != 0;
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e) {
|
||||
IccStroke customStroke = new IccStroke(e.Stroke.StylusPoints, e.Stroke.DrawingAttributes);
|
||||
if (e.Stroke is IccStroke) {
|
||||
Strokes.Add(e.Stroke);
|
||||
} else {
|
||||
Strokes.Remove(e.Stroke);
|
||||
Strokes.Add(customStroke);
|
||||
}
|
||||
|
||||
if (BoardSettings.StrokeNibStyle == StrokeNibStyle.Beautiful && customDynamicRenderer.InputType != InputtingDeviceType.Stylus) {
|
||||
try {
|
||||
var stylusPoints = new StylusPointCollection();
|
||||
var n = customStroke.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 = customStroke.StylusPoints[i].X;
|
||||
point.Y = customStroke.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 = customStroke.StylusPoints[i].X;
|
||||
point.Y = customStroke.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 = customStroke.StylusPoints[i].X;
|
||||
point.Y = customStroke.StylusPoints[i].Y;
|
||||
stylusPoints.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
customStroke.StylusPoints = stylusPoints;
|
||||
} catch { }
|
||||
} else if (BoardSettings.StrokeNibStyle == StrokeNibStyle.Solid) {
|
||||
try {
|
||||
var sp = new StylusPointCollection();
|
||||
foreach (var pt in customStroke.StylusPoints) {
|
||||
var point = new StylusPoint();
|
||||
point.PressureFactor = (float)0.5;
|
||||
point.X = pt.X;
|
||||
point.Y = pt.Y;
|
||||
sp.Add(point);
|
||||
}
|
||||
customStroke.StylusPoints = sp;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
InkCanvasStrokeCollectedEventArgs args =
|
||||
new InkCanvasStrokeCollectedEventArgs(customStroke);
|
||||
base.OnStrokeCollected(args);
|
||||
|
||||
Trace.WriteLine("dfsffdsdfdfsfds");
|
||||
}
|
||||
|
||||
public event EventHandler<RoutedEventArgs> DeleteKeyCommandFired;
|
||||
|
||||
public InputtingDeviceType InputtingDeviceType { get; private set; }
|
||||
}
|
||||
}
|
||||