Files
community/Ink Canvas/MainWindow_cs/MW_Timer.cs
T
PrefacedCorg 11a5a7fdbe 代码清理
2025-08-03 16:46:33 +08:00

583 lines
29 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Ink_Canvas.Helpers;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
namespace Ink_Canvas
{
public class TimeViewModel : INotifyPropertyChanged
{
private string _nowTime;
private string _nowDate;
public string nowTime
{
get => _nowTime;
set
{
if (_nowTime != value)
{
_nowTime = value;
OnPropertyChanged();
}
}
}
public string nowDate
{
get => _nowDate;
set
{
if (_nowDate != value)
{
_nowDate = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public partial class MainWindow : Window
{
private Timer timerCheckPPT = new Timer();
private Timer timerKillProcess = new Timer();
private Timer timerCheckAutoFold = new Timer();
private string AvailableLatestVersion;
private Timer timerCheckAutoUpdateWithSilence = new Timer();
private bool isHidingSubPanelsWhenInking; // 避免书写时触发二次关闭二级菜单导致动画不连续
private Timer timerDisplayTime = new Timer();
private Timer timerDisplayDate = new Timer();
private TimeViewModel nowTimeVM = new TimeViewModel();
private async Task<DateTime> GetNetworkTimeAsync()
{
try
{
const string ntpServer = "ntp.ntsc.ac.cn";
var ntpData = new byte[48];
ntpData[0] = 0x1B;
var addresses = await Dns.GetHostAddressesAsync(ntpServer);
var ipEndPoint = new IPEndPoint(addresses[0], 123);
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
socket.ReceiveTimeout = 2000;
socket.Connect(ipEndPoint);
await Task.Factory.FromAsync(socket.BeginSend(ntpData, 0, ntpData.Length, SocketFlags.None, null, socket), socket.EndSend);
await Task.Factory.FromAsync(socket.BeginReceive(ntpData, 0, ntpData.Length, SocketFlags.None, null, socket), socket.EndReceive);
}
const byte serverReplyTime = 40;
ulong intPart = BitConverter.ToUInt32(ntpData.Skip(serverReplyTime).Take(4).Reverse().ToArray(), 0);
ulong fractPart = BitConverter.ToUInt32(ntpData.Skip(serverReplyTime + 4).Take(4).Reverse().ToArray(), 0);
var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
return networkDateTime.ToLocalTime();
}
catch
{
return DateTime.Now;
}
}
// 修改InitTimers方法中的初始时间和日期格式
private void InitTimers()
{
// PPT检查现在由PPTManager处理,不再需要定时器
// timerCheckPPT.Elapsed += TimerCheckPPT_Elapsed;
// timerCheckPPT.Interval = 500;
timerKillProcess.Elapsed += TimerKillProcess_Elapsed;
timerKillProcess.Interval = 2000;
timerCheckAutoFold.Elapsed += timerCheckAutoFold_Elapsed;
timerCheckAutoFold.Interval = 500;
timerCheckAutoUpdateWithSilence.Elapsed += timerCheckAutoUpdateWithSilence_Elapsed;
timerCheckAutoUpdateWithSilence.Interval = 1000 * 60 * 10;
WaterMarkTime.DataContext = nowTimeVM;
WaterMarkDate.DataContext = nowTimeVM;
timerDisplayTime.Elapsed += async (s, e) => await TimerDisplayTime_ElapsedAsync();
timerDisplayTime.Interval = 1000;
timerDisplayTime.Start();
timerDisplayDate.Elapsed += TimerDisplayDate_Elapsed;
timerDisplayDate.Interval = 1000 * 60 * 60 * 1;
timerDisplayDate.Start();
timerKillProcess.Start();
nowTimeVM.nowDate = DateTime.Now.ToString("yyyy'年'MM'月'dd'日' dddd");
nowTimeVM.nowTime = DateTime.Now.ToString("tt hh'时'mm'分'ss'秒'");
}
// 修改TimerDisplayTime_ElapsedAsync方法中的时间格式
private async Task TimerDisplayTime_ElapsedAsync()
{
DateTime now = await GetNetworkTimeAsync();
// 只更新时间,日期由原有逻辑定时更新即可
Dispatcher.Invoke(() =>
{
nowTimeVM.nowTime = now.ToString("tt hh'时'mm'分'ss'秒'");
});
}
// 修改TimerDisplayDate_Elapsed方法中的日期格式
private void TimerDisplayDate_Elapsed(object sender, ElapsedEventArgs e)
{
nowTimeVM.nowDate = DateTime.Now.ToString("yyyy'年'MM'月'dd'日' dddd");
}
private void TimerKillProcess_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
// 希沃相关: easinote swenserver RemoteProcess EasiNote.MediaHttpService smartnote.cloud EasiUpdate smartnote EasiUpdate3 EasiUpdate3Protect SeewoP2P CefSharp.BrowserSubprocess SeewoUploadService
var arg = "/F";
if (Settings.Automation.IsAutoKillPptService)
{
var processes = Process.GetProcessesByName("PPTService");
if (processes.Length > 0) arg += " /IM PPTService.exe";
processes = Process.GetProcessesByName("SeewoIwbAssistant");
if (processes.Length > 0) arg += " /IM SeewoIwbAssistant.exe" + " /IM Sia.Guard.exe";
}
if (Settings.Automation.IsAutoKillEasiNote)
{
var processes = Process.GetProcessesByName("EasiNote");
if (processes.Length > 0) arg += " /IM EasiNote.exe";
}
if (Settings.Automation.IsAutoKillHiteAnnotation)
{
var processes = Process.GetProcessesByName("HiteAnnotation");
if (processes.Length > 0) arg += " /IM HiteAnnotation.exe";
}
if (Settings.Automation.IsAutoKillVComYouJiao)
{
var processes = Process.GetProcessesByName("VcomTeach");
if (processes.Length > 0) arg += " /IM VcomTeach.exe" + " /IM VcomDaemon.exe" + " /IM VcomRender.exe";
}
if (Settings.Automation.IsAutoKillICA)
{
var processesAnnotation = Process.GetProcessesByName("Ink Canvas Annotation");
var processesArtistry = Process.GetProcessesByName("Ink Canvas Artistry");
if (processesAnnotation.Length > 0) arg += " /IM \"Ink Canvas Annotation.exe\"";
if (processesArtistry.Length > 0) arg += " /IM \"Ink Canvas Artistry.exe\"";
}
if (Settings.Automation.IsAutoKillInkCanvas)
{
var processes = Process.GetProcessesByName("Ink Canvas");
if (processes.Length > 0) arg += " /IM \"Ink Canvas.exe\"";
}
if (Settings.Automation.IsAutoKillIDT)
{
var processes = Process.GetProcessesByName("Inkeys");
if (processes.Length > 0) arg += " /IM \"Inkeys.exe\"";
}
if (Settings.Automation.IsAutoKillSeewoLauncher2DesktopAnnotation)
{
//由于希沃桌面2.0提供的桌面批注是64位应用程序,32位程序无法访问,目前暂不做精准匹配,只匹配进程名称,后面会考虑封装一套基于P/Invoke和WMI的综合进程识别方案。
var processes = Process.GetProcessesByName("DesktopAnnotation");
if (processes.Length > 0) arg += " /IM DesktopAnnotation.exe";
}
if (arg != "/F")
{
var p = new Process();
p.StartInfo = new ProcessStartInfo("taskkill", arg);
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
if (arg.Contains("EasiNote"))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“希沃白板 5”已自动关闭");
});
}
if (arg.Contains("HiteAnnotation"))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“鸿合屏幕书写”已自动关闭");
if (Settings.Automation.IsAutoKillHiteAnnotation && Settings.Automation.IsAutoEnterAnnotationAfterKillHite)
{
// 自动进入批注状态
PenIcon_Click(null, null);
}
});
}
if (arg.Contains("Ink Canvas Annotation") || arg.Contains("Ink Canvas Artistry"))
{
Dispatcher.Invoke(() =>
{
ShowNewMessage("“ICA”已自动关闭");
});
}
if (arg.Contains("\"Ink Canvas.exe\""))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“Ink Canvas”已自动关闭");
});
}
if (arg.Contains("Inkeys"))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“智绘教Inkeys”已自动关闭");
});
}
if (arg.Contains("VcomTeach"))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“优教授课端”已自动关闭");
});
}
if (arg.Contains("DesktopAnnotation"))
{
Dispatcher.Invoke(() =>
{
ShowNotification("“希沃桌面2.0 桌面批注”已自动关闭");
});
}
}
}
catch { }
}
private bool foldFloatingBarByUser, // 保持收纳操作不受自动收纳的控制
unfoldFloatingBarByUser; // 允许用户在希沃软件内进行展开操作
private void timerCheckAutoFold_Elapsed(object sender, ElapsedEventArgs e)
{
if (isFloatingBarChangingHideMode) return;
try
{
var windowProcessName = ForegroundWindowInfo.ProcessName();
var windowTitle = ForegroundWindowInfo.WindowTitle();
//LogHelper.WriteLogToFile("windowTitle | " + windowTitle + " | windowProcessName | " + windowProcessName);
if (windowProcessName == "EasiNote")
{
// 检测到有可能是EasiNote5或者EasiNote3/3C
if (ForegroundWindowInfo.ProcessPath() != "Unknown")
{
var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
string version = versionInfo.FileVersion;
string prodName = versionInfo.ProductName;
Trace.WriteLine(ForegroundWindowInfo.ProcessPath());
Trace.WriteLine(version);
Trace.WriteLine(prodName);
if (version.StartsWith("5.") && Settings.Automation.IsAutoFoldInEasiNote && (!(windowTitle.Length == 0 && ForegroundWindowInfo.WindowRect().Height < 500) ||
!Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno))
{ // EasiNote5
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
}
else if (version.StartsWith("3.") && Settings.Automation.IsAutoFoldInEasiNote3)
{ // EasiNote3
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
}
else if (prodName.Contains("3C") && Settings.Automation.IsAutoFoldInEasiNote3C &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{ // EasiNote3C
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
}
}
// EasiCamera
}
else if (Settings.Automation.IsAutoFoldInEasiCamera && windowProcessName == "EasiCamera" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// EasiNote5C
}
else if (Settings.Automation.IsAutoFoldInEasiNote5C && windowProcessName == "EasiNote5C" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// SeewoPinco
}
else if (Settings.Automation.IsAutoFoldInSeewoPincoTeacher && (windowProcessName == "BoardService" || windowProcessName == "seewoPincoTeacher"))
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// HiteCamera
}
else if (Settings.Automation.IsAutoFoldInHiteCamera && windowProcessName == "HiteCamera" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// HiteTouchPro
}
else if (Settings.Automation.IsAutoFoldInHiteTouchPro && windowProcessName == "HiteTouchPro" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// WxBoardMain
}
else if (Settings.Automation.IsAutoFoldInWxBoardMain && windowProcessName == "WxBoardMain" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// MSWhiteboard
}
else if (Settings.Automation.IsAutoFoldInMSWhiteboard && (windowProcessName == "MicrosoftWhiteboard" ||
windowProcessName == "msedgewebview2"))
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// OldZyBoard
}
else if (Settings.Automation.IsAutoFoldInOldZyBoard && // 中原旧白板
(WinTabWindowsChecker.IsWindowExisted("WhiteBoard - DrawingWindow")
|| WinTabWindowsChecker.IsWindowExisted("InstantAnnotationWindow")))
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// HiteLightBoard
}
else if (Settings.Automation.IsAutoFoldInHiteLightBoard && windowProcessName == "HiteLightBoard" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// AdmoxWhiteboard
}
else if (Settings.Automation.IsAutoFoldInAdmoxWhiteboard && windowProcessName == "Amdox.WhiteBoard" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// AdmoxBooth
}
else if (Settings.Automation.IsAutoFoldInAdmoxBooth && windowProcessName == "Amdox.Booth" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// QPoint
}
else if (Settings.Automation.IsAutoFoldInQPoint && windowProcessName == "QPoint" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// YiYunVisualPresenter
}
else if (Settings.Automation.IsAutoFoldInYiYunVisualPresenter && windowProcessName == "YiYunVisualPresenter" &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
// MaxHubWhiteboard
}
else if (Settings.Automation.IsAutoFoldInMaxHubWhiteboard && windowProcessName == "WhiteBoard" &&
WinTabWindowsChecker.IsWindowExisted("白板书写") &&
ForegroundWindowInfo.WindowRect().Height >= SystemParameters.WorkArea.Height - 16 &&
ForegroundWindowInfo.WindowRect().Width >= SystemParameters.WorkArea.Width - 16)
{
if (ForegroundWindowInfo.ProcessPath() != "Unknown")
{
var versionInfo = FileVersionInfo.GetVersionInfo(ForegroundWindowInfo.ProcessPath());
var version = versionInfo.FileVersion; var prodName = versionInfo.ProductName;
if (version.StartsWith("6.") && prodName == "WhiteBoard") if (!unfoldFloatingBarByUser && !isFloatingBarFolded) FoldFloatingBar_MouseUp(null, null);
}
}
else if (WinTabWindowsChecker.IsWindowExisted("幻灯片放映", false))
{
// 处于幻灯片放映状态
if (!Settings.Automation.IsAutoFoldInPPTSlideShow && isFloatingBarFolded && !foldFloatingBarByUser)
UnFoldFloatingBar_MouseUp(new object(), null);
}
else
{
if (isFloatingBarFolded && !foldFloatingBarByUser) UnFoldFloatingBar_MouseUp(new object(), null);
unfoldFloatingBarByUser = false;
}
}
catch { }
}
private void timerCheckAutoUpdateWithSilence_Elapsed(object sender, ElapsedEventArgs e)
{
// 停止计时器,避免重复触发
timerCheckAutoUpdateWithSilence.Stop();
try
{
// 检查是否有可用的更新
if (string.IsNullOrEmpty(AvailableLatestVersion))
{
LogHelper.WriteLogToFile("AutoUpdate | No available update version found");
return;
}
// 检查是否启用了静默更新
if (!Settings.Startup.IsAutoUpdateWithSilence)
{
LogHelper.WriteLogToFile("AutoUpdate | Silent update is disabled");
return;
}
// 检查更新文件是否已下载
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
if (!File.Exists(statusFilePath) || File.ReadAllText(statusFilePath).Trim().ToLower() != "true")
{
LogHelper.WriteLogToFile("AutoUpdate | Update file not downloaded yet");
// 尝试下载更新文件,使用多线路组下载功能
Task.Run(async () =>
{
bool isDownloadSuccessful = false;
try
{
// 如果主要线路组可用,直接使用
if (AvailableLatestLineGroup != null)
{
LogHelper.WriteLogToFile($"AutoUpdate | 使用主要线路组下载: {AvailableLatestLineGroup.GroupName}");
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup);
}
// 如果主要线路组不可用或下载失败,获取所有可用线路组
if (!isDownloadSuccessful)
{
LogHelper.WriteLogToFile("AutoUpdate | 主要线路组不可用或下载失败,获取所有可用线路组");
var availableGroups = await AutoUpdateHelper.GetAvailableLineGroupsOrdered(Settings.Startup.UpdateChannel);
if (availableGroups.Count > 0)
{
LogHelper.WriteLogToFile($"AutoUpdate | 使用 {availableGroups.Count} 个可用线路组进行下载");
isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileWithFallback(AvailableLatestVersion, availableGroups);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | 下载更新时出错: {ex.Message}", LogHelper.LogType.Error);
}
if (isDownloadSuccessful)
{
LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will check again for installation");
// 重新启动计时器,下次检查时安装
timerCheckAutoUpdateWithSilence.Start();
}
else
{
LogHelper.WriteLogToFile("AutoUpdate | Failed to download update", LogHelper.LogType.Error);
}
});
return;
}
// 检查是否在静默更新时间段内
bool isInSilencePeriod = AutoUpdateWithSilenceTimeComboBox.CheckIsInSilencePeriod(
Settings.Startup.AutoUpdateWithSilenceStartTime,
Settings.Startup.AutoUpdateWithSilenceEndTime);
if (!isInSilencePeriod)
{
LogHelper.WriteLogToFile("AutoUpdate | Not in silence update time period");
// 重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
return;
}
// 检查应用程序状态,确保可以安全更新
// 空闲状态的判定为不处于批注模式和画板模式
bool canSafelyUpdate = false;
Dispatcher.Invoke(() =>
{
try
{
// 判断是否处于批注模式(inkCanvas.EditingMode == InkCanvasEditingMode.Ink
// 判断是否处于画板模式(!Topmost)
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink && Topmost)
{
// 检查是否有未保存的内容或正在进行的操作
if (!isHidingSubPanelsWhenInking)
{
canSafelyUpdate = true;
LogHelper.WriteLogToFile("AutoUpdate | Application is in a safe state for update - not in ink or board mode");
}
else
{
LogHelper.WriteLogToFile("AutoUpdate | Application is currently performing operations");
}
}
else
{
LogHelper.WriteLogToFile("AutoUpdate | Application is in ink or board mode, cannot update now");
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error checking application state: {ex.Message}", LogHelper.LogType.Error);
}
});
if (canSafelyUpdate)
{
LogHelper.WriteLogToFile("AutoUpdate | Installing update now");
// 设置为用户主动退出,避免被看门狗判定为崩溃
App.IsAppExitByUser = true;
// 执行更新安装
AutoUpdateHelper.InstallNewVersionApp(AvailableLatestVersion, true);
// 关闭应用程序
Dispatcher.Invoke(() =>
{
Application.Current.Shutdown();
});
}
else
{
LogHelper.WriteLogToFile("AutoUpdate | Cannot safely update now, will try again later");
// 重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"AutoUpdate | Error in silent update check: {ex.Message}", LogHelper.LogType.Error);
// 出错时重新启动计时器,稍后再检查
timerCheckAutoUpdateWithSilence.Start();
}
}
}
}