Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11593db23c | |||
| a9ae2a004f | |||
| 7b2a31781c | |||
| ab73eb9632 | |||
| 8ade170b4e | |||
| 91c3d1161d | |||
| bb63805e87 | |||
| 8caf04990c | |||
| f28dd0a965 | |||
| b5d83268e5 | |||
| 19adc42122 | |||
| 8afee913be | |||
| 82d101365f | |||
| 73e679f268 | |||
| 372a8a1de1 | |||
| 171cc34c91 | |||
| fbd217d674 | |||
| f24960ab26 | |||
| d1a871c8f6 | |||
| 086b97906b | |||
| db76a11347 | |||
| 729b10cce8 | |||
| 4cbd25ccb3 | |||
| 0ef7b738a9 | |||
| 33b5563601 | |||
| f6f799f534 | |||
| 8c3f1360e1 | |||
| fafbabd603 | |||
| 254e38895c | |||
| aa0bb22cdd | |||
| 5bfd0c7b2f | |||
| c3885c170c | |||
| 88a7cce269 | |||
| a1fccc2905 | |||
| a889041896 | |||
| 8d778aba2c | |||
| ba5db63e0b | |||
| 0259d83429 | |||
| b6999e57ae | |||
| 04184cf731 | |||
| 04f98eb9e7 | |||
| 869dd045af | |||
| 339ebb862e | |||
| 7b8598bf9f | |||
| ab1c460225 | |||
| 298164d6ed | |||
| 703a8a4e0d | |||
| deaf5fcbf6 | |||
| 18b46689f1 | |||
| edbe3f8311 | |||
| 94c4c3e2d4 | |||
| 077f72737d | |||
| ae089a9390 | |||
| 0f087c2aa6 | |||
| 19d2ffb48e | |||
| a9bb6f73de | |||
| ca124732fa | |||
| 11da14aeab | |||
| 7d5f037c85 | |||
| f62b415227 | |||
| f2b8d4014e | |||
| 3ef047fb41 | |||
| aa3be4ab0d | |||
| 7500049ea2 | |||
| 44600df75c | |||
| dec2a15773 | |||
| 4da78a04cb | |||
| 98ec204bab | |||
| cd9499b064 | |||
| f5e824be86 | |||
| c76254f4f9 | |||
| 77ac6f88ca | |||
| 7e10911991 | |||
| 161b67b09d | |||
| 9614536a29 | |||
| 8ba7aab468 | |||
| 4ea9f79de1 | |||
| b7f7025d97 | |||
| 20d5dd2668 | |||
| adc2d02fbb | |||
| ef2dbdc93b | |||
| 9721ec1f0b | |||
| 4d069d87d7 | |||
| 0308f9ce65 | |||
| 6bcd3cb217 | |||
| 7f83c490db | |||
| bbf9c895b8 | |||
| ffa2063c52 | |||
| d464b1f78e | |||
| 92cb071408 | |||
| 9141b60d03 | |||
| df0a196931 | |||
| a8cb1dd495 | |||
| adc4966d49 | |||
| 1b2ea8c522 | |||
| 7c8bdb489b | |||
| 16458fbb42 | |||
| c72839cdcb | |||
| a31ad5803c | |||
| cf800cbd36 | |||
| 3c06ef0b1a | |||
| 2c3b921f09 | |||
| 402ecc66ae | |||
| e25f56a9b5 | |||
| b28fa887a2 | |||
| f83a02e619 | |||
| eaad089d68 | |||
| a2fda16df9 | |||
| e9e8ff57ae | |||
| 1fd95a2f2e | |||
| 228584ee48 | |||
| c651df0f6e | |||
| 5cced9baf2 |
@@ -1,4 +1,428 @@
|
||||
obj/
|
||||
bin/
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.env
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
|
||||
[Dd]ebug/x64/
|
||||
[Dd]ebugPublic/x64/
|
||||
[Rr]elease/x64/
|
||||
[Rr]eleases/x64/
|
||||
bin/x64/
|
||||
obj/x64/
|
||||
|
||||
[Dd]ebug/x86/
|
||||
[Dd]ebugPublic/x86/
|
||||
[Rr]elease/x86/
|
||||
[Rr]eleases/x86/
|
||||
bin/x86/
|
||||
obj/x86/
|
||||
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
[Aa][Rr][Mm]64[Ee][Cc]/
|
||||
bld/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Build results on 'Bin' directories
|
||||
**/[Bb]in/*
|
||||
# Uncomment if you have tasks that rely on *.refresh files to move binaries
|
||||
# (https://github.com/github/gitignore/pull/3736)
|
||||
#!**/[Bb]in/*.refresh
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
/Ink Canvas/obj
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
*.trx
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Approval Tests result files
|
||||
*.received.*
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.idb
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
# but not Directory.Build.rsp, as it configures directory-level build defaults
|
||||
!Directory.Build.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
**/.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
**/.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
**/.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
**/__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
#tools/**
|
||||
#!tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
MSBuild_Logs/
|
||||
|
||||
# AWS SAM Build and Temporary Artifacts folder
|
||||
.aws-sam
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
**/.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
**/.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
**/.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
@@ -1 +1 @@
|
||||
1.7.13.0
|
||||
1.7.15.0
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<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>
|
||||
<s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue">C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe</s:String>
|
||||
<s:Int64 x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsbuildVersion/@EntryValue">1114112</s:Int64>
|
||||
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=InkCanvasForClass_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -232,7 +232,7 @@
|
||||
ContextMenu="{StaticResource SysTrayMenu}"
|
||||
IconSource="/Resources/icc.ico"/>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemeResources RequestedTheme="Light"/>
|
||||
<ui:ThemeResources/>
|
||||
<ui:XamlControlsResources />
|
||||
<ResourceDictionary Source="Resources/SeewoImageDictionary.xaml"/>
|
||||
<ResourceDictionary Source="Resources/DrawShapeImageDictionary.xaml"/>
|
||||
|
||||
@@ -38,9 +38,11 @@ namespace Ink_Canvas
|
||||
// 新增:标记是否通过--show参数启动
|
||||
public static bool StartWithShowMode = false;
|
||||
// 新增:保存看门狗进程对象
|
||||
private static Process watchdogProcess;
|
||||
public static Process watchdogProcess;
|
||||
// 新增:标记是否为软件内主动退出
|
||||
public static bool IsAppExitByUser;
|
||||
// 新增:标记是否启用了UIA置顶功能
|
||||
public static bool IsUIAccessTopMostEnabled;
|
||||
// 新增:退出信号文件路径
|
||||
private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + Process.GetCurrentProcess().Id + ".flag");
|
||||
// 新增:崩溃日志文件路径
|
||||
@@ -436,7 +438,6 @@ namespace Ink_Canvas
|
||||
{
|
||||
_splashScreen.CloseSplashScreen();
|
||||
_isSplashScreenShown = false;
|
||||
LogHelper.WriteLogToFile("启动画面已关闭");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -629,7 +630,7 @@ namespace Ink_Canvas
|
||||
LogHelper.WriteLogToFile("App | 检测到最终应用启动(更新后的应用)");
|
||||
}
|
||||
|
||||
// 在应用启动时自动释放IACore相关DLL
|
||||
// 释放IACore相关DLL
|
||||
if (_isSplashScreenShown)
|
||||
{
|
||||
SetSplashMessage("正在初始化组件...");
|
||||
@@ -645,6 +646,22 @@ namespace Ink_Canvas
|
||||
LogHelper.WriteLogToFile($"释放IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 释放UIAccess DLL
|
||||
if (_isSplashScreenShown)
|
||||
{
|
||||
SetSplashMessage("正在初始化组件...");
|
||||
SetSplashProgress(50);
|
||||
await Task.Delay(300);
|
||||
}
|
||||
try
|
||||
{
|
||||
UIAccessDllExtractor.ExtractUIAccessDlls();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"释放UIAccess DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
|
||||
// 记录应用启动(设备标识符)
|
||||
if (_isSplashScreenShown)
|
||||
{
|
||||
@@ -1016,7 +1033,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
// 看门狗进程
|
||||
private void StartWatchdogIfNeeded()
|
||||
public static void StartWatchdogIfNeeded()
|
||||
{
|
||||
// 避免递归启动
|
||||
if (Environment.GetCommandLineArgs().Contains("--watchdog")) return;
|
||||
@@ -1055,7 +1072,13 @@ namespace Ink_Canvas
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
// 主进程异常退出,自动重启前判断崩溃后操作
|
||||
SyncCrashActionFromSettings(); // 新增:同步设置
|
||||
SyncCrashActionFromSettings(); // 同步设置
|
||||
|
||||
if (IsUIAccessTopMostEnabled)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
if (CrashAction == CrashActionType.SilentRestart)
|
||||
{
|
||||
StartupCount.Increment();
|
||||
@@ -1068,7 +1091,6 @@ namespace Ink_Canvas
|
||||
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
Process.Start(exePath);
|
||||
}
|
||||
// CrashActionType.NoAction 时不重启,直接退出
|
||||
}
|
||||
catch { }
|
||||
Environment.Exit(0);
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Windows;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("CJK_mkp")]
|
||||
[assembly: AssemblyProduct("InkCanvasForClass")]
|
||||
[assembly: AssemblyCopyright("Copyright © HARKOTEK Studio 2024")]
|
||||
[assembly: AssemblyCopyright("Copyright © CJK_mkp 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -49,5 +49,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.7.13.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.13.0")]
|
||||
[assembly: AssemblyVersion("1.7.15.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.15.0")]
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||
<xs:element name="Weavers">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX86Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinArm64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCompression" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCleanup" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableEventSubscription" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The attach method no longer subscribes to the `AppDomain.AssemblyResolve` (.NET 4.x) and `AssemblyLoadContext.Resolving` (.NET 6.0+) events.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UnmanagedWinX86Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UnmanagedWinX64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UnmanagedWinArm64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -112,4 +112,27 @@ namespace Ink_Canvas.Converter
|
||||
}
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public class InverseBooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if ((bool)value)
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if ((bool)value)
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,7 +865,7 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
// 检查当前是否处于鼠标模式
|
||||
bool isMouseMode = IsInSelectMode();
|
||||
|
||||
|
||||
if (isMouseMode)
|
||||
{
|
||||
// 鼠标模式下,根据设置决定是否启用快捷键
|
||||
@@ -874,7 +874,7 @@ namespace Ink_Canvas.Helpers
|
||||
else
|
||||
{
|
||||
// 非鼠标模式下,需要检查焦点和屏幕位置
|
||||
|
||||
|
||||
// 策略1:鼠标在窗口上时启用热键(最高优先级)
|
||||
if (_isMouseOverWindow)
|
||||
{
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制保存指定页面的墨迹(忽略锁定状态)
|
||||
/// 强制保存指定页面的墨迹
|
||||
/// </summary>
|
||||
public void ForceSaveSlideStrokes(int slideIndex, StrokeCollection strokes)
|
||||
{
|
||||
|
||||
@@ -678,14 +678,25 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
|
||||
if (!IsConnected || PPTApplication == null) return false;
|
||||
if (!Marshal.IsComObject(PPTApplication)) return false;
|
||||
|
||||
var slideShowWindow = PPTApplication.SlideShowWindows[1];
|
||||
if (slideShowWindow?.View != null)
|
||||
if (IsInSlideShow && PPTApplication.SlideShowWindows.Count >= 1)
|
||||
{
|
||||
slideShowWindow.View.GotoSlide(slideNumber);
|
||||
return true;
|
||||
var slideShowWindow = PPTApplication.SlideShowWindows[1];
|
||||
if (slideShowWindow?.View != null)
|
||||
{
|
||||
slideShowWindow.View.GotoSlide(slideNumber);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (CurrentPresentation != null)
|
||||
{
|
||||
if (CurrentPresentation.Windows?.Count >= 1)
|
||||
{
|
||||
CurrentPresentation.Windows[1].View.GotoSlide(slideNumber);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// UIAccess DLL释放器
|
||||
/// </summary>
|
||||
public static class UIAccessDllExtractor
|
||||
{
|
||||
private static readonly string[] RequiredDlls = {
|
||||
"UIAccessDLL_x64.dll",
|
||||
"UIAccessDLL_x86.dll"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 在应用启动时释放UIAccess相关DLL
|
||||
/// </summary>
|
||||
public static void ExtractUIAccessDlls()
|
||||
{
|
||||
try
|
||||
{
|
||||
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
LogHelper.WriteLogToFile("开始检查并释放UIAccess相关DLL文件");
|
||||
|
||||
foreach (string dllName in RequiredDlls)
|
||||
{
|
||||
string targetPath = Path.Combine(appDirectory, dllName);
|
||||
|
||||
// 检查文件是否已存在且有效
|
||||
if (File.Exists(targetPath) && IsValidDll(targetPath))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"{dllName} 已存在且有效,跳过释放");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 从嵌入资源中释放DLL
|
||||
if (ExtractDllFromResource(dllName, targetPath))
|
||||
{
|
||||
LogHelper.WriteLogToFile($"成功释放 {dllName} 到 {targetPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile($"警告:无法释放 {dllName},可能影响UIA置顶功能", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile("UIAccess DLL释放检查完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"释放UIAccess DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从嵌入资源中提取DLL文件
|
||||
/// </summary>
|
||||
private static bool ExtractDllFromResource(string dllName, string targetPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
string resourceName = $"Ink_Canvas.{dllName}";
|
||||
|
||||
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
|
||||
{
|
||||
if (resourceStream == null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"未找到嵌入资源: {resourceName}", LogHelper.LogType.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确保目标目录存在
|
||||
string targetDirectory = Path.GetDirectoryName(targetPath);
|
||||
if (!Directory.Exists(targetDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(targetDirectory);
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
using (FileStream fileStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
resourceStream.CopyTo(fileStream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"从资源提取 {dllName} 失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查DLL文件是否有效
|
||||
/// </summary>
|
||||
private static bool IsValidDll(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
return false;
|
||||
|
||||
FileInfo fileInfo = new FileInfo(filePath);
|
||||
|
||||
// 检查文件大小(空文件或过小的文件可能无效)
|
||||
if (fileInfo.Length < 1024) // 小于1KB可能无效
|
||||
return false;
|
||||
|
||||
// 简单检查PE头(DLL文件应该以MZ开头)
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
if (fs.Read(buffer, 0, 2) == 2)
|
||||
{
|
||||
return buffer[0] == 0x4D && buffer[1] == 0x5A; // "MZ"
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理释放的DLL文件(可选,在应用退出时调用)
|
||||
/// </summary>
|
||||
public static void CleanupExtractedDlls()
|
||||
{
|
||||
try
|
||||
{
|
||||
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
foreach (string dllName in RequiredDlls)
|
||||
{
|
||||
string filePath = Path.Combine(appDirectory, dllName);
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(filePath);
|
||||
LogHelper.WriteLogToFile($"已清理 {dllName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"清理 {dllName} 失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"清理UIAccess DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,11 +192,14 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\TimerDownNotice.wav" />
|
||||
<None Include="Resources\ProgressiveAudio.wav" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\IACore\IACore.dll" />
|
||||
<EmbeddedResource Include="Resources\IACore\IALoader.dll" />
|
||||
<EmbeddedResource Include="Resources\IACore\IAWinFX.dll" />
|
||||
<EmbeddedResource Include="UIAccessDLL_x64.dll" />
|
||||
<EmbeddedResource Include="UIAccessDLL_x86.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\Cursor.cur" />
|
||||
@@ -243,6 +246,10 @@
|
||||
<Resource Include="Resources\Icons-png\undo.png" />
|
||||
<Resource Include="Resources\Icons-png\minimize.png" />
|
||||
<Resource Include="Resources\Icons-png\penUpright.png" />
|
||||
<Resource Include="Resources\new-icons\multi-touch_white.png" />
|
||||
<Resource Include="Resources\new-icons\hand-move_white.png" />
|
||||
<Resource Include="Resources\new-icons\zoom_white.png" />
|
||||
<Resource Include="Resources\new-icons\rotate_white.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Icons-png\twoFingelMove-Blue.png" />
|
||||
|
||||
@@ -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>
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
<c:IsEnabledToOpacityConverter x:Key="IsEnabledToOpacityConverter" />
|
||||
<c:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<c:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
|
||||
<c:IntNumberToString x:Key="IntNumberToString" />
|
||||
<c:IntNumberToString2 x:Key="IntNumberToString2" />
|
||||
|
||||
@@ -609,6 +610,14 @@
|
||||
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
Toggled="ToggleSwitchAlwaysOnTop_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left" Name="UIAccessTopMostPanel" Visibility="Collapsed">
|
||||
<TextBlock Foreground="#fafafa" Text="UIA置顶" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchUIAccessTopMost"
|
||||
IsOn="False" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
Toggled="ToggleSwitchUIAccessTopMost_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<TextBlock Name="UIAccessTopMostDescription" Text="# 开启UIA置顶后,软件需要管理员启动才能置顶,关闭此功能需要完全关闭软件后再手动启动,无法使用重启来关闭此功能" TextWrapping="Wrap" Foreground="#a1a1aa" Visibility="Collapsed" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||
Name="ToggleSwitchIsAutoUpdate" Header="自动检查更新"
|
||||
FontFamily="Microsoft YaHei UI"
|
||||
@@ -631,6 +640,13 @@
|
||||
<TextBlock Text="# 稳定版提供可靠更新,测试版提供新功能抢先体验" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||
</ui:SimpleStackPanel>
|
||||
|
||||
<!-- 手动更新按钮 -->
|
||||
<Button x:Name="ManualUpdateButton" Content="手动更新" Margin="0,8,0,0"
|
||||
Width="120" HorizontalAlignment="Left" Click="ManualUpdateButton_Click"
|
||||
Visibility="{Binding ElementName=ToggleSwitchIsAutoUpdate, Path=IsOn, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
|
||||
<TextBlock Text="# 点击后立即检查并下载最新版本"
|
||||
TextWrapping="Wrap" Foreground="#a1a1aa"
|
||||
Visibility="{Binding ElementName=ToggleSwitchIsAutoUpdate, Path=IsOn, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
|
||||
<!-- 版本修复按钮 -->
|
||||
<Button x:Name="FixVersionButton" Content="版本修复" Margin="0,8,0,0"
|
||||
Width="120" HorizontalAlignment="Left" Click="FixVersionButton_Click"/>
|
||||
@@ -2013,7 +2029,7 @@
|
||||
FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||
Toggled="ToggleSwitchNotifyPreviousPage_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<TextBlock Text="#开启后会记录上次播放的页数,点击“是”后会在进入放映状态时自动跳转"
|
||||
<TextBlock Text="#开启后会记录上次播放的页数,点击“是”后会自动跳转"
|
||||
TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="进入放映时回到首页" VerticalAlignment="Center"
|
||||
@@ -3297,13 +3313,31 @@
|
||||
Toggled="ToggleSwitchUseLegacyTimerUI_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="启用仿希沃UI"
|
||||
<TextBlock Foreground="#fafafa" Text="新计时器UI"
|
||||
VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||
Name="ToggleSwitchUseSeewoStyleUI"
|
||||
Name="ToggleSwitchUseNewStyleUI"
|
||||
IsOn="False" FontFamily="Microsoft YaHei UI"
|
||||
FontWeight="Bold"
|
||||
Toggled="ToggleSwitchUseSeewoStyleUI_Toggled" />
|
||||
Toggled="ToggleSwitchUseNewStyleUI_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="启用正计时"
|
||||
VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||
Name="ToggleSwitchEnableOvertimeCountUp"
|
||||
IsOn="False" FontFamily="Microsoft YaHei UI"
|
||||
FontWeight="Bold"
|
||||
Toggled="ToggleSwitchEnableOvertimeCountUp_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="超时醒目数字"
|
||||
VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||
Name="ToggleSwitchEnableOvertimeRedText"
|
||||
IsOn="True" FontFamily="Microsoft YaHei UI"
|
||||
FontWeight="Bold"
|
||||
Toggled="ToggleSwitchEnableOvertimeRedText_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Foreground="#fafafa" Text="计时器提醒音量" VerticalAlignment="Center"
|
||||
@@ -3325,6 +3359,35 @@
|
||||
<Button Name="ButtonResetTimerSound" Content="重置" FontFamily="Microsoft YaHei UI"
|
||||
Click="ButtonResetTimerSound_Click" Padding="10,3" Margin="5,0,0,0"/>
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,5,0,0">
|
||||
<TextBlock Foreground="#fafafa" Text="渐进提醒" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||
Name="ToggleSwitchEnableProgressiveReminder"
|
||||
IsOn="False" FontFamily="Microsoft YaHei UI"
|
||||
FontWeight="Bold"
|
||||
Toggled="ToggleSwitchEnableProgressiveReminder_Toggled" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,5,0,0">
|
||||
<TextBlock Foreground="#fafafa" Text="渐进提醒音量" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<Slider x:Name="ProgressiveReminderVolumeSlider" Minimum="0"
|
||||
Maximum="1" Width="168" FontFamily="Microsoft YaHei UI"
|
||||
ValueChanged="ProgressiveReminderVolumeSlider_ValueChanged"
|
||||
FontSize="20" IsSnapToTickEnabled="True" Value="1" TickFrequency="0.1"
|
||||
TickPlacement="None" AutoToolTipPlacement="None" />
|
||||
<TextBlock VerticalAlignment="Center" Margin="12,0,16,0" FontSize="14"
|
||||
FontFamily="Consolas"
|
||||
Text="{Binding ElementName=ProgressiveReminderVolumeSlider, Path=Value, StringFormat={}{0:P0}}" />
|
||||
</ui:SimpleStackPanel>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,5,0,0">
|
||||
<TextBlock Foreground="#fafafa" Text="自定义渐进提醒音频:" VerticalAlignment="Center"
|
||||
FontSize="14" Margin="0,0,16,0" />
|
||||
<Button Name="ButtonSelectCustomProgressiveReminderSound" Content="选择文件" FontFamily="Microsoft YaHei UI"
|
||||
Click="ButtonSelectCustomProgressiveReminderSound_Click" Padding="10,3"/>
|
||||
<Button Name="ButtonResetProgressiveReminderSound" Content="重置" FontFamily="Microsoft YaHei UI"
|
||||
Click="ButtonResetProgressiveReminderSound_Click" Padding="10,3" Margin="5,0,0,0"/>
|
||||
</ui:SimpleStackPanel>
|
||||
</ui:SimpleStackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox>
|
||||
@@ -4418,7 +4481,7 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,3,0,0">
|
||||
<Image Source="/Resources/new-icons/multi-touch.png"
|
||||
<Image Source="{DynamicResource MultiTouchIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Height="16"
|
||||
Width="16" />
|
||||
@@ -4449,7 +4512,7 @@
|
||||
Orientation="Horizontal" Spacing="4"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/hand-move.png"
|
||||
<Image Source="{DynamicResource HandMoveIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Height="16"
|
||||
Width="16" />
|
||||
@@ -4480,7 +4543,7 @@
|
||||
Orientation="Horizontal" Spacing="4"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/zoom.png"
|
||||
<Image Source="{DynamicResource ZoomIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Height="16"
|
||||
Width="16" />
|
||||
@@ -4509,7 +4572,7 @@
|
||||
Orientation="Horizontal" Spacing="4"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/rotate.png"
|
||||
<Image Source="{DynamicResource RotateIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Height="16"
|
||||
Width="16" />
|
||||
@@ -9335,7 +9398,7 @@
|
||||
</Border>
|
||||
<ui:SimpleStackPanel Orientation="Horizontal" Spacing="4" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center" Margin="0,3,0,0">
|
||||
<Image Source="/Resources/new-icons/multi-touch.png"
|
||||
<Image Source="{DynamicResource MultiTouchIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Height="16" Width="16" />
|
||||
<Label Content="多指书写" FontSize="10" VerticalAlignment="Center" />
|
||||
<Viewbox Width="36" Height="18" Margin="4,0,0,0">
|
||||
@@ -9359,7 +9422,7 @@
|
||||
<ui:SimpleStackPanel Opacity="1" x:Name="TwoFingerGestureSimpleStackPanel"
|
||||
Orientation="Horizontal" Spacing="4" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/hand-move.png"
|
||||
<Image Source="{DynamicResource HandMoveIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Height="16" Width="16" />
|
||||
<Label Content="双指移动" FontSize="10" VerticalAlignment="Center" />
|
||||
<Viewbox Width="36" Height="18" Margin="4,0,0,0">
|
||||
@@ -9384,7 +9447,7 @@
|
||||
Opacity="{Binding ElementName=TwoFingerGestureSimpleStackPanel, Path=Opacity}"
|
||||
Orientation="Horizontal" Spacing="4" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/zoom.png"
|
||||
<Image Source="{DynamicResource ZoomIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Height="16" Width="16" />
|
||||
<Label Content="双指缩放" FontSize="10" VerticalAlignment="Center" />
|
||||
<Viewbox Width="36" Height="18" Margin="4,0,0,0">
|
||||
@@ -9409,7 +9472,7 @@
|
||||
Opacity="{Binding ElementName=TwoFingerGestureSimpleStackPanel, Path=Opacity}"
|
||||
Orientation="Horizontal" Spacing="4" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="/Resources/new-icons/rotate.png"
|
||||
<Image Source="{DynamicResource RotateIcon}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Height="16" Width="16" />
|
||||
<Label Content="双指旋转" FontSize="10" VerticalAlignment="Center" />
|
||||
<Viewbox Width="36" Height="18" Margin="4,0,0,0">
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
@@ -38,6 +39,12 @@ namespace Ink_Canvas
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
[DllImport("UIAccessDLL_x86.dll", EntryPoint = "PrepareUIAccess", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern Int32 PrepareUIAccessX86();
|
||||
|
||||
[DllImport("UIAccessDLL_x64.dll", EntryPoint = "PrepareUIAccess", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern Int32 PrepareUIAccessX64();
|
||||
|
||||
// 每一页一个Canvas对象
|
||||
private List<System.Windows.Controls.Canvas> whiteboardPages = new List<System.Windows.Controls.Canvas>();
|
||||
private int currentPageIndex;
|
||||
@@ -55,6 +62,7 @@ namespace Ink_Canvas
|
||||
|
||||
// 设置面板相关状态
|
||||
private bool userChangedNoFocusModeInSettings;
|
||||
private bool isTemporarilyDisablingNoFocusMode = false;
|
||||
|
||||
|
||||
|
||||
@@ -550,6 +558,12 @@ namespace Ink_Canvas
|
||||
ToggleSwitchAlwaysOnTop.IsOn = Settings.Advanced.IsAlwaysOnTop;
|
||||
ApplyAlwaysOnTop();
|
||||
|
||||
// 初始化UIA置顶开关
|
||||
ToggleSwitchUIAccessTopMost.IsOn = Settings.Advanced.EnableUIAccessTopMost;
|
||||
UpdateUIAccessTopMostVisibility();
|
||||
|
||||
App.IsUIAccessTopMostEnabled = Settings.Advanced.EnableUIAccessTopMost;
|
||||
|
||||
// 初始化剪贴板监控
|
||||
InitializeClipboardMonitoring();
|
||||
|
||||
@@ -787,7 +801,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:使用多线路组下载更新
|
||||
// 使用多线路组下载更新
|
||||
private async Task<bool> DownloadUpdateWithFallback(string version, AutoUpdateHelper.UpdateLineGroup primaryGroup, UpdateChannel channel)
|
||||
{
|
||||
try
|
||||
@@ -832,12 +846,14 @@ namespace Ink_Canvas
|
||||
// 声明下载状态变量,用于整个方法
|
||||
bool isDownloadSuccessful = false;
|
||||
|
||||
bool hasValidLineGroup = lineGroup != null;
|
||||
|
||||
if (AvailableLatestVersion != null)
|
||||
{
|
||||
// 检测到新版本,停止重试定时器
|
||||
timerCheckAutoUpdateRetry.Stop();
|
||||
updateCheckRetryCount = 0;
|
||||
|
||||
|
||||
// 检测到新版本
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {AvailableLatestVersion}");
|
||||
|
||||
@@ -1001,17 +1017,25 @@ namespace Ink_Canvas
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hasValidLineGroup)
|
||||
{
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Current version is already the latest, no retry needed");
|
||||
|
||||
// 停止重试定时器
|
||||
timerCheckAutoUpdateRetry.Stop();
|
||||
updateCheckRetryCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 检查更新失败,启动重试定时器
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update check failed, starting retry timer");
|
||||
|
||||
|
||||
// 重置重试计数
|
||||
updateCheckRetryCount = 0;
|
||||
|
||||
|
||||
// 启动重试定时器,10分钟后重新检查
|
||||
timerCheckAutoUpdateRetry.Start();
|
||||
|
||||
|
||||
// 清理更新文件夹
|
||||
AutoUpdateHelper.DeleteUpdatesFolder();
|
||||
}
|
||||
@@ -1194,14 +1218,14 @@ namespace Ink_Canvas
|
||||
RefreshDeviceInfo();
|
||||
}
|
||||
|
||||
// 新增:个性化设置
|
||||
// 个性化设置
|
||||
private void NavTheme_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 切换到个性化设置页面
|
||||
ShowSettingsSection("theme");
|
||||
}
|
||||
|
||||
// 新增:快捷键设置
|
||||
// 快捷键设置
|
||||
private void NavShortcuts_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenHotkeySettingsWindow();
|
||||
@@ -1298,7 +1322,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:折叠侧边栏
|
||||
// 折叠侧边栏
|
||||
private void CollapseNavSidebar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 折叠/展开侧边栏
|
||||
@@ -1315,7 +1339,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:显示侧边栏
|
||||
// 显示侧边栏
|
||||
private void ShowNavSidebar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 确保侧边栏展开
|
||||
@@ -1323,7 +1347,7 @@ namespace Ink_Canvas
|
||||
columnDefinitions[0].Width = new GridLength(50);
|
||||
}
|
||||
|
||||
// 辅助方法:显示指定的设置部分
|
||||
// 显示指定的设置部分
|
||||
private async void ShowSettingsSection(string sectionTag)
|
||||
{
|
||||
// 显示设置面板
|
||||
@@ -1816,7 +1840,11 @@ namespace Ink_Canvas
|
||||
{
|
||||
var hwnd = new WindowInteropHelper(this).Handle;
|
||||
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
if (Settings.Advanced.IsNoFocusMode)
|
||||
|
||||
bool shouldBeNoFocus = isTemporarilyDisablingNoFocusMode ?
|
||||
false : Settings.Advanced.IsNoFocusMode;
|
||||
|
||||
if (shouldBeNoFocus)
|
||||
{
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
|
||||
}
|
||||
@@ -1833,10 +1861,8 @@ namespace Ink_Canvas
|
||||
var hwnd = new WindowInteropHelper(this).Handle;
|
||||
if (Settings.Advanced.IsAlwaysOnTop)
|
||||
{
|
||||
// 先设置WPF的Topmost属性
|
||||
Topmost = true;
|
||||
|
||||
// 使用更强的Win32 API调用来确保置顶
|
||||
// 1. 设置窗口样式为置顶
|
||||
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST);
|
||||
@@ -1845,8 +1871,8 @@ namespace Ink_Canvas
|
||||
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
|
||||
|
||||
// 3. 如果启用了无焦点模式,需要特殊处理
|
||||
if (Settings.Advanced.IsNoFocusMode)
|
||||
// 3. 如果启用了无焦点模式且未启用UIA置顶,需要特殊处理
|
||||
if (Settings.Advanced.IsNoFocusMode && !Settings.Advanced.EnableUIAccessTopMost)
|
||||
{
|
||||
// 启动置顶维护定时器
|
||||
StartTopmostMaintenance();
|
||||
@@ -1870,11 +1896,6 @@ namespace Ink_Canvas
|
||||
|
||||
// 3. 停止置顶维护定时器
|
||||
StopTopmostMaintenance();
|
||||
|
||||
// 注意:这里不直接设置Topmost,让其他代码根据模式决定
|
||||
|
||||
// 添加调试日志
|
||||
LogHelper.WriteLogToFile("应用窗口置顶: 取消置顶", LogHelper.LogType.Trace);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1888,6 +1909,11 @@ namespace Ink_Canvas
|
||||
/// </summary>
|
||||
private void StartTopmostMaintenance()
|
||||
{
|
||||
if (Settings.Advanced.EnableUIAccessTopMost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTopmostMaintenanceEnabled) return;
|
||||
|
||||
if (topmostMaintenanceTimer == null)
|
||||
@@ -1922,6 +1948,12 @@ namespace Ink_Canvas
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings.Advanced.EnableUIAccessTopMost)
|
||||
{
|
||||
StopTopmostMaintenance();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Settings.Advanced.IsAlwaysOnTop || !Settings.Advanced.IsNoFocusMode)
|
||||
{
|
||||
StopTopmostMaintenance();
|
||||
@@ -1998,6 +2030,12 @@ namespace Ink_Canvas
|
||||
var toggle = sender as ToggleSwitch;
|
||||
Settings.Advanced.IsNoFocusMode = toggle != null && toggle.IsOn;
|
||||
SaveSettingsToFile();
|
||||
|
||||
if (isTemporarilyDisablingNoFocusMode)
|
||||
{
|
||||
isTemporarilyDisablingNoFocusMode = false;
|
||||
}
|
||||
|
||||
ApplyNoFocusMode();
|
||||
|
||||
// 如果启用了窗口置顶,需要重新应用置顶设置以处理无焦点模式的变化
|
||||
@@ -2020,6 +2058,21 @@ namespace Ink_Canvas
|
||||
Settings.Advanced.IsAlwaysOnTop = toggle != null && toggle.IsOn;
|
||||
SaveSettingsToFile();
|
||||
ApplyAlwaysOnTop();
|
||||
UpdateUIAccessTopMostVisibility();
|
||||
}
|
||||
|
||||
private void ToggleSwitchUIAccessTopMost_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
var toggle = sender as ToggleSwitch;
|
||||
bool newValue = toggle != null && toggle.IsOn;
|
||||
|
||||
Settings.Advanced.EnableUIAccessTopMost = newValue;
|
||||
SaveSettingsToFile();
|
||||
ApplyUIAccessTopMost();
|
||||
|
||||
App.IsUIAccessTopMostEnabled = newValue;
|
||||
|
||||
}
|
||||
|
||||
private void Window_Activated(object sender, EventArgs e)
|
||||
@@ -2449,6 +2502,8 @@ namespace Ink_Canvas
|
||||
SideControlMinimumAutomationSlider,
|
||||
RandWindowOnceCloseLatencySlider,
|
||||
RandWindowOnceMaxStudentsSlider,
|
||||
TimerVolumeSlider,
|
||||
ProgressiveReminderVolumeSlider,
|
||||
BoardInkWidthSlider,
|
||||
BoardInkAlphaSlider,
|
||||
BoardHighlighterWidthSlider,
|
||||
@@ -2911,5 +2966,93 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UIA置顶功能
|
||||
|
||||
/// <summary>
|
||||
/// 更新UIA置顶开关的可见性
|
||||
/// </summary>
|
||||
private void UpdateUIAccessTopMostVisibility()
|
||||
{
|
||||
try
|
||||
{
|
||||
var visibility = Settings.Advanced.IsAlwaysOnTop ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
if (UIAccessTopMostPanel != null)
|
||||
{
|
||||
UIAccessTopMostPanel.Visibility = visibility;
|
||||
}
|
||||
|
||||
if (UIAccessTopMostDescription != null)
|
||||
{
|
||||
UIAccessTopMostDescription.Visibility = visibility;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"更新UIA置顶开关可见性时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用UIA置顶功能
|
||||
/// </summary>
|
||||
private void ApplyUIAccessTopMost()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings.Advanced.EnableUIAccessTopMost && Settings.Advanced.IsAlwaysOnTop)
|
||||
{
|
||||
// 检查是否以管理员权限运行
|
||||
var identity = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(identity);
|
||||
|
||||
if (principal.IsInRole(WindowsBuiltInRole.Administrator))
|
||||
{
|
||||
try
|
||||
{
|
||||
timerKillProcess.Stop();
|
||||
if (App.watchdogProcess != null && !App.watchdogProcess.HasExited)
|
||||
{
|
||||
App.watchdogProcess.Kill();
|
||||
App.watchdogProcess = null;
|
||||
}
|
||||
|
||||
|
||||
// 调用UIAccess DLL
|
||||
if (Environment.Is64BitProcess)
|
||||
{
|
||||
PrepareUIAccessX64();
|
||||
}
|
||||
else
|
||||
{
|
||||
PrepareUIAccessX86();
|
||||
}
|
||||
|
||||
App.StartWatchdogIfNeeded();
|
||||
timerKillProcess.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"启用UIA置顶功能时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("UIA置顶功能需要管理员权限", LogHelper.LogType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("UIA置顶功能已禁用", LogHelper.LogType.Trace);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"应用UIA置顶功能时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Ink_Canvas
|
||||
|
||||
// 强制刷新UI
|
||||
window.InvalidateVisual();
|
||||
|
||||
|
||||
// 通知其他窗口刷新主题
|
||||
RefreshOtherWindowsTheme();
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace Ink_Canvas
|
||||
|
||||
// 强制刷新UI
|
||||
window.InvalidateVisual();
|
||||
|
||||
|
||||
// 通知其他窗口刷新主题
|
||||
RefreshOtherWindowsTheme();
|
||||
}
|
||||
@@ -184,18 +184,18 @@ namespace Ink_Canvas
|
||||
// 根据主题设置高光颜色
|
||||
Color highlightBackgroundColor;
|
||||
Color highlightBarColor;
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
(Settings.Appearance.Theme == 2 && !IsSystemThemeLight());
|
||||
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
highlightBackgroundColor = Color.FromArgb(21, 102, 204, 255);
|
||||
highlightBarColor = Color.FromRgb(102, 204, 255);
|
||||
highlightBackgroundColor = Color.FromArgb(21, 102, 204, 255);
|
||||
highlightBarColor = Color.FromRgb(102, 204, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightBackgroundColor = Color.FromArgb(21, 59, 130, 246);
|
||||
highlightBarColor = Color.FromRgb(37, 99, 235);
|
||||
highlightBackgroundColor = Color.FromArgb(21, 59, 130, 246);
|
||||
highlightBarColor = Color.FromRgb(37, 99, 235);
|
||||
}
|
||||
|
||||
// 设置高光背景颜色
|
||||
@@ -224,16 +224,16 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 根据主题选择高光颜色
|
||||
Color selectedColor;
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
(Settings.Appearance.Theme == 2 && !IsSystemThemeLight());
|
||||
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
selectedColor = Color.FromRgb(102, 204, 255);
|
||||
selectedColor = Color.FromRgb(102, 204, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedColor = Color.FromRgb(30, 58, 138);
|
||||
selectedColor = Color.FromRgb(30, 58, 138);
|
||||
}
|
||||
|
||||
// 根据当前模式设置按钮颜色
|
||||
@@ -376,7 +376,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 强制刷新墨迹选中栏的视觉状态
|
||||
BorderStrokeSelectionControl.InvalidateVisual();
|
||||
|
||||
|
||||
// 刷新墨迹选中栏内的所有图标
|
||||
var viewbox = BorderStrokeSelectionControl.Child as Viewbox;
|
||||
if (viewbox?.Child is ui.SimpleStackPanel stackPanel)
|
||||
@@ -434,7 +434,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 强制刷新图片选中栏的视觉状态
|
||||
BorderImageSelectionControl.InvalidateVisual();
|
||||
|
||||
|
||||
// 刷新图片选中栏内的所有图标
|
||||
var viewbox = BorderImageSelectionControl.Child as Viewbox;
|
||||
if (viewbox?.Child is ui.SimpleStackPanel stackPanel)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -120,15 +121,25 @@ namespace Ink_Canvas
|
||||
_currentCommitType = CommitReason.ClearingCanvas;
|
||||
if (isErasedByCode) _currentCommitType = CommitReason.CodeInput;
|
||||
|
||||
|
||||
|
||||
// 只清除笔画,不清除图片元素
|
||||
// 图片元素的清除由调用方决定
|
||||
inkCanvas.Strokes.Clear();
|
||||
|
||||
// 执行内存清理
|
||||
PerformLightweightMemoryCleanup();
|
||||
|
||||
_currentCommitType = CommitReason.UserInput;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行内存清理
|
||||
/// </summary>
|
||||
private void PerformLightweightMemoryCleanup()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
GC.Collect();
|
||||
});
|
||||
}
|
||||
|
||||
// 恢复每页白板图片信息
|
||||
private void RestoreStrokes(bool isBackupMain = false)
|
||||
{
|
||||
@@ -418,7 +429,7 @@ namespace Ink_Canvas
|
||||
|
||||
// 获取主题颜色资源
|
||||
var iconForegroundBrush = Application.Current.FindResource("IconForeground") as SolidColorBrush;
|
||||
|
||||
|
||||
// 设置下一页按钮颜色
|
||||
if (iconForegroundBrush != null)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,10 @@ namespace Ink_Canvas
|
||||
|
||||
private void ColorSwitchCheck()
|
||||
{
|
||||
HideSubPanels("color");
|
||||
if (penType != 1)
|
||||
{
|
||||
HideSubPanels("color");
|
||||
}
|
||||
if (GridTransparencyFakeBackground.Background == Brushes.Transparent)
|
||||
{
|
||||
if (currentMode == 1)
|
||||
|
||||
@@ -383,7 +383,7 @@ namespace Ink_Canvas
|
||||
var slideAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 0, // 滑动距离
|
||||
To = BorderSettings.RenderTransform.Value.OffsetX - 440,
|
||||
To = BorderSettings.RenderTransform.Value.OffsetX - 490,
|
||||
Duration = TimeSpan.FromSeconds(0.6)
|
||||
};
|
||||
slideAnimation.EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut };
|
||||
@@ -396,18 +396,13 @@ namespace Ink_Canvas
|
||||
{
|
||||
BorderSettings.Visibility = Visibility.Collapsed;
|
||||
isOpeningOrHidingSettingsPane = false;
|
||||
// 在设置面板完全关闭后,根据情况恢复无焦点模式状态
|
||||
if (!userChangedNoFocusModeInSettings && wasNoFocusModeBeforeSettings)
|
||||
if (isTemporarilyDisablingNoFocusMode)
|
||||
{
|
||||
// 如果用户没有在设置中修改无焦点模式,则恢复之前的状态
|
||||
Settings.Advanced.IsNoFocusMode = true;
|
||||
ToggleSwitchNoFocusMode.IsOn = true; // 同步更新设置面板中的开关状态
|
||||
isTemporarilyDisablingNoFocusMode = false;
|
||||
ApplyNoFocusMode();
|
||||
}
|
||||
// 如果用户在设置中修改了无焦点模式,则保持用户的修改
|
||||
};
|
||||
|
||||
BorderSettings.Visibility = Visibility.Visible;
|
||||
BorderSettings.RenderTransform = new TranslateTransform();
|
||||
|
||||
isOpeningOrHidingSettingsPane = true;
|
||||
@@ -477,9 +472,9 @@ namespace Ink_Canvas
|
||||
|
||||
// 根据主题选择高光颜色
|
||||
Color highlightColor;
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
(Settings.Appearance.Theme == 2 && !IsSystemThemeLight());
|
||||
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
highlightColor = Color.FromRgb(102, 204, 255); // #66ccff for dark theme
|
||||
@@ -929,7 +924,7 @@ namespace Ink_Canvas
|
||||
#region 主要的工具按鈕事件
|
||||
|
||||
/// <summary>
|
||||
/// 浮動工具欄的"套索選"按鈕事件,重定向到舊UI的<c>BtnSelect_Click</c>方法
|
||||
/// 浮動工具欄的"套索選"按鈕事件,重定向到舊UI的<c>BtnSelect_Click</c>方法
|
||||
/// </summary>
|
||||
/// <param name="sender">sender</param>
|
||||
/// <param name="e">MouseButtonEventArgs</param>
|
||||
@@ -2708,11 +2703,9 @@ namespace Ink_Canvas
|
||||
// 如果当前在设置面板中,需要先恢复无焦点模式状态
|
||||
if (BorderSettings.Visibility == Visibility.Visible)
|
||||
{
|
||||
// 如果用户没有在设置中修改无焦点模式,则恢复之前的状态
|
||||
if (!userChangedNoFocusModeInSettings && wasNoFocusModeBeforeSettings)
|
||||
if (isTemporarilyDisablingNoFocusMode)
|
||||
{
|
||||
Settings.Advanced.IsNoFocusMode = true;
|
||||
ToggleSwitchNoFocusMode.IsOn = true;
|
||||
isTemporarilyDisablingNoFocusMode = false;
|
||||
ApplyNoFocusMode();
|
||||
}
|
||||
SaveSettingsToFile();
|
||||
@@ -2727,11 +2720,9 @@ namespace Ink_Canvas
|
||||
{
|
||||
if (BorderSettings.Visibility == Visibility.Visible)
|
||||
{
|
||||
// 如果用户没有在设置中修改无焦点模式,则恢复之前的状态
|
||||
if (!userChangedNoFocusModeInSettings && wasNoFocusModeBeforeSettings)
|
||||
if (isTemporarilyDisablingNoFocusMode)
|
||||
{
|
||||
Settings.Advanced.IsNoFocusMode = true;
|
||||
ToggleSwitchNoFocusMode.IsOn = true;
|
||||
isTemporarilyDisablingNoFocusMode = false;
|
||||
ApplyNoFocusMode();
|
||||
}
|
||||
SaveSettingsToFile();
|
||||
@@ -2777,12 +2768,12 @@ namespace Ink_Canvas
|
||||
}
|
||||
else
|
||||
{
|
||||
// 临时禁用无焦点模式以避免下拉选项被遮挡
|
||||
BorderSettings.Visibility = Visibility.Visible;
|
||||
wasNoFocusModeBeforeSettings = Settings.Advanced.IsNoFocusMode;
|
||||
userChangedNoFocusModeInSettings = false; // 重置用户修改标志
|
||||
if (wasNoFocusModeBeforeSettings)
|
||||
{
|
||||
Settings.Advanced.IsNoFocusMode = false;
|
||||
isTemporarilyDisablingNoFocusMode = true;
|
||||
ApplyNoFocusMode();
|
||||
}
|
||||
|
||||
@@ -2795,7 +2786,7 @@ namespace Ink_Canvas
|
||||
// 滑动动画
|
||||
var slideAnimation = new DoubleAnimation
|
||||
{
|
||||
From = BorderSettings.RenderTransform.Value.OffsetX - 440, // 滑动距离
|
||||
From = BorderSettings.RenderTransform.Value.OffsetX - 490, // 滑动距离
|
||||
To = 0,
|
||||
Duration = TimeSpan.FromSeconds(0.6)
|
||||
};
|
||||
@@ -2807,7 +2798,6 @@ namespace Ink_Canvas
|
||||
|
||||
sb.Completed += (s, _) => { isOpeningOrHidingSettingsPane = false; };
|
||||
|
||||
BorderSettings.Visibility = Visibility.Visible;
|
||||
BorderSettings.RenderTransform = new TranslateTransform();
|
||||
|
||||
isOpeningOrHidingSettingsPane = true;
|
||||
@@ -2854,36 +2844,32 @@ namespace Ink_Canvas
|
||||
|
||||
if (Settings.Canvas.ClearCanvasAndClearTimeMachine) timeMachine.ClearStrokeHistory();
|
||||
|
||||
// 清空墨迹后模拟用户重新手动开关多指书写功能
|
||||
SimulateMultiTouchToggle();
|
||||
if (Settings.Gesture.IsEnableMultiTouchMode && ToggleSwitchEnableMultiTouchMode != null && ToggleSwitchEnableMultiTouchMode.IsOn)
|
||||
{
|
||||
ReinitializeMultiTouchMode();
|
||||
}
|
||||
}
|
||||
|
||||
private bool lastIsInMultiTouchMode;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟用户重新手动开关多指书写功能
|
||||
/// </summary>
|
||||
private void SimulateMultiTouchToggle()
|
||||
private void ReinitializeMultiTouchMode()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查多指书写模式是否启用
|
||||
if (ToggleSwitchEnableMultiTouchMode != null && ToggleSwitchEnableMultiTouchMode.IsOn)
|
||||
if (!isInMultiTouchMode)
|
||||
{
|
||||
// 先关闭多指书写模式
|
||||
ToggleSwitchEnableMultiTouchMode.IsOn = false;
|
||||
|
||||
// 使用Dispatcher.BeginInvoke确保UI更新完成后再重新开启
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
// 重新开启多指书写模式
|
||||
ToggleSwitchEnableMultiTouchMode.IsOn = true;
|
||||
}), DispatcherPriority.Background);
|
||||
isInMultiTouchMode = true;
|
||||
}
|
||||
|
||||
inkCanvas.TouchDown -= Main_Grid_TouchDown;
|
||||
inkCanvas.TouchDown += MainWindow_TouchDown;
|
||||
inkCanvas.StylusDown += MainWindow_StylusDown;
|
||||
inkCanvas.StylusMove += MainWindow_StylusMove;
|
||||
inkCanvas.StylusUp += MainWindow_StylusUp;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"模拟多指书写开关时发生错误: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3114,7 +3100,15 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
StackPanelPPTButtons.Visibility = Visibility.Collapsed;
|
||||
Topmost = false;
|
||||
|
||||
if (Settings.Advanced.EnableUIAccessTopMost)
|
||||
{
|
||||
Topmost = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Topmost = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3717,18 +3711,18 @@ namespace Ink_Canvas
|
||||
// 根据主题设置高光颜色
|
||||
Color highlightBackgroundColor;
|
||||
Color highlightBarColor;
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
bool isDarkTheme = Settings.Appearance.Theme == 1 ||
|
||||
(Settings.Appearance.Theme == 2 && !IsSystemThemeLight());
|
||||
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
highlightBackgroundColor = Color.FromArgb(21, 102, 204, 255);
|
||||
highlightBarColor = Color.FromRgb(102, 204, 255);
|
||||
highlightBackgroundColor = Color.FromArgb(21, 102, 204, 255);
|
||||
highlightBarColor = Color.FromRgb(102, 204, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
highlightBackgroundColor = Color.FromArgb(21, 59, 130, 246);
|
||||
highlightBarColor = Color.FromRgb(37, 99, 235);
|
||||
highlightBackgroundColor = Color.FromArgb(21, 59, 130, 246);
|
||||
highlightBarColor = Color.FromRgb(37, 99, 235);
|
||||
}
|
||||
|
||||
// 设置高光背景颜色
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Application = System.Windows.Application;
|
||||
@@ -77,7 +78,7 @@ namespace Ink_Canvas
|
||||
|
||||
#region PPT State Management
|
||||
private bool wasFloatingBarFoldedWhenEnterSlideShow;
|
||||
private bool isEnteredSlideShowEndEvent; //防止重复调用本函数导致墨迹保存失效
|
||||
private bool isEnteredSlideShowEndEvent;
|
||||
private bool isPresentationHaveBlackSpace;
|
||||
|
||||
// 长按翻页相关字段
|
||||
@@ -104,10 +105,11 @@ namespace Ink_Canvas
|
||||
#region PPT Managers
|
||||
private PPTManager _pptManager;
|
||||
private MultiPPTInkManager _multiPPTInkManager;
|
||||
private PPTInkManager _singlePPTInkManager;
|
||||
private PPTUIManager _pptUIManager;
|
||||
|
||||
/// <summary>
|
||||
/// 获取PPT管理器实例(供UI管理器使用)
|
||||
/// 获取PPT管理器实例
|
||||
/// </summary>
|
||||
public PPTManager PPTManager => _pptManager;
|
||||
#endregion
|
||||
@@ -133,11 +135,19 @@ namespace Ink_Canvas
|
||||
_pptManager.PresentationClose += OnPPTPresentationClose;
|
||||
_pptManager.SlideShowStateChanged += OnPPTSlideShowStateChanged;
|
||||
|
||||
// 初始化多PPT墨迹管理器
|
||||
_multiPPTInkManager = new MultiPPTInkManager();
|
||||
_multiPPTInkManager.IsAutoSaveEnabled = Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
|
||||
_multiPPTInkManager.AutoSaveLocation = Settings.Automation.AutoSavedStrokesLocation;
|
||||
_multiPPTInkManager.PPTManager = _pptManager;
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager = new PPTInkManager();
|
||||
_singlePPTInkManager.IsAutoSaveEnabled = Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
|
||||
_singlePPTInkManager.AutoSaveLocation = Settings.Automation.AutoSavedStrokesLocation;
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager = new MultiPPTInkManager();
|
||||
_multiPPTInkManager.IsAutoSaveEnabled = Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
|
||||
_multiPPTInkManager.AutoSaveLocation = Settings.Automation.AutoSavedStrokesLocation;
|
||||
_multiPPTInkManager.PPTManager = _pptManager;
|
||||
}
|
||||
|
||||
// 初始化UI管理器
|
||||
_pptUIManager = new PPTUIManager(this);
|
||||
@@ -421,10 +431,12 @@ namespace Ink_Canvas
|
||||
{
|
||||
_pptManager?.Dispose();
|
||||
_multiPPTInkManager?.Dispose();
|
||||
_singlePPTInkManager?.Dispose();
|
||||
_longPressTimer?.Stop();
|
||||
_longPressTimer = null;
|
||||
_pptManager = null;
|
||||
_multiPPTInkManager = null;
|
||||
_singlePPTInkManager = null;
|
||||
_pptUIManager = null;
|
||||
|
||||
// 清理PowerPoint进程守护
|
||||
@@ -509,8 +521,14 @@ namespace Ink_Canvas
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("PPT连接已断开", LogHelper.LogType.Event);
|
||||
// 清理墨迹管理器
|
||||
_multiPPTInkManager?.ClearAllStrokes();
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.ClearAllStrokes();
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.ClearAllStrokes();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -535,8 +553,14 @@ namespace Ink_Canvas
|
||||
TimeMachineHistories[0] = null;
|
||||
}
|
||||
|
||||
// 初始化多PPT墨迹管理器
|
||||
_multiPPTInkManager?.InitializePresentation(pres);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.InitializePresentation(pres);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.InitializePresentation(pres);
|
||||
}
|
||||
|
||||
// 处理跳转到首页或上次播放页的逻辑
|
||||
HandlePresentationOpenNavigation(pres);
|
||||
@@ -570,11 +594,15 @@ namespace Ink_Canvas
|
||||
{
|
||||
Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// 保存所有墨迹
|
||||
_multiPPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
|
||||
// 移除演示文稿管理器
|
||||
_multiPPTInkManager?.RemovePresentation(pres);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
_multiPPTInkManager?.RemovePresentation(pres);
|
||||
}
|
||||
|
||||
_pptUIManager?.UpdateConnectionStatus(false);
|
||||
});
|
||||
@@ -629,7 +657,6 @@ namespace Ink_Canvas
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果关闭了PPT自动收纳功能,但用户当前在收纳模式下,进入PPT时取消收纳以提供更好的使用体验
|
||||
if (isFloatingBarFolded)
|
||||
{
|
||||
await UnFoldFloatingBar(new object());
|
||||
@@ -640,11 +667,16 @@ namespace Ink_Canvas
|
||||
|
||||
await Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// 获取当前活跃的演示文稿并切换到对应的墨迹管理器
|
||||
var activePresentation = _pptManager?.GetCurrentActivePresentation();
|
||||
if (activePresentation != null)
|
||||
{
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理跳转到首页或上次播放位置
|
||||
@@ -720,6 +752,22 @@ namespace Ink_Canvas
|
||||
{
|
||||
UpdateCurrentToolMode("pen");
|
||||
SetFloatingBarHighlightPosition("pen");
|
||||
if (Settings.Appearance.IsShowQuickColorPalette && QuickColorPalettePanel != null && QuickColorPaletteSingleRowPanel != null)
|
||||
{
|
||||
// 根据显示模式选择显示哪个面板
|
||||
if (Settings.Appearance.QuickColorPaletteDisplayMode == 0)
|
||||
{
|
||||
// 单行显示模式
|
||||
QuickColorPalettePanel.Visibility = Visibility.Collapsed;
|
||||
QuickColorPaletteSingleRowPanel.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 双行显示模式
|
||||
QuickColorPalettePanel.Visibility = Visibility.Visible;
|
||||
QuickColorPaletteSingleRowPanel.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -759,11 +807,16 @@ namespace Ink_Canvas
|
||||
{
|
||||
Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// 获取当前活跃的演示文稿并确保切换到正确的墨迹管理器
|
||||
var activePresentation = _pptManager?.GetCurrentActivePresentation();
|
||||
if (activePresentation != null)
|
||||
{
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
}
|
||||
}
|
||||
|
||||
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
||||
@@ -784,7 +837,6 @@ namespace Ink_Canvas
|
||||
{
|
||||
try
|
||||
{
|
||||
// 处理浮动栏状态:根据"退出PPT放映后自动恢复浮动栏状态"设置决定是否恢复
|
||||
if (Settings.Automation.IsAutoFoldAfterPPTSlideShow)
|
||||
{
|
||||
if (wasFloatingBarFoldedWhenEnterSlideShow)
|
||||
@@ -807,7 +859,6 @@ namespace Ink_Canvas
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果两个功能都关闭,确保浮动栏展开
|
||||
if (isFloatingBarFolded)
|
||||
{
|
||||
await UnFoldFloatingBar(new object());
|
||||
@@ -818,8 +869,14 @@ namespace Ink_Canvas
|
||||
if (isEnteredSlideShowEndEvent) return;
|
||||
isEnteredSlideShowEndEvent = true;
|
||||
|
||||
// 保存所有墨迹
|
||||
_multiPPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveAllStrokesToFile(pres);
|
||||
}
|
||||
|
||||
await Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
@@ -879,6 +936,9 @@ namespace Ink_Canvas
|
||||
if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
|
||||
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
|
||||
SetCurrentToolMode(InkCanvasEditingMode.None);
|
||||
|
||||
UpdateCurrentToolMode("cursor");
|
||||
SetFloatingBarHighlightPosition("cursor");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -889,8 +949,6 @@ namespace Ink_Canvas
|
||||
await Task.Delay(100);
|
||||
await Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
// 强制重新计算浮动栏位置,确保在退出PPT模式后正确复位
|
||||
// 先调用桌面模式的复位方法,然后调用通用的位置计算方法
|
||||
PureViewboxFloatingBarMarginAnimationInDesktopMode();
|
||||
ViewboxFloatingBarMarginAnimation(100, true);
|
||||
});
|
||||
@@ -941,7 +999,24 @@ namespace Ink_Canvas
|
||||
_lastPlaybackPage = page;
|
||||
new YesOrNoNotificationWindow($"上次播放到了第 {page} 页, 是否立即跳转", () =>
|
||||
{
|
||||
_shouldNavigateToLastPage = true;
|
||||
try
|
||||
{
|
||||
if (_pptManager?.PPTApplication != null)
|
||||
{
|
||||
if (_pptManager.PPTApplication.SlideShowWindows.Count >= 1)
|
||||
{
|
||||
pres.SlideShowWindow.View.GotoSlide(page);
|
||||
}
|
||||
else
|
||||
{
|
||||
pres.Windows[1].View.GotoSlide(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"跳转到第{page}页失败: {ex}", LogHelper.LogType.Error);
|
||||
}
|
||||
}).ShowDialog();
|
||||
}
|
||||
}
|
||||
@@ -1060,7 +1135,16 @@ namespace Ink_Canvas
|
||||
{
|
||||
try
|
||||
{
|
||||
var strokes = _multiPPTInkManager?.LoadSlideStrokes(slideIndex);
|
||||
StrokeCollection strokes = null;
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
strokes = _singlePPTInkManager?.LoadSlideStrokes(slideIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
strokes = _multiPPTInkManager?.LoadSlideStrokes(slideIndex);
|
||||
}
|
||||
|
||||
if (strokes != null)
|
||||
{
|
||||
inkCanvas.Strokes.Clear();
|
||||
@@ -1080,15 +1164,18 @@ namespace Ink_Canvas
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取当前活跃的演示文稿
|
||||
var activePresentation = _pptManager?.GetCurrentActivePresentation();
|
||||
if (activePresentation != null)
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
// 切换到对应的墨迹管理器
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
|
||||
// 重置锁定状态
|
||||
_multiPPTInkManager?.ResetCurrentPresentationLockState();
|
||||
_singlePPTInkManager?.ResetLockState();
|
||||
}
|
||||
else
|
||||
{
|
||||
var activePresentation = _pptManager?.GetCurrentActivePresentation();
|
||||
if (activePresentation != null)
|
||||
{
|
||||
_multiPPTInkManager?.SwitchToPresentation(activePresentation);
|
||||
_multiPPTInkManager?.ResetCurrentPresentationLockState();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1202,26 +1289,41 @@ namespace Ink_Canvas
|
||||
// 如果有当前墨迹且不是第一次切换,先保存到当前页面
|
||||
if (inkCanvas.Strokes.Count > 0 && currentSlideIndex > 0 && currentSlideIndex != newSlideIndex)
|
||||
{
|
||||
// 检查是否可以写入墨迹
|
||||
bool canWrite = _multiPPTInkManager?.CanWriteInk(currentSlideIndex) == true;
|
||||
|
||||
if (canWrite)
|
||||
bool canWrite = false;
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
// 正常保存
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlideIndex, inkCanvas.Strokes);
|
||||
canWrite = _singlePPTInkManager?.CanWriteInk(currentSlideIndex) == true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 墨迹被锁定,跳过保存以避免墨迹错页
|
||||
canWrite = _multiPPTInkManager?.CanWriteInk(currentSlideIndex) == true;
|
||||
}
|
||||
|
||||
if (canWrite)
|
||||
{
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveCurrentSlideStrokes(currentSlideIndex, inkCanvas.Strokes);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlideIndex, inkCanvas.Strokes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (inkCanvas.Strokes.Count > 0 && currentSlideIndex <= 0)
|
||||
{
|
||||
// 无法获取当前页面索引时,不保存墨迹,直接清空
|
||||
}
|
||||
|
||||
// 切换到新页面并加载墨迹
|
||||
var newStrokes = _multiPPTInkManager?.SwitchToSlide(newSlideIndex, null);
|
||||
StrokeCollection newStrokes = null;
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
newStrokes = _singlePPTInkManager?.SwitchToSlide(newSlideIndex, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
newStrokes = _multiPPTInkManager?.SwitchToSlide(newSlideIndex, null);
|
||||
}
|
||||
if (newStrokes != null)
|
||||
{
|
||||
inkCanvas.Strokes.Clear();
|
||||
@@ -1362,7 +1464,14 @@ namespace Ink_Canvas
|
||||
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
||||
if (currentSlide > 0)
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存截图(如果启用)
|
||||
@@ -1402,7 +1511,14 @@ namespace Ink_Canvas
|
||||
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
||||
if (currentSlide > 0)
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存截图(如果启用)
|
||||
@@ -1432,7 +1548,7 @@ namespace Ink_Canvas
|
||||
});
|
||||
}
|
||||
|
||||
private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
private void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = sender;
|
||||
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
|
||||
@@ -1454,7 +1570,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
private async void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
|
||||
private void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
lastBorderMouseDownObject = null;
|
||||
if (sender == PPTLSPageButton)
|
||||
@@ -1562,7 +1678,14 @@ namespace Ink_Canvas
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
if (Settings.PowerPointSettings.IsSupportWPS)
|
||||
{
|
||||
_singlePPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
else
|
||||
{
|
||||
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
||||
}
|
||||
timeMachine.ClearStrokeHistory();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -433,8 +433,8 @@ namespace Ink_Canvas
|
||||
|
||||
public void UpdateCustomIconsInComboBox()
|
||||
{
|
||||
// 保留前11个内置图标选项
|
||||
while (ComboBoxFloatingBarImg.Items.Count > 11)
|
||||
// 保留前12个内置图标选项
|
||||
while (ComboBoxFloatingBarImg.Items.Count > 12)
|
||||
{
|
||||
ComboBoxFloatingBarImg.Items.RemoveAt(ComboBoxFloatingBarImg.Items.Count - 1);
|
||||
}
|
||||
@@ -2611,17 +2611,17 @@ namespace Ink_Canvas
|
||||
Settings.RandSettings.UseLegacyTimerUI = ToggleSwitchUseLegacyTimerUI.IsOn;
|
||||
if (ToggleSwitchUseLegacyTimerUI.IsOn)
|
||||
{
|
||||
ToggleSwitchUseSeewoStyleUI.IsOn = false;
|
||||
Settings.RandSettings.UseSeewoStyleUI = false;
|
||||
ToggleSwitchUseNewStyleUI.IsOn = false;
|
||||
Settings.RandSettings.UseNewStyleUI = false;
|
||||
}
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchUseSeewoStyleUI_Toggled(object sender, RoutedEventArgs e)
|
||||
private void ToggleSwitchUseNewStyleUI_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
Settings.RandSettings.UseSeewoStyleUI = ToggleSwitchUseSeewoStyleUI.IsOn;
|
||||
if (ToggleSwitchUseSeewoStyleUI.IsOn)
|
||||
Settings.RandSettings.UseNewStyleUI = ToggleSwitchUseNewStyleUI.IsOn;
|
||||
if (ToggleSwitchUseNewStyleUI.IsOn)
|
||||
{
|
||||
ToggleSwitchUseLegacyTimerUI.IsOn = false;
|
||||
Settings.RandSettings.UseLegacyTimerUI = false;
|
||||
@@ -2629,6 +2629,34 @@ namespace Ink_Canvas
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableOvertimeCountUp_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
Settings.RandSettings.EnableOvertimeCountUp = ToggleSwitchEnableOvertimeCountUp.IsOn;
|
||||
|
||||
if (!ToggleSwitchEnableOvertimeCountUp.IsOn)
|
||||
{
|
||||
ToggleSwitchEnableOvertimeRedText.IsOn = false;
|
||||
Settings.RandSettings.EnableOvertimeRedText = false;
|
||||
}
|
||||
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableOvertimeRedText_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
|
||||
if (ToggleSwitchEnableOvertimeRedText.IsOn && !ToggleSwitchEnableOvertimeCountUp.IsOn)
|
||||
{
|
||||
ToggleSwitchEnableOvertimeRedText.IsOn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Settings.RandSettings.EnableOvertimeRedText = ToggleSwitchEnableOvertimeRedText.IsOn;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void TimerVolumeSlider_ValueChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
@@ -2636,6 +2664,42 @@ namespace Ink_Canvas
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchEnableProgressiveReminder_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
Settings.RandSettings.EnableProgressiveReminder = ToggleSwitchEnableProgressiveReminder.IsOn;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ProgressiveReminderVolumeSlider_ValueChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
Settings.RandSettings.ProgressiveReminderVolume = ProgressiveReminderVolumeSlider.Value;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ButtonSelectCustomProgressiveReminderSound_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
|
||||
{
|
||||
Title = "选择渐进提醒音频文件",
|
||||
Filter = "音频文件 (*.wav)|*.wav|所有文件 (*.*)|*.*",
|
||||
DefaultExt = "wav"
|
||||
};
|
||||
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
{
|
||||
Settings.RandSettings.ProgressiveReminderSoundPath = openFileDialog.FileName;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
}
|
||||
|
||||
private void ButtonResetProgressiveReminderSound_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Settings.RandSettings.ProgressiveReminderSoundPath = "";
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ButtonSelectCustomTimerSound_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
|
||||
@@ -3181,6 +3245,149 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
|
||||
private async void ManualUpdateButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ManualUpdateButton.IsEnabled = false;
|
||||
ManualUpdateButton.Content = "正在检查更新...";
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Manual update button clicked");
|
||||
|
||||
// 使用当前选择的更新通道检查更新
|
||||
var (remoteVersion, lineGroup, apiReleaseNotes) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel, true, false);
|
||||
|
||||
if (remoteVersion != null)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"ManualUpdate | Found new version: {remoteVersion}");
|
||||
|
||||
// 获取当前版本
|
||||
string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
|
||||
// 创建并显示更新窗口
|
||||
HasNewUpdateWindow updateWindow = new HasNewUpdateWindow(currentVersion, remoteVersion, "", apiReleaseNotes);
|
||||
updateWindow.Owner = Application.Current.MainWindow;
|
||||
bool? dialogResult = updateWindow.ShowDialog();
|
||||
|
||||
// 如果窗口被关闭但没有点击按钮,则不执行任何操作
|
||||
if (dialogResult != true)
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | Update dialog closed without selection");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据用户选择处理更新
|
||||
switch (updateWindow.Result)
|
||||
{
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateNow:
|
||||
// 立即更新:显示下载进度,下载完成后立即安装
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User chose to update now");
|
||||
|
||||
// 显示下载进度提示
|
||||
MessageBox.Show("开始下载更新,请稍候...", "正在更新", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
// 下载更新文件,使用多线路组下载功能
|
||||
bool isDownloadSuccessful = await DownloadUpdateWithFallback(remoteVersion, lineGroup, Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful)
|
||||
{
|
||||
// 下载成功,提示用户准备安装
|
||||
MessageBoxResult result = MessageBox.Show("更新已下载完成,点击确定后将关闭软件并安装新版本!", "安装更新", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
|
||||
// 只有当用户点击确定按钮后才关闭软件
|
||||
if (result == MessageBoxResult.OK)
|
||||
{
|
||||
// 设置为用户主动退出,避免被看门狗判定为崩溃
|
||||
App.IsAppExitByUser = true;
|
||||
|
||||
// 准备批处理脚本
|
||||
AutoUpdateHelper.InstallNewVersionApp(remoteVersion, true);
|
||||
|
||||
// 关闭软件,让安装程序接管
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User cancelled update installation");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 下载失败
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.UpdateLater:
|
||||
// 稍后更新:静默下载,在软件关闭时自动安装
|
||||
LogHelper.WriteLogToFile("ManualUpdate | User chose to update later");
|
||||
|
||||
// 不管设置如何,都进行下载,使用多线路组下载功能
|
||||
isDownloadSuccessful = await DownloadUpdateWithFallback(remoteVersion, lineGroup, Settings.Startup.UpdateChannel);
|
||||
|
||||
if (isDownloadSuccessful)
|
||||
{
|
||||
LogHelper.WriteLogToFile("ManualUpdate | 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("ManualUpdate | Update download failed", LogHelper.LogType.Error);
|
||||
MessageBox.Show("更新下载失败,请检查网络连接后重试。", "下载失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
break;
|
||||
|
||||
case HasNewUpdateWindow.UpdateResult.SkipVersion:
|
||||
// 跳过该版本:记录到设置中
|
||||
LogHelper.WriteLogToFile($"ManualUpdate | User chose to skip version {remoteVersion}");
|
||||
|
||||
// 记录要跳过的版本号
|
||||
Settings.Startup.SkippedVersion = remoteVersion;
|
||||
|
||||
// 保存设置到文件
|
||||
SaveSettingsToFile();
|
||||
|
||||
// 通知用户
|
||||
MessageBox.Show($"已设置跳过版本 {remoteVersion},在下次发布新版本之前不会再提示更新。",
|
||||
"已跳过此版本",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有更新
|
||||
LogHelper.WriteLogToFile("ManualUpdate | No updates available");
|
||||
MessageBox.Show("当前已是最新版本!", "无可用更新", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"Error in ManualUpdateButton_Click: {ex.Message}", LogHelper.LogType.Error);
|
||||
MessageBox.Show(
|
||||
$"手动更新过程中发生错误: {ex.Message}",
|
||||
"更新错误",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 恢复按钮状态
|
||||
ManualUpdateButton.IsEnabled = true;
|
||||
ManualUpdateButton.Content = "手动更新";
|
||||
}
|
||||
}
|
||||
|
||||
private async void FixVersionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 显示确认对话框
|
||||
|
||||
@@ -883,9 +883,22 @@ namespace Ink_Canvas
|
||||
|
||||
// 计时器设置
|
||||
ToggleSwitchUseLegacyTimerUI.IsOn = Settings.RandSettings.UseLegacyTimerUI;
|
||||
ToggleSwitchUseSeewoStyleUI.IsOn = Settings.RandSettings.UseSeewoStyleUI;
|
||||
ToggleSwitchUseNewStyleUI.IsOn = Settings.RandSettings.UseNewStyleUI;
|
||||
ToggleSwitchEnableOvertimeCountUp.IsOn = Settings.RandSettings.EnableOvertimeCountUp;
|
||||
|
||||
bool canEnableRedText = Settings.RandSettings.EnableOvertimeCountUp && Settings.RandSettings.EnableOvertimeRedText;
|
||||
ToggleSwitchEnableOvertimeRedText.IsOn = canEnableRedText;
|
||||
if (!canEnableRedText)
|
||||
{
|
||||
Settings.RandSettings.EnableOvertimeRedText = false;
|
||||
}
|
||||
|
||||
TimerVolumeSlider.Value = Settings.RandSettings.TimerVolume;
|
||||
|
||||
// 渐进提醒设置
|
||||
ToggleSwitchEnableProgressiveReminder.IsOn = Settings.RandSettings.EnableProgressiveReminder;
|
||||
ProgressiveReminderVolumeSlider.Value = Settings.RandSettings.ProgressiveReminderVolume;
|
||||
|
||||
// 加载自定义点名背景
|
||||
UpdatePickNameBackgroundsInComboBox();
|
||||
|
||||
@@ -905,8 +918,21 @@ namespace Ink_Canvas
|
||||
ToggleSwitchExternalCaller.IsOn = Settings.RandSettings.DirectCallCiRand;
|
||||
ComboBoxExternalCallerType.SelectedIndex = Settings.RandSettings.ExternalCallerType;
|
||||
ToggleSwitchUseLegacyTimerUI.IsOn = Settings.RandSettings.UseLegacyTimerUI;
|
||||
ToggleSwitchUseSeewoStyleUI.IsOn = Settings.RandSettings.UseSeewoStyleUI;
|
||||
ToggleSwitchUseNewStyleUI.IsOn = Settings.RandSettings.UseNewStyleUI;
|
||||
ToggleSwitchEnableOvertimeCountUp.IsOn = Settings.RandSettings.EnableOvertimeCountUp;
|
||||
|
||||
bool canEnableRedText = Settings.RandSettings.EnableOvertimeCountUp && Settings.RandSettings.EnableOvertimeRedText;
|
||||
ToggleSwitchEnableOvertimeRedText.IsOn = canEnableRedText;
|
||||
if (!canEnableRedText)
|
||||
{
|
||||
Settings.RandSettings.EnableOvertimeRedText = false;
|
||||
}
|
||||
|
||||
TimerVolumeSlider.Value = Settings.RandSettings.TimerVolume;
|
||||
|
||||
// 渐进提醒设置
|
||||
ToggleSwitchEnableProgressiveReminder.IsOn = Settings.RandSettings.EnableProgressiveReminder;
|
||||
ProgressiveReminderVolumeSlider.Value = Settings.RandSettings.ProgressiveReminderVolume;
|
||||
}
|
||||
|
||||
// ModeSettings
|
||||
|
||||
@@ -61,10 +61,10 @@ namespace Ink_Canvas
|
||||
private Timer timerCheckAutoFold = new Timer();
|
||||
private string AvailableLatestVersion;
|
||||
private Timer timerCheckAutoUpdateWithSilence = new Timer();
|
||||
private Timer timerCheckAutoUpdateRetry = new Timer();
|
||||
private Timer timerCheckAutoUpdateRetry = new Timer();
|
||||
private bool isHidingSubPanelsWhenInking; // 避免书写时触发二次关闭二级菜单导致动画不连续
|
||||
private int updateCheckRetryCount = 0;
|
||||
private const int MAX_UPDATE_CHECK_RETRIES = 6;
|
||||
private int updateCheckRetryCount = 0;
|
||||
private const int MAX_UPDATE_CHECK_RETRIES = 6;
|
||||
private Timer timerDisplayTime = new Timer();
|
||||
private Timer timerDisplayDate = new Timer();
|
||||
private Timer timerNtpSync = new Timer();
|
||||
@@ -120,7 +120,7 @@ namespace Ink_Canvas
|
||||
timerCheckAutoUpdateWithSilence.Elapsed += timerCheckAutoUpdateWithSilence_Elapsed;
|
||||
timerCheckAutoUpdateWithSilence.Interval = 1000 * 60 * 10;
|
||||
timerCheckAutoUpdateRetry.Elapsed += timerCheckAutoUpdateRetry_Elapsed;
|
||||
timerCheckAutoUpdateRetry.Interval = 1000 * 60 * 10;
|
||||
timerCheckAutoUpdateRetry.Interval = 1000 * 60 * 10;
|
||||
WaterMarkTime.DataContext = nowTimeVM;
|
||||
WaterMarkDate.DataContext = nowTimeVM;
|
||||
timerDisplayTime.Elapsed += TimerDisplayTime_Elapsed;
|
||||
@@ -863,7 +863,7 @@ namespace Ink_Canvas
|
||||
|
||||
// 执行更新检查
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Retrying update check after failure");
|
||||
|
||||
|
||||
// 清除之前的更新状态
|
||||
AvailableLatestVersion = null;
|
||||
AvailableLatestLineGroup = null;
|
||||
@@ -878,7 +878,7 @@ namespace Ink_Canvas
|
||||
// 检查更新成功,重置重试计数
|
||||
updateCheckRetryCount = 0;
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Retry successful, found new version: {AvailableLatestVersion}");
|
||||
|
||||
|
||||
// 停止重试定时器,因为已经找到了更新
|
||||
return;
|
||||
}
|
||||
@@ -886,7 +886,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 检查更新仍然失败,继续重试
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Retry {updateCheckRetryCount} failed, will retry in 10 minutes");
|
||||
|
||||
|
||||
// 重新启动定时器,10分钟后再次尝试
|
||||
timerCheckAutoUpdateRetry.Start();
|
||||
}
|
||||
@@ -894,7 +894,7 @@ namespace Ink_Canvas
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | Error in retry check: {ex.Message}", LogHelper.LogType.Error);
|
||||
|
||||
|
||||
// 出错时也重新启动定时器,稍后再检查
|
||||
if (updateCheckRetryCount <= MAX_UPDATE_CHECK_RETRIES)
|
||||
{
|
||||
@@ -910,10 +910,10 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 停止重试定时器
|
||||
timerCheckAutoUpdateRetry.Stop();
|
||||
|
||||
|
||||
// 重置重试计数
|
||||
updateCheckRetryCount = 0;
|
||||
|
||||
|
||||
LogHelper.WriteLogToFile("AutoUpdate | Update check retry state reset");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -259,7 +259,6 @@ namespace Ink_Canvas
|
||||
|
||||
// 只保留普通橡皮逻辑
|
||||
TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None;
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(50, 50);
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint
|
||||
&& inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke)
|
||||
{
|
||||
@@ -682,8 +681,6 @@ namespace Ink_Canvas
|
||||
|
||||
if (Settings.Advanced.IsSpecialScreen)
|
||||
boundWidth *= Settings.Advanced.TouchMultiplier;
|
||||
|
||||
inkCanvas.EraserShape = new EllipseStylusShape(boundWidth, boundWidth);
|
||||
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
|
||||
isPalmEraserActive = true;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Windows;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("CJK_mkp")]
|
||||
[assembly: AssemblyProduct("InkCanvasForClass")]
|
||||
[assembly: AssemblyCopyright("Copyright © HARKOTEK Studio 2024")]
|
||||
[assembly: AssemblyCopyright("Copyright © CJK_mkp 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -49,5 +49,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.7.13.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.13.0")]
|
||||
[assembly: AssemblyVersion("1.7.15.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.15.0")]
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>dist\</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
</Project>
|
||||
@@ -74,5 +74,14 @@ namespace Ink_Canvas.Properties {
|
||||
return ResourceManager.GetStream("TimerDownNotice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
|
||||
/// </summary>
|
||||
internal static UnmanagedMemoryStream ProgressiveAudio {
|
||||
get {
|
||||
return ResourceManager.GetStream("ProgressiveAudio", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,4 +121,7 @@
|
||||
<data name="TimerDownNotice" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\TimerDownNotice.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="ProgressiveAudio" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ProgressiveAudio.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -591,6 +591,9 @@ namespace Ink_Canvas
|
||||
|
||||
[JsonProperty("isAlwaysOnTop")]
|
||||
public bool IsAlwaysOnTop { get; set; } = true;
|
||||
|
||||
[JsonProperty("enableUIAccessTopMost")]
|
||||
public bool EnableUIAccessTopMost { get; set; } = false;
|
||||
}
|
||||
|
||||
public class InkToShape
|
||||
@@ -631,12 +634,22 @@ namespace Ink_Canvas
|
||||
public List<CustomPickNameBackground> CustomPickNameBackgrounds { get; set; } = new List<CustomPickNameBackground>();
|
||||
[JsonProperty("useLegacyTimerUI")]
|
||||
public bool UseLegacyTimerUI { get; set; } = false;
|
||||
[JsonProperty("useSeewoStyleUI")]
|
||||
public bool UseSeewoStyleUI { get; set; } = false;
|
||||
[JsonProperty("useNewStyleUI")]
|
||||
public bool UseNewStyleUI { get; set; } = true;
|
||||
[JsonProperty("timerVolume")]
|
||||
public double TimerVolume { get; set; } = 1.0;
|
||||
[JsonProperty("customTimerSoundPath")]
|
||||
public string CustomTimerSoundPath { get; set; } = "";
|
||||
[JsonProperty("enableOvertimeCountUp")]
|
||||
public bool EnableOvertimeCountUp { get; set; } = false;
|
||||
[JsonProperty("enableOvertimeRedText")]
|
||||
public bool EnableOvertimeRedText { get; set; } = false;
|
||||
[JsonProperty("enableProgressiveReminder")]
|
||||
public bool EnableProgressiveReminder { get; set; } = false;
|
||||
[JsonProperty("progressiveReminderVolume")]
|
||||
public double ProgressiveReminderVolume { get; set; } = 1.0;
|
||||
[JsonProperty("progressiveReminderSoundPath")]
|
||||
public string ProgressiveReminderSoundPath { get; set; } = "";
|
||||
}
|
||||
|
||||
public class CustomPickNameBackground
|
||||
|
||||
@@ -113,15 +113,15 @@
|
||||
<BitmapImage x:Key="TimerWindowClockIcon" UriSource="/Resources/Icons-Fluent/ic_fluent_timer_24_regular-light.png"/>
|
||||
|
||||
<!-- 倒计时窗口主题颜色 -->
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowBackground" Color="#1f1f1f"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowBorderBrush" Color="#E0E0E0"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowTextForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowButtonBackground" Color="#2a2a2a"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowButtonForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowDigitForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowTitleForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowPrimaryButtonBackground" Color="#4CAF50"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowPrimaryButtonForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowBackground" Color="#1f1f1f"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowBorderBrush" Color="#E0E0E0"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowTextForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowButtonBackground" Color="#2a2a2a"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowButtonForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowDigitForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowTitleForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowPrimaryButtonBackground" Color="#4CAF50"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowPrimaryButtonForeground" Color="White"/>
|
||||
|
||||
<!-- 说明书窗口主题颜色 -->
|
||||
<SolidColorBrush x:Key="OperatingGuideWindowBackground" Color="#1f1f1f"/>
|
||||
@@ -139,4 +139,10 @@
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon1" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular_white.png"/>
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon2" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular_white.png"/>
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon3" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular_white.png"/>
|
||||
|
||||
<!-- 手势选项面板图标资源 - 深色主题 -->
|
||||
<BitmapImage x:Key="MultiTouchIcon" UriSource="/Resources/new-icons/multi-touch_white.png"/>
|
||||
<BitmapImage x:Key="HandMoveIcon" UriSource="/Resources/new-icons/hand-move_white.png"/>
|
||||
<BitmapImage x:Key="ZoomIcon" UriSource="/Resources/new-icons/zoom_white.png"/>
|
||||
<BitmapImage x:Key="RotateIcon" UriSource="/Resources/new-icons/rotate_white.png"/>
|
||||
</ResourceDictionary>
|
||||
@@ -113,15 +113,15 @@
|
||||
<BitmapImage x:Key="TimerWindowClockIcon" UriSource="/Resources/Icons-Fluent/ic_fluent_timer_24_regular.png"/>
|
||||
|
||||
<!-- 倒计时窗口主题颜色 -->
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowBackground" Color="White"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowBorderBrush" Color="#E0E0E0"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowTextForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowButtonBackground" Color="#F0F0F0"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowButtonForeground" Color="#666666"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowDigitForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowTitleForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowPrimaryButtonBackground" Color="#4CAF50"/>
|
||||
<SolidColorBrush x:Key="SeewoTimerWindowPrimaryButtonForeground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowBackground" Color="White"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowBorderBrush" Color="#E0E0E0"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowTextForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowButtonBackground" Color="#F0F0F0"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowButtonForeground" Color="#666666"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowDigitForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowTitleForeground" Color="#333333"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowPrimaryButtonBackground" Color="#4CAF50"/>
|
||||
<SolidColorBrush x:Key="NewTimerWindowPrimaryButtonForeground" Color="White"/>
|
||||
|
||||
<!-- 说明书窗口主题颜色 -->
|
||||
<SolidColorBrush x:Key="OperatingGuideWindowBackground" Color="#F0F3F9"/>
|
||||
@@ -139,4 +139,10 @@
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon1" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png"/>
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon2" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png"/>
|
||||
<BitmapImage x:Key="OperatingGuideWindowControlIcon3" UriSource="/Resources/Icons-Fluent/ic_fluent_control_button_24_regular.png"/>
|
||||
|
||||
<!-- 手势选项面板图标资源 - 浅色主题 -->
|
||||
<BitmapImage x:Key="MultiTouchIcon" UriSource="/Resources/new-icons/multi-touch.png"/>
|
||||
<BitmapImage x:Key="HandMoveIcon" UriSource="/Resources/new-icons/hand-move.png"/>
|
||||
<BitmapImage x:Key="ZoomIcon" UriSource="/Resources/new-icons/zoom.png"/>
|
||||
<BitmapImage x:Key="RotateIcon" UriSource="/Resources/new-icons/rotate.png"/>
|
||||
</ResourceDictionary>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,26 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls.Primitives;
|
||||
|
||||
namespace Ink_Canvas.Windows.Controls
|
||||
{
|
||||
public class WinUI3CloseButton : ButtonBase
|
||||
{
|
||||
static WinUI3CloseButton()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(WinUI3CloseButton), new FrameworkPropertyMetadata(typeof(WinUI3CloseButton)));
|
||||
}
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => (bool)GetValue(IsActiveProperty);
|
||||
set => SetValue(IsActiveProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(
|
||||
nameof(IsActive),
|
||||
typeof(bool),
|
||||
typeof(WinUI3CloseButton),
|
||||
new PropertyMetadata(true)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Ink_Canvas.Windows.Controls"
|
||||
xmlns:system="clr-namespace:System;assembly=netstandard">
|
||||
|
||||
<Style TargetType="{x:Type local:WinUI3CloseButton}">
|
||||
<Setter Property="Width" Value="46" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource NewTimerWindowButtonForeground}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type local:WinUI3CloseButton}">
|
||||
<Border
|
||||
x:Name="ButtonBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="0,15,0,0">
|
||||
<ContentPresenter
|
||||
x:Name="PART_ContentPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsActive" Value="False">
|
||||
<Setter TargetName="PART_ContentPresenter" Property="Opacity" Value="0.382" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="#808080" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ButtonBorder" Property="Background" Value="#E81123" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ButtonBorder" Property="Background" Value="#F1707A" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- 关闭按钮图标模板 -->
|
||||
<DataTemplate x:Key="CloseButtonIconTemplate" DataType="system:String">
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Text="✕"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</DataTemplate>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -22,16 +22,16 @@ namespace Ink_Canvas
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.Interval = 50;
|
||||
InitializeUI();
|
||||
|
||||
|
||||
// 应用主题
|
||||
ApplyTheme();
|
||||
}
|
||||
|
||||
public static Window CreateTimerWindow()
|
||||
{
|
||||
if (MainWindow.Settings.RandSettings?.UseSeewoStyleUI == true)
|
||||
if (MainWindow.Settings.RandSettings?.UseNewStyleUI == true)
|
||||
{
|
||||
return new SeewoStyleTimerWindow();
|
||||
return new NewStyleTimerWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -49,46 +49,72 @@ namespace Ink_Canvas
|
||||
|
||||
TimeSpan timeSpan = DateTime.Now - startTime;
|
||||
TimeSpan totalTimeSpan = new TimeSpan(hour, minute, second);
|
||||
TimeSpan leftTimeSpan = totalTimeSpan - timeSpan;
|
||||
if (leftTimeSpan.Milliseconds > 0) leftTimeSpan += new TimeSpan(0, 0, 1);
|
||||
double spentTimePercent = timeSpan.TotalMilliseconds / (totalSeconds * 1000.0);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
ProcessBarTime.CurrentValue = 1 - spentTimePercent;
|
||||
TextBlockHour.Text = leftTimeSpan.Hours.ToString("00");
|
||||
TextBlockMinute.Text = leftTimeSpan.Minutes.ToString("00");
|
||||
TextBlockSecond.Text = leftTimeSpan.Seconds.ToString("00");
|
||||
TbCurrentTime.Text = leftTimeSpan.ToString(@"hh\:mm\:ss");
|
||||
if (spentTimePercent >= 1)
|
||||
if (!isOvertimeMode)
|
||||
{
|
||||
ProcessBarTime.CurrentValue = 0;
|
||||
TextBlockHour.Text = "00";
|
||||
TextBlockMinute.Text = "00";
|
||||
TextBlockSecond.Text = "00";
|
||||
timer.Stop();
|
||||
isTimerRunning = false;
|
||||
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Play;
|
||||
BtnStartCover.Visibility = Visibility.Visible;
|
||||
var textForeground = Application.Current.FindResource("TimerWindowTextForeground") as SolidColorBrush;
|
||||
if (textForeground != null)
|
||||
TimeSpan leftTimeSpan = totalTimeSpan - timeSpan;
|
||||
if (leftTimeSpan.Milliseconds > 0) leftTimeSpan += new TimeSpan(0, 0, 1);
|
||||
|
||||
ProcessBarTime.CurrentValue = 1 - spentTimePercent;
|
||||
TextBlockHour.Text = leftTimeSpan.Hours.ToString("00");
|
||||
TextBlockMinute.Text = leftTimeSpan.Minutes.ToString("00");
|
||||
TextBlockSecond.Text = leftTimeSpan.Seconds.ToString("00");
|
||||
TbCurrentTime.Text = leftTimeSpan.ToString(@"hh\:mm\:ss");
|
||||
|
||||
if (spentTimePercent >= 1 && MainWindow.Settings.RandSettings?.EnableOvertimeCountUp == true)
|
||||
{
|
||||
TextBlockHour.Foreground = textForeground;
|
||||
isOvertimeMode = true;
|
||||
ProcessBarTime.CurrentValue = 0;
|
||||
ProcessBarTime.Visibility = Visibility.Collapsed;
|
||||
BorderStopTime.Visibility = Visibility.Collapsed;
|
||||
|
||||
// 播放提醒音
|
||||
PlayTimerSound();
|
||||
}
|
||||
else
|
||||
else if (spentTimePercent >= 1)
|
||||
{
|
||||
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
|
||||
ProcessBarTime.CurrentValue = 0;
|
||||
TextBlockHour.Text = "00";
|
||||
TextBlockMinute.Text = "00";
|
||||
TextBlockSecond.Text = "00";
|
||||
timer.Stop();
|
||||
isTimerRunning = false;
|
||||
SymbolIconStart.Symbol = iNKORE.UI.WPF.Modern.Controls.Symbol.Play;
|
||||
BtnStartCover.Visibility = Visibility.Visible;
|
||||
var textForeground = Application.Current.FindResource("TimerWindowTextForeground") as SolidColorBrush;
|
||||
if (textForeground != null)
|
||||
{
|
||||
TextBlockHour.Foreground = textForeground;
|
||||
}
|
||||
else
|
||||
{
|
||||
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
|
||||
}
|
||||
BorderStopTime.Visibility = Visibility.Collapsed;
|
||||
|
||||
// 播放提醒音
|
||||
PlayTimerSound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSpan overtimeSpan = timeSpan - totalTimeSpan;
|
||||
TextBlockHour.Text = overtimeSpan.Hours.ToString("00");
|
||||
TextBlockMinute.Text = overtimeSpan.Minutes.ToString("00");
|
||||
TextBlockSecond.Text = overtimeSpan.Seconds.ToString("00");
|
||||
TbCurrentTime.Text = overtimeSpan.ToString(@"hh\:mm\:ss");
|
||||
|
||||
if (MainWindow.Settings.RandSettings?.EnableOvertimeRedText == true)
|
||||
{
|
||||
TextBlockHour.Foreground = Brushes.Red;
|
||||
TextBlockMinute.Foreground = Brushes.Red;
|
||||
TextBlockSecond.Foreground = Brushes.Red;
|
||||
}
|
||||
BorderStopTime.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
});
|
||||
if (spentTimePercent >= 1)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
//Play sound
|
||||
PlayTimerSound();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SoundPlayer player = new SoundPlayer();
|
||||
@@ -105,15 +131,16 @@ namespace Ink_Canvas
|
||||
bool isTimerRunning = false;
|
||||
bool isPaused = false;
|
||||
bool useLegacyUI = false;
|
||||
bool isOvertimeMode = false;
|
||||
|
||||
Timer timer = new Timer();
|
||||
|
||||
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
|
||||
|
||||
var textForeground = Application.Current.FindResource("TimerWindowTextForeground") as SolidColorBrush;
|
||||
|
||||
|
||||
if (ProcessBarTime.Visibility == Visibility.Visible && isTimerRunning == false)
|
||||
{
|
||||
ProcessBarTime.Visibility = Visibility.Collapsed;
|
||||
@@ -268,6 +295,9 @@ namespace Ink_Canvas
|
||||
TextBlockHour.Foreground = textForeground3;
|
||||
else
|
||||
TextBlockHour.Foreground = new SolidColorBrush(StringToColor("#FF5B5D5F"));
|
||||
|
||||
isOvertimeMode = false;
|
||||
ProcessBarTime.Visibility = Visibility.Visible;
|
||||
}
|
||||
else if (isTimerRunning && isPaused)
|
||||
{
|
||||
@@ -288,6 +318,9 @@ namespace Ink_Canvas
|
||||
isPaused = false;
|
||||
ProcessBarTime.CurrentValue = 0;
|
||||
ProcessBarTime.IsPaused = false;
|
||||
|
||||
isOvertimeMode = false;
|
||||
ProcessBarTime.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -390,6 +423,8 @@ namespace Ink_Canvas
|
||||
|
||||
isPaused = false;
|
||||
isTimerRunning = true;
|
||||
isOvertimeMode = false;
|
||||
ProcessBarTime.Visibility = Visibility.Visible;
|
||||
timer.Start();
|
||||
UpdateStopTime();
|
||||
BorderStopTime.Visibility = Visibility.Visible;
|
||||
@@ -439,7 +474,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 重新应用主题
|
||||
ApplyTheme();
|
||||
|
||||
|
||||
// 强制刷新UI
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
// 如果当前选中的是被删除的图标,重置为默认图标
|
||||
if (MainWindow.Settings.Appearance.FloatingBarImg >= 8 &&
|
||||
MainWindow.Settings.Appearance.FloatingBarImg - 8 >= MainWindow.Settings.Appearance.CustomFloatingBarImgs.Count)
|
||||
if (MainWindow.Settings.Appearance.FloatingBarImg >= 12 &&
|
||||
MainWindow.Settings.Appearance.FloatingBarImg - 12 >= MainWindow.Settings.Appearance.CustomFloatingBarImgs.Count)
|
||||
{
|
||||
MainWindow.Settings.Appearance.FloatingBarImg = 0;
|
||||
mainWindow.ComboBoxFloatingBarImg.SelectedIndex = 0;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<!-- 数字0-9的SVG路径数据 -->
|
||||
<Geometry x:Key="Digit0">M840.61 501.32 q0 244.71 -91.93 371.69 q-91.93 126.99 -249.34 126.99 q-101.85 0 -178.57 -56.21 q-76.72 -56.22 -119.05 -167.99 q-42.33 -111.78 -42.33 -274.48 q0 -164.02 42.33 -276.45 q42.33 -112.44 119.05 -168.65 q76.72 -56.22 178.57 -56.22 q157.41 0 249.34 127.64 q91.93 127.64 91.93 373.68 ZM310.19 501.32 q0 182.54 50.26 275.8 q50.26 93.25 138.89 93.25 q88.62 0 139.55 -92.59 q50.92 -92.59 50.92 -276.46 q0 -183.86 -50.92 -277.77 q-50.92 -93.91 -139.55 -93.91 q-88.63 0 -138.89 93.25 q-50.26 93.25 -50.26 278.44 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit1">M309 301.5 l0 -145.97 l268.76 -155.53 l113.24 0 l0 1000 l-148.71 0 l0 -830.83 l-233.29 132.33 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit2">M393.43 872.65 l427.62 0 l0 127.35 l-642.1 0 l0 -92.49 l309.66 -348.53 q84.45 -92.49 117.29 -146.78 q32.84 -54.29 32.84 -118.63 q0 -76.41 -42.23 -119.31 q-42.23 -42.89 -106.56 -42.89 q-67.03 0 -118.63 45.57 q-51.61 45.58 -74.39 124.67 l-115.28 -65.69 q30.83 -112.6 119.97 -174.26 q89.14 -61.66 199.06 -61.66 q83.11 0 149.46 34.85 q66.36 34.85 103.88 99.87 q37.53 65.01 37.53 152.14 q0 87.13 -42.22 163.54 q-42.23 76.41 -149.46 193.03 l-206.44 229.22 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit3">M649.27 472.92 q84.55 27.74 127.48 89.17 q42.93 61.42 42.93 151.25 q0 89.83 -43.59 154.56 q-43.59 64.73 -116.24 98.42 q-72.65 33.68 -158.53 33.68 q-110.96 0 -200.13 -54.82 q-89.17 -54.82 -120.87 -160.5 l113.6 -64.73 q23.78 75.29 80.58 114.26 q56.81 38.97 125.5 38.97 q71.33 0 120.21 -44.25 q48.88 -44.25 48.88 -120.87 q0 -163.81 -229.86 -163.81 l-39.63 0 l1.32 -122.85 l47.56 0 q91.15 0 138.7 -44.25 q47.56 -44.25 47.56 -111.63 q0 -63.41 -40.29 -100.39 q-40.29 -36.99 -103.7 -36.99 q-66.05 0 -113.61 40.95 q-47.56 40.95 -72.65 116.25 l-110.96 -64.73 q31.7 -108.32 114.27 -164.47 q82.56 -56.15 192.2 -56.15 q84.54 0 149.27 32.37 q64.73 32.37 100.4 91.15 q35.67 58.78 35.67 135.41 q0 72.65 -33.69 128.8 q-33.68 56.14 -102.38 85.2 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit4">M723.06 394.27 l0 264.67 l147.34 0 l0 125.51 l-147.34 0 l0 215.55 l-144.62 0 l0 -215.55 l-448.84 0 l0 -100.96 l376.54 -683.49 l156.89 0 l-364.26 658.94 l279.67 0 l0 -264.67 l144.62 0 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit5">M503.36 355.7 q87.24 0 157.04 39.6 q69.8 39.6 110.07 111.41 q40.27 71.81 40.27 165.77 q0 97.99 -43.63 172.49 q-43.63 74.5 -118.12 114.76 q-74.5 40.27 -161.75 40.27 q-102.02 0 -183.23 -50.34 q-81.2 -50.33 -114.76 -145.63 l115.44 -67.12 q25.5 65.77 72.48 100 q46.98 34.23 108.73 34.23 q79.19 0 125.5 -53.02 q46.31 -53.02 46.31 -140.27 q0 -84.56 -44.97 -139.6 q-44.97 -55.03 -128.19 -55.03 q-60.4 0 -106.04 28.19 q-45.63 28.19 -72.48 75.17 l-96.64 -48.32 l65.77 -538.26 l491.27 0 l0 124.83 l-366.44 0 l-34.9 264.43 q63.09 -33.56 138.26 -33.56 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit6">M521.48 367.79 q91.27 0 161.74 40.94 q70.47 40.94 109.39 112.08 q38.92 71.14 38.92 159.73 q0 91.27 -42.95 163.75 q-42.95 72.49 -118.79 114.1 q-75.84 41.61 -169.8 41.61 q-95.3 0 -171.14 -40.94 q-75.84 -40.94 -118.12 -113.42 q-42.28 -72.49 -42.28 -166.44 q0 -76.51 28.85 -144.3 q28.85 -67.78 89.26 -163.08 l230.87 -371.81 l159.73 0 l-198.66 315.44 l-44.29 64.43 q41.61 -12.08 87.25 -12.08 ZM498.66 869.8 q81.88 0 130.2 -51.68 q48.32 -51.68 48.32 -133.56 q0 -84.56 -47.65 -136.91 q-47.65 -52.35 -130.87 -52.35 q-81.88 0 -130.21 53.02 q-48.32 53.02 -48.32 136.24 q0 83.23 49 134.24 q49 51 129.54 51 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit7">M653.27 126.7 l-471.39 0 l0 -126.7 l636.24 0 l0 91.28 l-363.76 908.72 l-160.76 0 l359.67 -873.3 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit8">M663.8 459.71 q77.94 34.35 122.2 99.07 q44.25 64.73 44.25 151.92 q0 83.22 -41.61 149.27 q-41.61 66.05 -116.25 103.04 q-74.64 36.99 -169.75 36.99 q-97.75 0 -173.05 -36.99 q-75.3 -36.99 -117.57 -103.04 q-42.27 -66.05 -42.27 -149.27 q0 -85.87 44.91 -151.25 q44.91 -65.39 121.53 -99.74 q-62.09 -30.38 -97.76 -83.22 q-35.67 -52.84 -35.67 -120.22 q0 -70.01 38.31 -128.79 q38.31 -58.78 106.34 -93.13 q68.04 -34.34 155.22 -34.34 q87.19 0 153.24 34.34 q66.05 34.34 101.72 92.47 q35.66 58.13 35.66 129.45 q0 67.38 -34.35 120.22 q-34.34 52.84 -95.12 83.22 ZM502.64 122.85 q-68.69 0 -110.3 38.97 q-41.61 38.97 -41.61 99.74 q0 60.76 41.61 99.73 q41.61 38.97 110.3 38.97 q67.37 0 108.99 -38.97 q41.62 -38.97 41.62 -99.73 q0 -60.77 -41.62 -99.74 q-41.62 -38.97 -108.99 -38.97 ZM502.64 873.18 q79.26 0 128.8 -45.57 q49.54 -45.58 49.54 -124.84 q0 -80.58 -48.88 -128.79 q-48.88 -48.22 -129.46 -48.22 q-83.22 0 -132.1 48.22 q-48.88 48.22 -48.88 128.79 q0 79.26 49.54 124.84 q49.54 45.57 131.44 45.57 Z</Geometry>
|
||||
|
||||
<Geometry x:Key="Digit9">M500 0 q95.3 0 171.14 40.94 q75.84 40.94 118.12 113.43 q42.28 72.48 42.28 166.44 q0 76.51 -27.51 142.95 q-27.51 66.44 -90.61 165.77 l-230.87 370.47 l-159.73 0 l198.66 -315.44 l16.1 -24.16 q20.14 -32.21 26.85 -40.27 q-40.27 12.08 -85.91 12.08 q-91.27 0 -161.74 -40.93 q-70.47 -40.94 -109.39 -112.08 q-38.92 -71.15 -38.92 -159.74 q0 -91.27 42.95 -163.75 q42.95 -72.48 118.79 -114.09 q75.84 -41.61 169.8 -41.61 ZM501.34 504.7 q81.88 0 130.21 -53.02 q48.32 -53.02 48.32 -136.24 q0 -81.88 -49 -133.56 q-49 -51.68 -129.54 -51.68 q-81.88 0 -130.2 51.68 q-48.32 51.68 -48.32 133.56 q0 84.56 47.65 136.91 q47.65 52.35 130.87 52.35 Z</Geometry>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,95 @@
|
||||
<Window x:Class="Ink_Canvas.FullscreenTimerWindow"
|
||||
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"
|
||||
Topmost="True" Background="Black"
|
||||
mc:Ignorable="d" WindowStyle="None" AllowsTransparency="False"
|
||||
WindowState="Maximized" WindowStartupLocation="Manual"
|
||||
MouseLeftButtonDown="Window_MouseLeftButtonDown"
|
||||
KeyDown="Window_KeyDown">
|
||||
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="DigitResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Background="Black">
|
||||
<!-- 时间显示 -->
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 小时 -->
|
||||
<Path x:Name="FullHour1Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,20,0"/>
|
||||
<Path x:Name="FullHour2Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,20,0"/>
|
||||
|
||||
<!-- 冒号 -->
|
||||
<TextBlock x:Name="FullColon1Display" Text=":" FontSize="120" FontWeight="Bold"
|
||||
Foreground="White"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,0,20,0"/>
|
||||
|
||||
<!-- 分钟 -->
|
||||
<Path x:Name="FullMinute1Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,20,0"/>
|
||||
<Path x:Name="FullMinute2Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,20,0"/>
|
||||
|
||||
<!-- 冒号 -->
|
||||
<TextBlock x:Name="FullColon2Display" Text=":" FontSize="120" FontWeight="Bold"
|
||||
Foreground="White"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,0,20,0"/>
|
||||
|
||||
<!-- 秒 -->
|
||||
<Path x:Name="FullSecond1Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,20,0"/>
|
||||
<Path x:Name="FullSecond2Display" Data="{StaticResource Digit0}"
|
||||
Fill="White"
|
||||
Width="120" Height="120"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 退出提示 -->
|
||||
<TextBlock Text="点击屏幕退出全屏"
|
||||
FontSize="16"
|
||||
Foreground="Gray"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,0,50"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,255 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Timers;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// 全屏计时器窗口
|
||||
/// </summary>
|
||||
public partial class FullscreenTimerWindow : Window
|
||||
{
|
||||
private NewStyleTimerWindow parentWindow;
|
||||
private System.Timers.Timer updateTimer;
|
||||
|
||||
public FullscreenTimerWindow(NewStyleTimerWindow parent)
|
||||
{
|
||||
InitializeComponent();
|
||||
parentWindow = parent;
|
||||
|
||||
// 设置窗口位置和大小
|
||||
this.Left = 0;
|
||||
this.Top = 0;
|
||||
this.Width = SystemParameters.PrimaryScreenWidth;
|
||||
this.Height = SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
// 启动更新定时器
|
||||
updateTimer = new System.Timers.Timer(100);
|
||||
updateTimer.Elapsed += UpdateTimer_Elapsed;
|
||||
updateTimer.Start();
|
||||
|
||||
parentWindow.TimerCompleted += ParentWindow_TimerCompleted;
|
||||
}
|
||||
|
||||
private void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (parentWindow != null)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (ShouldCloseWindow())
|
||||
{
|
||||
this.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateTimeDisplay();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldCloseWindow()
|
||||
{
|
||||
if (parentWindow == null) return true;
|
||||
|
||||
if (MainWindow.Settings.RandSettings?.EnableOvertimeCountUp == true)
|
||||
{
|
||||
if (parentWindow.IsTimerRunning)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var remainingTime = parentWindow.GetRemainingTime();
|
||||
if (remainingTime.HasValue && remainingTime.Value.TotalSeconds < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !parentWindow.IsTimerRunning;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTimeDisplay()
|
||||
{
|
||||
if (parentWindow == null) return;
|
||||
|
||||
// 获取剩余时间
|
||||
var remainingTime = parentWindow.GetRemainingTime();
|
||||
if (remainingTime.HasValue)
|
||||
{
|
||||
var timeSpan = remainingTime.Value;
|
||||
bool isOvertimeMode = timeSpan.TotalSeconds < 0;
|
||||
bool shouldShowRed = isOvertimeMode && MainWindow.Settings.RandSettings?.EnableOvertimeRedText == true;
|
||||
|
||||
int hours, minutes, seconds;
|
||||
|
||||
if (isOvertimeMode)
|
||||
{
|
||||
var totalTimeSpan = parentWindow.GetTotalTimeSpan();
|
||||
if (totalTimeSpan.HasValue)
|
||||
{
|
||||
var elapsedTime = parentWindow.GetElapsedTime();
|
||||
if (elapsedTime.HasValue)
|
||||
{
|
||||
var overtimeSpan = elapsedTime.Value - totalTimeSpan.Value;
|
||||
hours = (int)overtimeSpan.TotalHours;
|
||||
minutes = overtimeSpan.Minutes;
|
||||
seconds = overtimeSpan.Seconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = (int)timeSpan.TotalHours;
|
||||
minutes = timeSpan.Minutes;
|
||||
seconds = timeSpan.Seconds;
|
||||
}
|
||||
|
||||
// 更新小时显示
|
||||
SetDigitDisplay("FullHour1Display", hours / 10, shouldShowRed);
|
||||
SetDigitDisplay("FullHour2Display", hours % 10, shouldShowRed);
|
||||
|
||||
// 更新分钟显示
|
||||
SetDigitDisplay("FullMinute1Display", minutes / 10, shouldShowRed);
|
||||
SetDigitDisplay("FullMinute2Display", minutes % 10, shouldShowRed);
|
||||
|
||||
// 更新秒显示
|
||||
SetDigitDisplay("FullSecond1Display", seconds / 10, shouldShowRed);
|
||||
SetDigitDisplay("FullSecond2Display", seconds % 10, shouldShowRed);
|
||||
|
||||
SetColonDisplay(shouldShowRed);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParentWindow_TimerCompleted(object sender, EventArgs e)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.Close();
|
||||
});
|
||||
}
|
||||
|
||||
private void SetDigitDisplay(string pathName, int digit, bool isRed = false)
|
||||
{
|
||||
var path = this.FindName(pathName) as Path;
|
||||
if (path != null)
|
||||
{
|
||||
string resourceKey = $"Digit{digit}";
|
||||
var geometry = this.FindResource(resourceKey) as Geometry;
|
||||
if (geometry != null)
|
||||
{
|
||||
path.Data = geometry;
|
||||
}
|
||||
|
||||
// 设置颜色
|
||||
if (isRed)
|
||||
{
|
||||
path.Fill = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Fill = Brushes.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置全屏窗口冒号显示颜色
|
||||
/// </summary>
|
||||
/// <param name="isRed">是否显示为红色</param>
|
||||
private void SetColonDisplay(bool isRed = false)
|
||||
{
|
||||
var colon1 = this.FindName("FullColon1Display") as TextBlock;
|
||||
var colon2 = this.FindName("FullColon2Display") as TextBlock;
|
||||
|
||||
if (colon1 != null)
|
||||
{
|
||||
if (isRed)
|
||||
{
|
||||
colon1.Foreground = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
colon1.Foreground = Brushes.White;
|
||||
}
|
||||
}
|
||||
|
||||
if (colon2 != null)
|
||||
{
|
||||
if (isRed)
|
||||
{
|
||||
colon2.Foreground = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
colon2.Foreground = Brushes.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 点击屏幕退出全屏
|
||||
ExitFullscreen();
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
// 按ESC键退出全屏
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
ExitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExitFullscreen()
|
||||
{
|
||||
// 恢复主窗口
|
||||
if (parentWindow != null)
|
||||
{
|
||||
// 清除全屏模式标志
|
||||
parentWindow.SetFullscreenMode(false);
|
||||
parentWindow.Show();
|
||||
parentWindow.Activate();
|
||||
parentWindow.WindowState = WindowState.Normal;
|
||||
}
|
||||
this.Close();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
if (parentWindow != null)
|
||||
{
|
||||
parentWindow.TimerCompleted -= ParentWindow_TimerCompleted;
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
if (updateTimer != null)
|
||||
{
|
||||
updateTimer.Stop();
|
||||
updateTimer.Dispose();
|
||||
}
|
||||
base.OnClosed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<Window x:Class="Ink_Canvas.MinimizedTimerWindow"
|
||||
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"
|
||||
Topmost="True" Background="Transparent"
|
||||
mc:Ignorable="d" WindowStyle="None" AllowsTransparency="True"
|
||||
WindowStartupLocation="Manual" Title="计时器" Height="200" Width="600"
|
||||
MouseLeftButtonDown="Window_MouseLeftButtonDown" MouseLeftButtonUp="Window_MouseLeftButtonUp"
|
||||
MouseEnter="Window_MouseEnter" MouseLeave="Window_MouseLeave" MouseMove="Window_MouseMove">
|
||||
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="DigitResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<Border x:Name="MainBorder" Background="{DynamicResource NewTimerWindowBackground}"
|
||||
CornerRadius="15"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource NewTimerWindowBorderBrush}"
|
||||
Margin="0"
|
||||
UseLayoutRounding="True"
|
||||
SnapsToDevicePixels="True">
|
||||
<Grid>
|
||||
<!-- 时间显示 -->
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,20,20,20">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 小时 -->
|
||||
<Path x:Name="MinHour1Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,12,0"/>
|
||||
<Path x:Name="MinHour2Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,12,0"/>
|
||||
|
||||
<!-- 冒号 -->
|
||||
<TextBlock x:Name="MinColon1Display" Text=":" FontSize="48" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,0,12,0"/>
|
||||
|
||||
<!-- 分钟 -->
|
||||
<Path x:Name="MinMinute1Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,12,0"/>
|
||||
<Path x:Name="MinMinute2Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,12,0"/>
|
||||
|
||||
<!-- 冒号 -->
|
||||
<TextBlock x:Name="MinColon2Display" Text=":" FontSize="48" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,0,12,0"/>
|
||||
|
||||
<!-- 秒 -->
|
||||
<Path x:Name="MinSecond1Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,12,0"/>
|
||||
<Path x:Name="MinSecond2Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="72" Height="72"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<Button x:Name="CloseButton"
|
||||
Width="24" Height="24"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Margin="0,8,8,0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Click="CloseButton_Click"
|
||||
Cursor="Hand"
|
||||
Opacity="0.7">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="12">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#E81123"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="✕" FontSize="12" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
@@ -0,0 +1,392 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// 最小化计时器窗口
|
||||
/// </summary>
|
||||
public partial class MinimizedTimerWindow : Window
|
||||
{
|
||||
private NewStyleTimerWindow parentWindow;
|
||||
private System.Timers.Timer updateTimer;
|
||||
private bool isMouseOver = false;
|
||||
private bool isDragging = false;
|
||||
private Point lastMousePosition;
|
||||
|
||||
public MinimizedTimerWindow(NewStyleTimerWindow parent)
|
||||
{
|
||||
InitializeComponent();
|
||||
parentWindow = parent;
|
||||
|
||||
// 设置窗口位置
|
||||
this.Left = parent.Left;
|
||||
this.Top = parent.Top;
|
||||
|
||||
// 启动更新定时器
|
||||
updateTimer = new System.Timers.Timer(100); // 100ms更新一次
|
||||
updateTimer.Elapsed += UpdateTimer_Elapsed;
|
||||
updateTimer.Start();
|
||||
|
||||
parentWindow.TimerCompleted += ParentWindow_TimerCompleted;
|
||||
|
||||
// 应用主题
|
||||
ApplyTheme();
|
||||
}
|
||||
|
||||
private void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
if (parentWindow != null)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (ShouldCloseWindow())
|
||||
{
|
||||
this.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateTimeDisplay();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldCloseWindow()
|
||||
{
|
||||
if (parentWindow == null) return true;
|
||||
|
||||
if (MainWindow.Settings.RandSettings?.EnableOvertimeCountUp == true)
|
||||
{
|
||||
if (parentWindow.IsTimerRunning)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var remainingTime = parentWindow.GetRemainingTime();
|
||||
if (remainingTime.HasValue && remainingTime.Value.TotalSeconds < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !parentWindow.IsTimerRunning;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTimeDisplay()
|
||||
{
|
||||
if (parentWindow == null) return;
|
||||
|
||||
// 获取剩余时间
|
||||
var remainingTime = parentWindow.GetRemainingTime();
|
||||
if (remainingTime.HasValue)
|
||||
{
|
||||
var timeSpan = remainingTime.Value;
|
||||
bool isOvertimeMode = timeSpan.TotalSeconds < 0;
|
||||
bool shouldShowRed = isOvertimeMode && MainWindow.Settings.RandSettings?.EnableOvertimeRedText == true;
|
||||
|
||||
int hours, minutes, seconds;
|
||||
|
||||
if (isOvertimeMode)
|
||||
{
|
||||
var totalTimeSpan = parentWindow.GetTotalTimeSpan();
|
||||
if (totalTimeSpan.HasValue)
|
||||
{
|
||||
var elapsedTime = parentWindow.GetElapsedTime();
|
||||
if (elapsedTime.HasValue)
|
||||
{
|
||||
var overtimeSpan = elapsedTime.Value - totalTimeSpan.Value;
|
||||
hours = (int)overtimeSpan.TotalHours;
|
||||
minutes = overtimeSpan.Minutes;
|
||||
seconds = overtimeSpan.Seconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hours = (int)timeSpan.TotalHours;
|
||||
minutes = timeSpan.Minutes;
|
||||
seconds = timeSpan.Seconds;
|
||||
}
|
||||
|
||||
// 更新小时显示
|
||||
SetDigitDisplay("MinHour1Display", hours / 10, shouldShowRed);
|
||||
SetDigitDisplay("MinHour2Display", hours % 10, shouldShowRed);
|
||||
|
||||
// 更新分钟显示
|
||||
SetDigitDisplay("MinMinute1Display", minutes / 10, shouldShowRed);
|
||||
SetDigitDisplay("MinMinute2Display", minutes % 10, shouldShowRed);
|
||||
|
||||
// 更新秒显示
|
||||
SetDigitDisplay("MinSecond1Display", seconds / 10, shouldShowRed);
|
||||
SetDigitDisplay("MinSecond2Display", seconds % 10, shouldShowRed);
|
||||
|
||||
SetColonDisplay(shouldShowRed);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParentWindow_TimerCompleted(object sender, EventArgs e)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.Close();
|
||||
});
|
||||
}
|
||||
|
||||
private void SetDigitDisplay(string pathName, int digit, bool isRed = false)
|
||||
{
|
||||
var path = this.FindName(pathName) as Path;
|
||||
if (path != null)
|
||||
{
|
||||
string resourceKey = $"Digit{digit}";
|
||||
var geometry = this.FindResource(resourceKey) as Geometry;
|
||||
if (geometry != null)
|
||||
{
|
||||
path.Data = geometry;
|
||||
}
|
||||
|
||||
// 设置颜色
|
||||
if (isRed)
|
||||
{
|
||||
path.Fill = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush;
|
||||
if (defaultBrush != null)
|
||||
{
|
||||
path.Fill = defaultBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isLightTheme = IsLightTheme();
|
||||
path.Fill = isLightTheme ? Brushes.Black : Brushes.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置最小化窗口冒号显示颜色
|
||||
/// </summary>
|
||||
/// <param name="isRed">是否显示为红色</param>
|
||||
private void SetColonDisplay(bool isRed = false)
|
||||
{
|
||||
var colon1 = this.FindName("MinColon1Display") as TextBlock;
|
||||
var colon2 = this.FindName("MinColon2Display") as TextBlock;
|
||||
|
||||
if (colon1 != null)
|
||||
{
|
||||
if (isRed)
|
||||
{
|
||||
colon1.Foreground = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush;
|
||||
if (defaultBrush != null)
|
||||
{
|
||||
colon1.Foreground = defaultBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isLightTheme = IsLightTheme();
|
||||
colon1.Foreground = isLightTheme ? Brushes.Black : Brushes.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (colon2 != null)
|
||||
{
|
||||
if (isRed)
|
||||
{
|
||||
colon2.Foreground = Brushes.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultBrush = this.FindResource("NewTimerWindowDigitForeground") as Brush;
|
||||
if (defaultBrush != null)
|
||||
{
|
||||
colon2.Foreground = defaultBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isLightTheme = IsLightTheme();
|
||||
colon2.Foreground = isLightTheme ? Brushes.Black : Brushes.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTheme()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
bool isLightTheme = IsLightTheme();
|
||||
if (!isLightTheme)
|
||||
{
|
||||
SetDarkThemeBorder();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"应用主题时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsLightTheme()
|
||||
{
|
||||
try
|
||||
{
|
||||
var mainWindow = Application.Current.MainWindow as MainWindow;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
var currentModeField = mainWindow.GetType().GetField("currentMode",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (currentModeField != null)
|
||||
{
|
||||
var currentMode = currentModeField.GetValue(mainWindow);
|
||||
return currentMode?.ToString() == "Light";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果获取主题失败,默认使用浅色主题
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置深色主题下的灰色边框
|
||||
private void SetDarkThemeBorder()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 找到Border元素并设置灰色边框
|
||||
var border = this.FindName("MainBorder") as Border;
|
||||
if (border != null)
|
||||
{
|
||||
border.BorderBrush = new SolidColorBrush(Color.FromRgb(64, 64, 64));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 记录点击时间
|
||||
lastClickTime = DateTime.Now;
|
||||
// 开始拖动
|
||||
isDragging = true;
|
||||
lastMousePosition = e.GetPosition(this);
|
||||
this.CaptureMouse();
|
||||
}
|
||||
|
||||
private void Window_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (isDragging)
|
||||
{
|
||||
var currentPosition = e.GetPosition(this);
|
||||
var deltaX = currentPosition.X - lastMousePosition.X;
|
||||
var deltaY = currentPosition.Y - lastMousePosition.Y;
|
||||
|
||||
this.Left += deltaX;
|
||||
this.Top += deltaY;
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (isDragging)
|
||||
{
|
||||
isDragging = false;
|
||||
this.ReleaseMouseCapture();
|
||||
|
||||
// 如果点击时间很短,认为是单击,恢复主窗口
|
||||
var clickDuration = DateTime.Now - lastClickTime;
|
||||
if (clickDuration.TotalMilliseconds < 200) // 200ms内认为是单击
|
||||
{
|
||||
// 恢复主窗口
|
||||
if (parentWindow != null)
|
||||
{
|
||||
parentWindow.Show();
|
||||
parentWindow.Activate();
|
||||
parentWindow.WindowState = WindowState.Normal;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime lastClickTime = DateTime.Now;
|
||||
|
||||
private void Window_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
isMouseOver = true;
|
||||
// 鼠标进入时显示关闭按钮
|
||||
if (CloseButton != null)
|
||||
{
|
||||
CloseButton.Opacity = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
isMouseOver = false;
|
||||
// 鼠标离开时隐藏关闭按钮
|
||||
if (CloseButton != null)
|
||||
{
|
||||
CloseButton.Opacity = 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 停止计时器并关闭窗口
|
||||
if (parentWindow != null)
|
||||
{
|
||||
parentWindow.StopTimer();
|
||||
}
|
||||
this.Close();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
if (parentWindow != null)
|
||||
{
|
||||
parentWindow.TimerCompleted -= ParentWindow_TimerCompleted;
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
if (updateTimer != null)
|
||||
{
|
||||
updateTimer.Stop();
|
||||
updateTimer.Dispose();
|
||||
}
|
||||
base.OnClosed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,783 @@
|
||||
<Window x:Class="Ink_Canvas.NewStyleTimerWindow"
|
||||
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:controls="clr-namespace:Ink_Canvas.Windows.Controls"
|
||||
Topmost="True" Background="Transparent"
|
||||
mc:Ignorable="d" WindowStyle="None" AllowsTransparency="True"
|
||||
Loaded="Window_Loaded" Closing="Window_Closing" WindowStartupLocation="CenterScreen"
|
||||
MouseMove="Window_MouseMove" MouseEnter="Window_MouseEnter"
|
||||
Title="Ink Canvas 画板 - 计时器" Height="450" Width="900">
|
||||
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Controls/WinUI3CloseButton.xaml" />
|
||||
<ResourceDictionary Source="DigitResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
|
||||
<Border Background="{DynamicResource NewTimerWindowBackground}" CornerRadius="15" BorderThickness="1" BorderBrush="{DynamicResource NewTimerWindowBorderBrush}" Margin="10" x:Name="MainBorder" MouseLeftButtonDown="WindowDragMove">
|
||||
<Grid>
|
||||
<controls:WinUI3CloseButton x:Name="CloseButton"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
||||
Margin="0,0,0,0" Cursor="Hand" Click="CloseButton_Click"
|
||||
Content="✕"/>
|
||||
<!-- 主要内容区域 -->
|
||||
<Grid>
|
||||
<!-- 使用Viewbox自动缩放内容 -->
|
||||
<Viewbox x:Name="MainViewController" Margin="20,20,20,20">
|
||||
<Grid Height="400" Width="900">
|
||||
<!-- 顶部标题栏 -->
|
||||
<Grid Height="50" Background="{DynamicResource NewTimerWindowBackground}" x:Name="TitleBar" VerticalAlignment="Top" MouseLeftButtonDown="WindowDragMove" Margin="0,0,450,0">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="22,0,0,0">
|
||||
<!-- 计时器图标 -->
|
||||
<Path Data="M5 13a7 7 0 1 0 14 0a7 7 0 0 0 -14 0z M14.5 10.5l-2.5 2.5 M17 8l1 -1 M14 3h-4"
|
||||
Stroke="{DynamicResource NewTimerWindowTitleForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="24" Height="24"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<!-- 计时文字 -->
|
||||
<TextBlock Text="计时" FontSize="28" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowTitleForeground}" x:Name="TitleText"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!-- 主要内容区域 - 分为左右两部分 -->
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center"
|
||||
x:Name="MainContentGrid" Margin="0,-25,0,25">
|
||||
<!-- 左侧:6位数字显示区域 -->
|
||||
<Grid HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
x:Name="MainDisplayGrid" Width="500" Margin="-10,0,0,0">
|
||||
<!-- 6位数字水平排列 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
|
||||
x:Name="DigitsPanel">
|
||||
<!-- 小时组(十位和个位) -->
|
||||
<Grid Margin="0,0,20,0" HorizontalAlignment="Center" Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第1位数字(小时十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit1PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit1Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit1Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit1MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit1Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第2位数字(小时个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit2PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit2Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit2Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit2MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit2Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 冒号分隔符 -->
|
||||
<TextBlock x:Name="Colon1Display" Text=":" FontSize="48" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Margin="-20,0,0,0"/>
|
||||
|
||||
<!-- 分钟组(十位和个位) -->
|
||||
<Grid Margin="0,0,20,0" HorizontalAlignment="Center" Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第3位数字(分钟十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit3PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit3Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit3Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit3MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit3Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第4位数字(分钟个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit4PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit4Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit4Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit4MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit4Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 冒号分隔符 -->
|
||||
<TextBlock x:Name="Colon2Display" Text=":" FontSize="48" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Margin="-20,0,0,0"/>
|
||||
|
||||
<!-- 秒组(十位和个位) -->
|
||||
<Grid Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第5位数字(秒十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit5PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit5Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit5Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit5MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit5Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第6位数字(秒个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit6PlusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit6Plus_Click" Cursor="Hand" Margin="0,0,0,15" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M12 5l0 14 M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<Path x:Name="Digit6Display" Data="{StaticResource Digit0}"
|
||||
Fill="{DynamicResource NewTimerWindowDigitForeground}"
|
||||
Width="48" Height="48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,0,15"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit6MinusBtn" Width="40" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit6Minus_Click" Cursor="Hand" HorizontalAlignment="Center">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path Data="M5 12l14 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 分割线 -->
|
||||
<Border Width="2" Background="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
Opacity="0.3" HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
||||
Margin="465,0,0,0"/>
|
||||
|
||||
<!-- 右侧:快捷选项区域 -->
|
||||
<Grid HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
x:Name="QuickOptionsGrid" Width="400" Margin="470,0,0,0" Height="200">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- Segmented Control -->
|
||||
<Grid Margin="0,0,0,20">
|
||||
<Border Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
CornerRadius="8"
|
||||
BorderThickness="1"
|
||||
BorderBrush="#616161"
|
||||
Width="240" Height="40">
|
||||
<Grid>
|
||||
<!-- 背景指示器 -->
|
||||
<Border x:Name="SegmentedIndicator"
|
||||
Background="{DynamicResource NewTimerWindowPrimaryButtonBackground}"
|
||||
CornerRadius="7.5,0,0,7.5"
|
||||
Width="120" Height="38"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,0"/>
|
||||
|
||||
<!-- 按钮容器 -->
|
||||
<Grid>
|
||||
<Button x:Name="CommonTabBtn"
|
||||
Width="120" Height="40"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Click="CommonTab_Click"
|
||||
Cursor="Hand"
|
||||
HorizontalAlignment="Left">
|
||||
<TextBlock x:Name="CommonTabText" Text="常用" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<Button x:Name="RecentTabBtn"
|
||||
Width="120" Height="40"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Click="RecentTab_Click"
|
||||
Cursor="Hand"
|
||||
HorizontalAlignment="Right">
|
||||
<TextBlock x:Name="RecentTabText" Text="最近" FontSize="16" FontWeight="Normal"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}" Opacity="0.6"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- 常用计时区域 -->
|
||||
<Grid x:Name="CommonTimersGrid" Visibility="Visible">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 第一排:5分钟, 10分钟, 15分钟 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,10">
|
||||
<Button x:Name="Common5MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common5Min_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M10 15h2a1.5 1.5 0 0 0 0 -3h-2v-3h3.5 M3 12v.01 M21 12v.01 M12 21v.01 M7.5 4.2v.01 M16.5 19.8v.01 M7.5 19.8v.01 M4.2 16.5v.01 M19.8 16.5v.01 M19.8 7.5v.01 M4.2 7.5v.01 M16.5 4.206a9.042 9.042 0 0 0 -4.5 -1.206"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="05:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="Common10MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common10Min_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M9 9v6 M12 11v2a2 2 0 1 0 4 0v-2a2 2 0 1 0 -4 0z M3 12v.01 M21 12v.01 M12 21v.01 M7.5 4.2v.01 M16.5 19.8v.01 M7.5 19.8v.01 M4.2 16.5v.01 M19.8 16.5v.01 M4.2 7.5v.01 M19.81 7.527a8.994 8.994 0 0 0 -7.81 -4.527"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="10:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="Common15MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common15Min_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M12 15h2a1 1 0 0 0 1 -1v-1a1 1 0 0 0 -1 -1h-2v-3h3 M9 9v6 M3 12v.01 M12 21v.01 M7.5 4.2v.01 M16.5 19.8v.01 M7.5 19.8v.01 M4.2 16.5v.01 M19.8 16.5v.01 M4.2 7.5v.01 M21 12a9 9 0 0 0 -9 -9"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="15:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第二排:30分钟, 45分钟, 60分钟 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button x:Name="Common30MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common30Min_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M14 10.5v3a1.5 1.5 0 0 0 3 0v-3a1.5 1.5 0 0 0 -3 0z M8 9h1.5a1.5 1.5 0 0 1 0 3h-.5h.5a1.5 1.5 0 0 1 0 3h-1.5 M3 12v.01 M7.5 4.2v.01 M7.5 19.8v.01 M4.2 16.5v.01 M4.2 7.5v.01 M12 21a9 9 0 0 0 0 -18"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="30:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="Common45MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common45Min_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M13 15h2a1 1 0 0 0 1 -1v-1a1 1 0 0 0 -1 -1h-2v-3h3 M7 9v2a1 1 0 0 0 1 1h1 M10 9v6 M7.5 4.2v.01 M4.2 7.5v.01 M3 12a9 9 0 1 0 9 -9"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="45:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="Common60MinBtn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Common60Min_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M14 10.5v3a1.5 1.5 0 0 0 3 0v-3a1.5 1.5 0 0 0 -3 0z M11 9h-2a1 1 0 0 0 -1 1v4a1 1 0 0 0 1 1h1a1 1 0 0 0 1 -1v-1a1 1 0 0 0 -1 -1h-2 M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeStartLineCap="Round"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Text="60:00" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 最近计时区域 -->
|
||||
<Grid x:Name="RecentTimersGrid" Visibility="Collapsed">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 第一排:最近3个 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,10">
|
||||
<Button x:Name="RecentTimer1Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer1_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer1Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<Button x:Name="RecentTimer2Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer2_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer2Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<Button x:Name="RecentTimer3Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer3_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer3Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第二排:最近3个 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button x:Name="RecentTimer4Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer4_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer4Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<Button x:Name="RecentTimer5Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer5_Click" Cursor="Hand" Margin="0,0,15,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer5Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<Button x:Name="RecentTimer6Btn" Width="100" Height="55" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="RecentTimer6_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock x:Name="RecentTimer6Text" Text="--:--" FontSize="16" FontWeight="Bold"
|
||||
Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- 底部控制按钮区域 -->
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 全屏按钮 -->
|
||||
<Button x:Name="FullscreenBtn" Width="80" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Fullscreen_Click" Cursor="Hand" Margin="0,0,30,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="8">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M4 8v-2a2 2 0 0 1 2 -2h2 M4 16v2a2 2 0 0 0 2 2h2 M16 4h2a2 2 0 0 1 2 2v2 M16 20h2a2 2 0 0 0 2 -2v-2"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,5,0"/>
|
||||
<TextBlock Text="全屏" FontSize="16" Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<!-- 开始/暂停按钮 -->
|
||||
<Button x:Name="StartPauseBtn" Width="80" Height="80" Background="{DynamicResource NewTimerWindowPrimaryButtonBackground}"
|
||||
BorderThickness="0" Click="StartPause_Click" Cursor="Hand" Margin="0,0,30,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="40">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path x:Name="StartPauseIcon" Data="M6.5 4.00004V20C6.49995 20.178 6.54737 20.3527 6.63738 20.5062C6.72739 20.6597 6.85672 20.7864 7.01202 20.8732C7.16733 20.96 7.34299 21.0038 7.52088 21.0001C7.69878 20.9964 7.87245 20.9453 8.024 20.852L21.024 12.852C21.1696 12.7626 21.2898 12.6373 21.3733 12.4881C21.4567 12.339 21.5005 12.1709 21.5005 12C21.5005 11.8291 21.4567 11.6611 21.3733 11.512C21.2898 11.3628 21.1696 11.2375 21.024 11.148L8.024 3.14804C7.87245 3.0548 7.69878 3.00369 7.52088 2.99997C7.34299 2.99626 7.16733 3.04007 7.01202 3.1269C6.85672 3.21372 6.72739 3.34042 6.63738 3.4939C6.54737 3.64739 6.49995 3.82211 6.5 4.00004Z"
|
||||
Fill="{DynamicResource NewTimerWindowPrimaryButtonForeground}"
|
||||
Width="24" Height="24" Margin="2,0,0,0"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Fill"/>
|
||||
</Button>
|
||||
|
||||
<!-- 重置按钮 -->
|
||||
<Button x:Name="ResetBtn" Width="80" Height="40" Background="{DynamicResource NewTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Reset_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="8">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Path Data="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4 M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"
|
||||
Stroke="{DynamicResource NewTimerWindowButtonForeground}"
|
||||
StrokeThickness="2"
|
||||
StrokeLineJoin="Round"
|
||||
Fill="Transparent"
|
||||
Width="20" Height="20"
|
||||
Stretch="Uniform"
|
||||
Margin="0,0,5,0"/>
|
||||
<TextBlock Text="重置" FontSize="16" Foreground="{DynamicResource NewTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
@@ -1,8 +1,8 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using iNKORE.UI.WPF.Modern;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
@@ -54,9 +54,9 @@ namespace Ink_Canvas
|
||||
try
|
||||
{
|
||||
// 根据当前主题设置窗口主题
|
||||
bool isDarkTheme = MainWindow.Settings.Appearance.Theme == 1 ||
|
||||
bool isDarkTheme = MainWindow.Settings.Appearance.Theme == 1 ||
|
||||
(MainWindow.Settings.Appearance.Theme == 2 && !IsSystemThemeLight());
|
||||
|
||||
|
||||
if (isDarkTheme)
|
||||
{
|
||||
ThemeManager.SetRequestedTheme(this, ElementTheme.Dark);
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
// 重新应用主题
|
||||
ApplyTheme(MainWindow.Settings);
|
||||
|
||||
|
||||
// 强制刷新UI
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
<Window x:Class="Ink_Canvas.SeewoStyleTimerWindow"
|
||||
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"
|
||||
Topmost="True" Background="Transparent"
|
||||
mc:Ignorable="d" WindowStyle="None" AllowsTransparency="True"
|
||||
Loaded="Window_Loaded" Closing="Window_Closing" WindowStartupLocation="CenterScreen"
|
||||
Title="Ink Canvas 画板 - 计时器" Height="400" Width="600">
|
||||
|
||||
<Border Background="{DynamicResource SeewoTimerWindowBackground}" CornerRadius="15" BorderThickness="1" BorderBrush="{DynamicResource SeewoTimerWindowBorderBrush}" Margin="10">
|
||||
<Grid>
|
||||
<!-- 主要内容区域 -->
|
||||
<Grid>
|
||||
<!-- 使用Viewbox自动缩放内容 -->
|
||||
<Viewbox x:Name="MainViewController" Margin="20,20,20,20">
|
||||
<Grid Height="350" Width="600">
|
||||
<!-- 顶部标题栏 -->
|
||||
<Grid Height="50" Background="{DynamicResource SeewoTimerWindowBackground}" x:Name="TitleBar" HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
||||
<TextBlock Text="计时" FontSize="20" FontWeight="Bold"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Margin="22,0,0,0" Foreground="{DynamicResource SeewoTimerWindowTitleForeground}" x:Name="TitleText"/>
|
||||
<Border x:Name="BtnClose" MouseUp="BtnClose_MouseUp"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,22,0" Background="{DynamicResource SeewoTimerWindowButtonBackground}" Height="30" Width="30"
|
||||
CornerRadius="15" Cursor="Hand">
|
||||
<TextBlock Text="×" FontSize="16" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
<!-- 6位数字显示区域 -->
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
x:Name="MainDisplayGrid">
|
||||
<!-- 6位数字水平排列 -->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
|
||||
x:Name="DigitsPanel" Margin="0,-25,0,25">
|
||||
<!-- 小时组(十位和个位) -->
|
||||
<Grid Margin="0,0,30,0" HorizontalAlignment="Center" Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第1位数字(小时十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit1PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit1Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit1Display" Text="0" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit1MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit1Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第2位数字(小时个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit2PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit2Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit2Display" Text="0" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit2MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit2Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<!-- 时标签 -->
|
||||
<TextBlock Text="时" FontSize="16" HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource SeewoTimerWindowButtonForeground}" Margin="0,112,0,-13"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 分钟组(十位和个位) -->
|
||||
<Grid Margin="0,0,30,0" HorizontalAlignment="Center" Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第3位数字(分钟十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit3PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit3Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit3Display" Text="0" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit3MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit3Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第4位数字(分钟个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit4PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit4Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit4Display" Text="5" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit4MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit4Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<!-- 分标签 -->
|
||||
<TextBlock Text="分" FontSize="16" HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource SeewoTimerWindowButtonForeground}" Margin="0,112,0,-12"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 秒组(十位和个位) -->
|
||||
<Grid Width="120">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 第5位数字(秒十位) -->
|
||||
<Grid Margin="0,0,15,0">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit5PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit5Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit5Display" Text="0" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit5MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit5Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 第6位数字(秒个位) -->
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<!-- 上方+按钮 -->
|
||||
<Button x:Name="Digit6PlusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit6Plus_Click" Cursor="Hand" Margin="0,0,0,8">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="+" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
<!-- 数字显示 -->
|
||||
<TextBlock x:Name="Digit6Display" Text="0" FontSize="64" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Foreground="{DynamicResource SeewoTimerWindowDigitForeground}" Margin="0,0,0,8"/>
|
||||
<!-- 下方-按钮 -->
|
||||
<Button x:Name="Digit6MinusBtn" Width="40" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Digit6Minus_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="15">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<TextBlock Text="-" FontSize="14" FontWeight="Bold" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<!-- 秒标签 -->
|
||||
<TextBlock Text="秒" FontSize="16" HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource SeewoTimerWindowButtonForeground}" Margin="0,112,0,-12"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- 底部控制按钮区域 -->
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<!-- 全屏按钮 -->
|
||||
<Button x:Name="FullscreenBtn" Width="80" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Fullscreen_Click" Cursor="Hand" Margin="0,0,30,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="8">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<TextBlock Text="⛶" FontSize="16" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}" Margin="0,0,5,0"/>
|
||||
<TextBlock Text="全屏" FontSize="16" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<!-- 开始/暂停按钮 -->
|
||||
<Button x:Name="StartPauseBtn" Width="80" Height="80" Background="{DynamicResource SeewoTimerWindowPrimaryButtonBackground}"
|
||||
BorderThickness="0" Click="StartPause_Click" Cursor="Hand" Margin="0,0,30,0">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="40">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<Path x:Name="StartPauseIcon" Data="M6.5 4.00004V20C6.49995 20.178 6.54737 20.3527 6.63738 20.5062C6.72739 20.6597 6.85672 20.7864 7.01202 20.8732C7.16733 20.96 7.34299 21.0038 7.52088 21.0001C7.69878 20.9964 7.87245 20.9453 8.024 20.852L21.024 12.852C21.1696 12.7626 21.2898 12.6373 21.3733 12.4881C21.4567 12.339 21.5005 12.1709 21.5005 12C21.5005 11.8291 21.4567 11.6611 21.3733 11.512C21.2898 11.3628 21.1696 11.2375 21.024 11.148L8.024 3.14804C7.87245 3.0548 7.69878 3.00369 7.52088 2.99997C7.34299 2.99626 7.16733 3.04007 7.01202 3.1269C6.85672 3.21372 6.72739 3.34042 6.63738 3.4939C6.54737 3.64739 6.49995 3.82211 6.5 4.00004Z"
|
||||
Fill="{DynamicResource SeewoTimerWindowPrimaryButtonForeground}"
|
||||
Width="24" Height="24" Margin="2,0,0,0"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Fill"/>
|
||||
</Button>
|
||||
|
||||
<!-- 重置按钮 -->
|
||||
<Button x:Name="ResetBtn" Width="80" Height="40" Background="{DynamicResource SeewoTimerWindowButtonBackground}"
|
||||
BorderThickness="0" Click="Reset_Click" Cursor="Hand">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}" CornerRadius="8">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<TextBlock Text="↻" FontSize="16" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}" Margin="0,0,5,0"/>
|
||||
<TextBlock Text="重置" FontSize="16" Foreground="{DynamicResource SeewoTimerWindowButtonForeground}"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
@@ -1,434 +0,0 @@
|
||||
using Ink_Canvas.Helpers;
|
||||
using System;
|
||||
using System.Media;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿希沃风格的倒计时器窗口
|
||||
/// </summary>
|
||||
public partial class SeewoStyleTimerWindow : Window
|
||||
{
|
||||
public SeewoStyleTimerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
AnimationsHelper.ShowWithSlideFromBottomAndFade(this, 0.25);
|
||||
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.Interval = 50;
|
||||
InitializeUI();
|
||||
|
||||
// 应用主题
|
||||
ApplyTheme();
|
||||
}
|
||||
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (!isTimerRunning || isPaused)
|
||||
{
|
||||
timer.Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
TimeSpan timeSpan = DateTime.Now - startTime;
|
||||
TimeSpan totalTimeSpan = new TimeSpan(hour, minute, second);
|
||||
TimeSpan leftTimeSpan = totalTimeSpan - timeSpan;
|
||||
if (leftTimeSpan.Milliseconds > 0) leftTimeSpan += new TimeSpan(0, 0, 1);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Digit1Display.Text = (leftTimeSpan.Hours / 10).ToString();
|
||||
Digit2Display.Text = (leftTimeSpan.Hours % 10).ToString();
|
||||
Digit3Display.Text = (leftTimeSpan.Minutes / 10).ToString();
|
||||
Digit4Display.Text = (leftTimeSpan.Minutes % 10).ToString();
|
||||
Digit5Display.Text = (leftTimeSpan.Seconds / 10).ToString();
|
||||
Digit6Display.Text = (leftTimeSpan.Seconds % 10).ToString();
|
||||
|
||||
if (leftTimeSpan.TotalSeconds <= 0)
|
||||
{
|
||||
Digit1Display.Text = "0";
|
||||
Digit2Display.Text = "0";
|
||||
Digit3Display.Text = "0";
|
||||
Digit4Display.Text = "0";
|
||||
Digit5Display.Text = "0";
|
||||
Digit6Display.Text = "0";
|
||||
timer.Stop();
|
||||
isTimerRunning = false;
|
||||
StartPauseIcon.Data = Geometry.Parse(PlayIconData);
|
||||
PlayTimerSound();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SoundPlayer player = new SoundPlayer();
|
||||
MediaPlayer mediaPlayer = new MediaPlayer();
|
||||
|
||||
int hour = 0;
|
||||
int minute = 5;
|
||||
int second = 0;
|
||||
|
||||
DateTime startTime = DateTime.Now;
|
||||
DateTime pauseTime = DateTime.Now;
|
||||
|
||||
bool isTimerRunning = false;
|
||||
bool isPaused = false;
|
||||
|
||||
Timer timer = new Timer();
|
||||
|
||||
private void InitializeUI()
|
||||
{
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void ApplyTheme()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 应用主题设置
|
||||
if (MainWindow.Settings != null)
|
||||
{
|
||||
ApplyTheme(MainWindow.Settings);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"应用仿希沃倒计时窗口主题出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTheme(Settings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (settings.Appearance.Theme == 0) // 浅色主题
|
||||
{
|
||||
iNKORE.UI.WPF.Modern.ThemeManager.SetRequestedTheme(this, iNKORE.UI.WPF.Modern.ElementTheme.Light);
|
||||
}
|
||||
else if (settings.Appearance.Theme == 1) // 深色主题
|
||||
{
|
||||
iNKORE.UI.WPF.Modern.ThemeManager.SetRequestedTheme(this, iNKORE.UI.WPF.Modern.ElementTheme.Dark);
|
||||
}
|
||||
else // 跟随系统主题
|
||||
{
|
||||
bool isSystemLight = IsSystemThemeLight();
|
||||
if (isSystemLight)
|
||||
{
|
||||
iNKORE.UI.WPF.Modern.ThemeManager.SetRequestedTheme(this, iNKORE.UI.WPF.Modern.ElementTheme.Light);
|
||||
}
|
||||
else
|
||||
{
|
||||
iNKORE.UI.WPF.Modern.ThemeManager.SetRequestedTheme(this, iNKORE.UI.WPF.Modern.ElementTheme.Dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"应用仿希沃倒计时窗口主题出错: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSystemThemeLight()
|
||||
{
|
||||
var light = false;
|
||||
try
|
||||
{
|
||||
var registryKey = Microsoft.Win32.Registry.CurrentUser;
|
||||
var themeKey = registryKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
||||
if (themeKey != null)
|
||||
{
|
||||
var value = themeKey.GetValue("AppsUseLightTheme");
|
||||
if (value != null)
|
||||
{
|
||||
light = (int)value == 1;
|
||||
}
|
||||
themeKey.Close();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果读取注册表失败,默认为浅色主题
|
||||
light = true;
|
||||
}
|
||||
return light;
|
||||
}
|
||||
|
||||
private void UpdateDigitDisplays()
|
||||
{
|
||||
Digit1Display.Text = (hour / 10).ToString();
|
||||
Digit2Display.Text = (hour % 10).ToString();
|
||||
Digit3Display.Text = (minute / 10).ToString();
|
||||
Digit4Display.Text = (minute % 10).ToString();
|
||||
Digit5Display.Text = (second / 10).ToString();
|
||||
Digit6Display.Text = (second % 10).ToString();
|
||||
}
|
||||
|
||||
// 第1位数字(小时十位)
|
||||
private void Digit1Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
hour += 10;
|
||||
if (hour >= 100) hour = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit1Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
hour -= 10;
|
||||
if (hour < 0) hour = 90;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 第2位数字(小时个位)
|
||||
private void Digit2Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
hour++;
|
||||
if (hour >= 100) hour = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit2Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
hour--;
|
||||
if (hour < 0) hour = 99;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 第3位数字(分钟十位)
|
||||
private void Digit3Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
minute += 10;
|
||||
if (minute >= 60) minute = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit3Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
minute -= 10;
|
||||
if (minute < 0) minute = 50;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 第4位数字(分钟个位)
|
||||
private void Digit4Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
minute++;
|
||||
if (minute >= 60) minute = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit4Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
minute--;
|
||||
if (minute < 0) minute = 59;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 第5位数字(秒十位)
|
||||
private void Digit5Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
second += 10;
|
||||
if (second >= 60) second = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit5Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
second -= 10;
|
||||
if (second < 0) second = 50;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 第6位数字(秒个位)
|
||||
private void Digit6Plus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
second++;
|
||||
if (second >= 60) second = 0;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
private void Digit6Minus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isTimerRunning) return;
|
||||
second--;
|
||||
if (second < 0) second = 59;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
// 图标数据常量
|
||||
private const string PlayIconData = "M6.5 4.00004V20C6.49995 20.178 6.54737 20.3527 6.63738 20.5062C6.72739 20.6597 6.85672 20.7864 7.01202 20.8732C7.16733 20.96 7.34299 21.0038 7.52088 21.0001C7.69878 20.9964 7.87245 20.9453 8.024 20.852L21.024 12.852C21.1696 12.7626 21.2898 12.6373 21.3733 12.4881C21.4567 12.339 21.5005 12.1709 21.5005 12C21.5005 11.8291 21.4567 11.6611 21.3733 11.512C21.2898 11.3628 21.1696 11.2375 21.024 11.148L8.024 3.14804C7.87245 3.0548 7.69878 3.00369 7.52088 2.99997C7.34299 2.99626 7.16733 3.04007 7.01202 3.1269C6.85672 3.21372 6.72739 3.34042 6.63738 3.4939C6.54737 3.64739 6.49995 3.82211 6.5 4.00004Z";
|
||||
private const string PauseIconData = "M9.5 4H7.5C6.96957 4 6.46086 4.21071 6.08579 4.58579C5.71071 4.96086 5.5 5.46957 5.5 6V18C5.5 18.5304 5.71071 19.0391 6.08579 19.4142C6.46086 19.7893 6.96957 20 7.5 20H9.5C10.0304 20 10.5391 19.7893 10.9142 19.4142C11.2893 19.0391 11.5 18.5304 11.5 18V6C11.5 5.46957 11.2893 4.96086 10.9142 4.58579C10.5391 4.21071 10.0304 4 9.5 4Z M17.5 4H15.5C14.9696 4 14.4609 4.21071 14.0858 4.58579C13.7107 4.96086 13.5 5.46957 13.5 6V18C13.5 18.5304 13.7107 19.0391 14.0858 19.4142C14.4609 19.7893 14.9696 20 15.5 20H17.5C18.0304 20 18.5391 19.7893 18.9142 19.4142C19.2893 19.0391 19.5 18.5304 19.5 18V6C19.5 5.46957 19.2893 4.96086 18.9142 4.58579C18.5391 4.21071 18.0304 4 17.5 4Z";
|
||||
|
||||
private void StartPause_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (isPaused && isTimerRunning)
|
||||
{
|
||||
// 继续计时
|
||||
startTime += DateTime.Now - pauseTime;
|
||||
StartPauseIcon.Data = Geometry.Parse(PauseIconData);
|
||||
isPaused = false;
|
||||
timer.Start();
|
||||
}
|
||||
else if (isTimerRunning)
|
||||
{
|
||||
// 暂停计时
|
||||
pauseTime = DateTime.Now;
|
||||
StartPauseIcon.Data = Geometry.Parse(PlayIconData);
|
||||
isPaused = true;
|
||||
timer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 开始计时
|
||||
if (hour == 0 && minute == 0 && second == 0)
|
||||
{
|
||||
second = 1;
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
|
||||
startTime = DateTime.Now;
|
||||
StartPauseIcon.Data = Geometry.Parse(PauseIconData);
|
||||
isPaused = false;
|
||||
isTimerRunning = true;
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void Reset_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isTimerRunning)
|
||||
{
|
||||
UpdateDigitDisplays();
|
||||
}
|
||||
else if (isTimerRunning && isPaused)
|
||||
{
|
||||
UpdateDigitDisplays();
|
||||
StartPauseIcon.Data = Geometry.Parse(PlayIconData);
|
||||
isTimerRunning = false;
|
||||
timer.Stop();
|
||||
isPaused = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
startTime = DateTime.Now;
|
||||
Timer_Elapsed(timer, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Fullscreen_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (WindowState == WindowState.Normal)
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void PlayTimerSound()
|
||||
{
|
||||
try
|
||||
{
|
||||
double volume = MainWindow.Settings.RandSettings?.TimerVolume ?? 1.0;
|
||||
mediaPlayer.Volume = volume;
|
||||
|
||||
if (!string.IsNullOrEmpty(MainWindow.Settings.RandSettings?.CustomTimerSoundPath) &&
|
||||
System.IO.File.Exists(MainWindow.Settings.RandSettings.CustomTimerSoundPath))
|
||||
{
|
||||
// 播放自定义铃声
|
||||
mediaPlayer.Open(new Uri(MainWindow.Settings.RandSettings.CustomTimerSoundPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 播放默认铃声
|
||||
string tempPath = System.IO.Path.GetTempFileName() + ".wav";
|
||||
using (var stream = Properties.Resources.TimerDownNotice)
|
||||
{
|
||||
using (var fileStream = new System.IO.FileStream(tempPath, System.IO.FileMode.Create))
|
||||
{
|
||||
stream.CopyTo(fileStream);
|
||||
}
|
||||
}
|
||||
mediaPlayer.Open(new Uri(tempPath));
|
||||
}
|
||||
|
||||
mediaPlayer.Play();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 如果播放失败,静默处理
|
||||
System.Diagnostics.Debug.WriteLine($"播放计时器铃声失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 窗口加载时的初始化
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
isTimerRunning = false;
|
||||
|
||||
if (MainWindow.Settings != null)
|
||||
{
|
||||
var mainWindow = Application.Current.MainWindow as MainWindow;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentModeField = mainWindow.GetType().GetField("currentMode",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (currentModeField != null)
|
||||
{
|
||||
int currentMode = (int)currentModeField.GetValue(mainWindow);
|
||||
if (currentMode == 1) // 白板模式
|
||||
{
|
||||
mainWindow.Topmost = false; // 保持白板模式下的非置顶状态
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindow.Topmost = true; // 其他模式恢复置顶
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果反射失败,使用默认行为
|
||||
mainWindow.Topmost = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnClose_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void WindowDragMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,3 +114,4 @@ GPLv3
|
||||
|
||||
## 项目引用
|
||||
[Alan-CRL/DesktopDrawpadBlocker](https://github.com/Alan-CRL/DesktopDrawpadBlocker)
|
||||
[Awesome-Iwb/iwbicons-gallery](https://github.com/awesome-iwb/awesome-iwb/wiki/iwbicons-gallery)「本项目部分图标来自 Awesome Iwb 的 IwbIcons 图标库,由 Douxiba 制作。」
|
||||
|
||||
@@ -98,4 +98,5 @@ ICC CE 1.7.X.X更新日志
|
||||
97. 改进橡皮系统
|
||||
98. 新增启动动画
|
||||
99. 修复仅调色盘状态下浮动栏不居中
|
||||
100. 修复希沃白板查杀与思锐希沃启动器导致的重复启动
|
||||
100. 修复希沃白板查杀与思锐希沃启动器导致的重复启动
|
||||
101. 新增UIA窗口置顶
|
||||
|
||||