Merge pull request #98 from InkCanvasForClass/beta

ICC CE 1.7.2.0
This commit is contained in:
CJK_mkp
2025-07-25 18:45:27 +08:00
committed by GitHub
11 changed files with 159 additions and 134 deletions
+1 -1
View File
@@ -1 +1 @@
1.7.1.0
1.7.2.0
+2 -2
View File
@@ -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.1.14")]
[assembly: AssemblyFileVersion("1.7.1.14")]
[assembly: AssemblyVersion("1.7.2.0")]
[assembly: AssemblyFileVersion("1.7.2.0")]
+23 -1
View File
@@ -845,9 +845,31 @@ namespace Ink_Canvas.Helpers
}
}
progressCallback?.Invoke(100, $"多线程下载完成({threadCount}线程)");
FileInfo fileInfo = new FileInfo(destinationPath);
if (fileInfo.Length != totalSize)
{
LogHelper.WriteLogToFile($"AutoUpdate | 文件大小校验失败,本地:{fileInfo.Length},服务器:{totalSize}", LogHelper.LogType.Error);
File.Delete(destinationPath);
progressCallback?.Invoke(0, "文件大小校验失败,已删除损坏文件");
return false;
}
if (destinationPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
{
try
{
System.IO.Compression.ZipFile.OpenRead(destinationPath).Dispose();
}
catch
{
LogHelper.WriteLogToFile("AutoUpdate | ZIP文件解压测试失败,文件可能已损坏", LogHelper.LogType.Error);
File.Delete(destinationPath);
progressCallback?.Invoke(0, "ZIP文件解压测试失败,已删除损坏文件");
return false;
}
}
return true;
}
// 理论上不会到这里
return false;
}
+7 -17
View File
@@ -2,8 +2,6 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Ink_Canvas.Helpers
{
@@ -96,22 +94,14 @@ namespace Ink_Canvas.Helpers
}
}
public static int GetTaskbarHeight(Screen screen, double dpiScaleY)
public static double GetTaskbarHeight(System.Windows.Forms.Screen screen, double dpiScaleY)
{
// 优先用工作区和屏幕的差值法,兼容多屏
int height = 0;
if (screen.Bounds.Height > screen.WorkingArea.Height)
{
// 任务栏在上下
height = screen.Bounds.Height - screen.WorkingArea.Height;
}
else if (screen.Bounds.Width > screen.WorkingArea.Width)
{
// 任务栏在左右
height = screen.Bounds.Width - screen.WorkingArea.Width;
}
// 考虑DPI缩放
return (int)(height / dpiScaleY);
// 获取工作区和屏幕高度的差值
var workingArea = screen.WorkingArea;
var bounds = screen.Bounds;
int taskbarHeight = bounds.Height - workingArea.Height;
// 考虑 DPI 缩放
return taskbarHeight / dpiScaleY;
}
}
}
+7
View File
@@ -618,6 +618,13 @@
FontSize="26" />
</GroupBox.Header>
<ui:SimpleStackPanel Spacing="6">
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Foreground="#fafafa" Text="窗口无焦点模式" VerticalAlignment="Center"
FontSize="14" Margin="0,0,16,0" />
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchNoFocusMode"
IsOn="False" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
Toggled="ToggleSwitchNoFocusMode_Toggled" />
</ui:SimpleStackPanel>
<ui:ToggleSwitch OnContent="" OffContent=""
Name="ToggleSwitchIsAutoUpdate" Header="自动检查更新"
FontFamily="Microsoft YaHei UI"
+39 -44
View File
@@ -19,6 +19,7 @@ using System.Reflection;
using Brushes = System.Windows.Media.Brushes;
using Point = System.Windows.Point;
using System.Collections.Generic;
using iNKORE.UI.WPF.Modern.Controls;
namespace Ink_Canvas {
public partial class MainWindow : Window {
@@ -28,44 +29,7 @@ namespace Ink_Canvas {
private System.Windows.Controls.Canvas currentCanvas = null;
private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup = null;
// Win32 API声明和常量(用于无焦点窗口)
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 0x08000000;
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_NOACTIVATE = 0x0010;
private const uint SWP_SHOWWINDOW = 0x0040;
// 新增:设置窗口置顶并兼容无焦点
private void SetTopmostWithNoActivate(bool topmost)
{
var hwnd = new WindowInteropHelper(this).Handle;
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
// 先移除 WS_EX_NOACTIVATE
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
// 设置 Topmost
this.Topmost = topmost;
// 使用SetWindowPos确保无焦点置顶
if (topmost)
{
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
}
else
{
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
}
// 再加回 WS_EX_NOACTIVATE
exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
}
#region Window Initialization
@@ -204,14 +168,12 @@ namespace Ink_Canvas {
BlackBoardRightSidePageListScrollViewer.ReleaseTouchCapture(e.TouchDevice);
e.Handled = true;
};
// 初始化无焦点模式开关
ToggleSwitchNoFocusMode.IsOn = Settings.Advanced.IsNoFocusMode;
ApplyNoFocusMode();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// 设置窗口为无焦点且置顶(不会抢占焦点且始终在最前)
SetTopmostWithNoActivate(true);
}
#endregion
@@ -435,6 +397,9 @@ namespace Ink_Canvas {
// 初始化插件系统
InitializePluginSystem();
// 确保开关和设置同步
ToggleSwitchNoFocusMode.IsOn = Settings.Advanced.IsNoFocusMode;
ApplyNoFocusMode();
}
private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) {
@@ -1378,5 +1343,35 @@ namespace Ink_Canvas {
BorderSettings.Visibility = Visibility.Visible;
BorderSettingsMask.Visibility = Visibility.Visible;
}
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 0x08000000;
private void ApplyNoFocusMode()
{
var hwnd = new WindowInteropHelper(this).Handle;
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
if (Settings.Advanced.IsNoFocusMode)
{
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
}
else
{
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
}
}
private void ToggleSwitchNoFocusMode_Toggled(object sender, RoutedEventArgs e)
{
if (!isLoaded) return;
var toggle = sender as ToggleSwitch;
Settings.Advanced.IsNoFocusMode = toggle != null && toggle.IsOn;
SaveSettingsToFile();
ApplyNoFocusMode();
}
}
}
+40 -62
View File
@@ -81,6 +81,9 @@ namespace Ink_Canvas {
// 在类中添加字段
private bool wasFloatingBarFoldedWhenEnterSlideShow = false;
// 新增:用于控制WPS强制关闭提示只弹一次
private static bool hasShownWpsForceCloseWarning = false;
private void BtnCheckPPT_Click(object sender, RoutedEventArgs e) {
try {
pptApplication =
@@ -1473,21 +1476,8 @@ namespace Ink_Canvas {
if (!allSaved)
{
// 弹窗提示用户
bool userContinue = false;
Application.Current.Dispatcher.Invoke(() =>
{
var result = MessageBox.Show(
"检测到有未保存的WPS文档,强制关闭可能导致数据丢失。是否继续?",
"警告", MessageBoxButton.YesNo, MessageBoxImage.Warning);
userContinue = (result == MessageBoxResult.Yes);
});
if (!userContinue)
{
LogHelper.WriteLogToFile("用户取消了强制关闭WPS进程", LogHelper.LogType.Trace);
StopWppProcessCheckTimer();
return;
}
// 直接跳过弹窗,自动继续
LogHelper.WriteLogToFile("检测到有未保存的WPS文档,但已取消弹窗提示,自动继续。", LogHelper.LogType.Trace);
}
// 立即结束WPP进程
@@ -1579,6 +1569,7 @@ namespace Ink_Canvas {
public bool IsMaximized { get; set; }
public ForegroundWindowInfo.RECT Rect { get; set; }
public uint ProcessId { get; set; }
public string ProcessName { get; set; } // 新增
}
/// <summary>
@@ -1656,6 +1647,15 @@ namespace Ink_Canvas {
GetWindowThreadProcessId(hWnd, out processId);
windowInfo.ProcessId = processId;
// 新增:获取进程名
windowInfo.ProcessName = "";
try
{
var proc = System.Diagnostics.Process.GetProcessById((int)processId);
windowInfo.ProcessName = proc.ProcessName.ToLower();
}
catch { }
return windowInfo;
}
@@ -1667,58 +1667,30 @@ namespace Ink_Canvas {
if (string.IsNullOrEmpty(windowInfo.Title) && string.IsNullOrEmpty(windowInfo.ClassName))
return false;
// 检查窗口标题
var title = windowInfo.Title.ToLower();
var className = windowInfo.ClassName.ToLower();
var processName = windowInfo.ProcessName ?? "";
// WPS相关关键词(扩展版)
var wpsKeywords = new[]
{
"wps", "演示文稿", "presentation", "powerpoint", "ppt", "pptx",
"kingsoft", "金山", "office", "幻灯片", "slide", "presentation",
"wpp", "wps演示", "wps presentation", "wps office", "kingsoft office"
};
// WPS相关关键词
var wpsKeywords = new[] { "wps", "wpp", "kingsoft", "金山", "wps演示", "wps presentation", "wps office", "kingsoft office" };
// 微软Office相关进程名
var msOfficeProcess = new[] { "powerpnt", "excel", "word", "onenote", "outlook", "microsoftoffice", "office" };
// 检查标题是否包含WPS相关关键词
// 只要进程名是微软Office,直接排除
if (msOfficeProcess.Any(keyword => processName.Contains(keyword)))
return false;
// 只要进程名是WPS/WPP/Kingsoft,直接通过
if (wpsKeywords.Any(keyword => processName.Contains(keyword)))
return true;
// 标题或类名包含WPS相关关键词
bool hasWpsTitle = wpsKeywords.Any(keyword => title.Contains(keyword));
// 检查类名是否包含WPS相关关键词
bool hasWpsClass = wpsKeywords.Any(keyword => className.Contains(keyword));
bool isWpsClass = className.Contains("wps") || className.Contains("kingsoft") || className.Contains("wpp");
bool hasValidSize = (windowInfo.Rect.Right - windowInfo.Rect.Left) > 0 && (windowInfo.Rect.Bottom - windowInfo.Rect.Top) > 0;
// 检查是否为WPS特有的窗口类名
bool isWpsClass = className.Contains("wps") ||
className.Contains("kingsoft") ||
className.Contains("presentation") ||
className.Contains("powerpoint") ||
className.Contains("wpp") ||
className.Contains("office");
// 检查窗口是否有有效尺寸(排除0尺寸窗口)
bool hasValidSize = (windowInfo.Rect.Right - windowInfo.Rect.Left) > 0 &&
(windowInfo.Rect.Bottom - windowInfo.Rect.Top) > 0;
// 检查窗口是否可见且不是最小化状态
bool isActiveWindow = windowInfo.IsVisible && !windowInfo.IsMinimized;
// 检查是否为前台窗口
bool isForegroundWindow = windowInfo.Handle == GetForegroundWindow();
// 综合判断是否为WPS窗口
bool isWpsWindow = (hasWpsTitle || hasWpsClass || isWpsClass) && hasValidSize;
// 如果是前台窗口且包含相关关键词,更可能是WPS窗口
if (isForegroundWindow && (hasWpsTitle || hasWpsClass))
{
isWpsWindow = true;
}
if (isWpsWindow)
{
var windowType = isForegroundWindow ? "前台" : (isActiveWindow ? "活跃" : "后台");
LogHelper.WriteLogToFile($"确认WPS窗口: 标题='{windowInfo.Title}', 类名='{windowInfo.ClassName}', 类型={windowType}, 尺寸={windowInfo.Rect.Right - windowInfo.Rect.Left}x{windowInfo.Rect.Bottom - windowInfo.Rect.Top}", LogHelper.LogType.Trace);
}
return isWpsWindow;
return (hasWpsTitle || hasWpsClass || isWpsClass) && hasValidSize;
}
/// <summary>
@@ -1954,9 +1926,15 @@ namespace Ink_Canvas {
try
{
var pname = process.ProcessName.ToLower();
// 只允许WPS/WPP相关进程,排除PowerPoint及微软Office
if ((pname.Contains("wps") || pname.Contains("wpp") || pname.Contains("presentation"))
// 排除PowerPoint官方进程
&& !pname.Contains("powerpnt"))
&& !pname.Contains("powerpnt")
&& !pname.Contains("office")
&& !pname.Contains("onenote")
&& !pname.Contains("excel")
&& !pname.Contains("word")
&& !pname.Contains("outlook")
&& !pname.Contains("microsoft"))
{
wpsProcesses.Add(process);
LogHelper.WriteLogToFile($"发现WPS进程: {process.ProcessName} (PID: {process.Id})", LogHelper.LogType.Trace);
+4 -4
View File
@@ -105,8 +105,8 @@ namespace Ink_Canvas {
timerDisplayDate.Interval = 1000 * 60 * 60 * 1;
timerDisplayDate.Start();
timerKillProcess.Start();
nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
nowTimeVM.nowTime = DateTime.Now.ToShortTimeString().ToString();
nowTimeVM.nowDate = DateTime.Now.ToString("yyyy/M/d");
nowTimeVM.nowTime = DateTime.Now.ToString("HH:mm");
}
private async Task TimerDisplayTime_ElapsedAsync()
@@ -115,12 +115,12 @@ namespace Ink_Canvas {
// 只更新时间,日期由原有逻辑定时更新即可
Dispatcher.Invoke(() =>
{
nowTimeVM.nowTime = now.ToShortTimeString();
nowTimeVM.nowTime = now.ToString("HH:mm");
});
}
private void TimerDisplayDate_Elapsed(object sender, ElapsedEventArgs e) {
nowTimeVM.nowDate = DateTime.Now.ToShortDateString().ToString();
nowTimeVM.nowDate = DateTime.Now.ToString("yyyy/M/d");
}
private void TimerKillProcess_Elapsed(object sender, ElapsedEventArgs e) {
+2 -2
View File
@@ -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.1.14")]
[assembly: AssemblyFileVersion("1.7.1.14")]
[assembly: AssemblyVersion("1.7.2.0")]
[assembly: AssemblyFileVersion("1.7.2.0")]
+3
View File
@@ -437,6 +437,9 @@ namespace Ink_Canvas
[JsonProperty("isAutoBackupBeforeUpdate")]
public bool IsAutoBackupBeforeUpdate { get; set; } = true;
[JsonProperty("isNoFocusMode")]
public bool IsNoFocusMode { get; set; } = true;
}
public class InkToShape
+31 -1
View File
@@ -1 +1,31 @@
1. 更新了自动更新
1. 改进端点吸附
2. 新增自定义浮动栏图标
3. 新增自定义点名背景
4. 新增退出收纳模式自动进入批注选项
5. 改进自动更新
6. 改进进程检测
7. 改进设置侧边栏
8. 修复PPT联动模块
9. 修复使用正方形预设时多出来一条直线
10. 新增白板自定义调色盘
11. 改进手掌擦逻辑
12. 新增并改进了插件功能
13. 修复大量触摸问题
14. 改进橡皮
15. 新增设置配置备份功能
16. 新增墨迹全屏保存功能
17. 修复win7下的自动更新不可用的问题
18. 改进墨迹打开功能
19. 改进插件功能及启动台插件
20. 改进墨迹平滑方案
21. 改进窗口无焦点
22. 修复白板页面预览不可触摸的问题
23. 新增插入图片功能
24. 新增侧边栏退出放映按钮
25. 新增退出PPT自动恢复收纳模式
26. 新增PPT自动回到首页
27. 新增查杀鸿合屏幕书写后进入批注
28. 修复浮动栏高度计算
29. 修复墨迹错页
30. 改进直线拉直
31. 改进白板时间显示