add:UIA窗口置顶
This commit is contained in:
+28
-3
@@ -41,6 +41,8 @@ namespace Ink_Canvas
|
|||||||
private static Process watchdogProcess;
|
private static Process watchdogProcess;
|
||||||
// 新增:标记是否为软件内主动退出
|
// 新增:标记是否为软件内主动退出
|
||||||
public static bool IsAppExitByUser;
|
public static bool IsAppExitByUser;
|
||||||
|
// 新增:标记是否启用了UIA置顶功能
|
||||||
|
public static bool IsUIAccessTopMostEnabled;
|
||||||
// 新增:退出信号文件路径
|
// 新增:退出信号文件路径
|
||||||
private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + Process.GetCurrentProcess().Id + ".flag");
|
private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + Process.GetCurrentProcess().Id + ".flag");
|
||||||
// 新增:崩溃日志文件路径
|
// 新增:崩溃日志文件路径
|
||||||
@@ -629,7 +631,7 @@ namespace Ink_Canvas
|
|||||||
LogHelper.WriteLogToFile("App | 检测到最终应用启动(更新后的应用)");
|
LogHelper.WriteLogToFile("App | 检测到最终应用启动(更新后的应用)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在应用启动时自动释放IACore相关DLL
|
// 释放IACore相关DLL
|
||||||
if (_isSplashScreenShown)
|
if (_isSplashScreenShown)
|
||||||
{
|
{
|
||||||
SetSplashMessage("正在初始化组件...");
|
SetSplashMessage("正在初始化组件...");
|
||||||
@@ -645,6 +647,22 @@ namespace Ink_Canvas
|
|||||||
LogHelper.WriteLogToFile($"释放IACore DLL时出错: {ex.Message}", LogHelper.LogType.Error);
|
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)
|
if (_isSplashScreenShown)
|
||||||
{
|
{
|
||||||
@@ -1055,7 +1073,15 @@ namespace Ink_Canvas
|
|||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
}
|
}
|
||||||
// 主进程异常退出,自动重启前判断崩溃后操作
|
// 主进程异常退出,自动重启前判断崩溃后操作
|
||||||
SyncCrashActionFromSettings(); // 新增:同步设置
|
SyncCrashActionFromSettings(); // 同步设置
|
||||||
|
|
||||||
|
if (IsUIAccessTopMostEnabled)
|
||||||
|
{
|
||||||
|
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
|
Process.Start(exePath);
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (CrashAction == CrashActionType.SilentRestart)
|
if (CrashAction == CrashActionType.SilentRestart)
|
||||||
{
|
{
|
||||||
StartupCount.Increment();
|
StartupCount.Increment();
|
||||||
@@ -1068,7 +1094,6 @@ namespace Ink_Canvas
|
|||||||
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
string exePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
Process.Start(exePath);
|
Process.Start(exePath);
|
||||||
}
|
}
|
||||||
// CrashActionType.NoAction 时不重启,直接退出
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -198,6 +198,8 @@
|
|||||||
<EmbeddedResource Include="Resources\IACore\IACore.dll" />
|
<EmbeddedResource Include="Resources\IACore\IACore.dll" />
|
||||||
<EmbeddedResource Include="Resources\IACore\IALoader.dll" />
|
<EmbeddedResource Include="Resources\IACore\IALoader.dll" />
|
||||||
<EmbeddedResource Include="Resources\IACore\IAWinFX.dll" />
|
<EmbeddedResource Include="Resources\IACore\IAWinFX.dll" />
|
||||||
|
<EmbeddedResource Include="UIAccessDLL_x64.dll" />
|
||||||
|
<EmbeddedResource Include="UIAccessDLL_x86.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Resource Include="Resources\Cursors\Cursor.cur" />
|
<Resource Include="Resources\Cursors\Cursor.cur" />
|
||||||
|
|||||||
@@ -610,6 +610,14 @@
|
|||||||
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
Toggled="ToggleSwitchAlwaysOnTop_Toggled" />
|
Toggled="ToggleSwitchAlwaysOnTop_Toggled" />
|
||||||
</ui:SimpleStackPanel>
|
</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=""
|
<ui:ToggleSwitch OnContent="" OffContent=""
|
||||||
Name="ToggleSwitchIsAutoUpdate" Header="自动检查更新"
|
Name="ToggleSwitchIsAutoUpdate" Header="自动检查更新"
|
||||||
FontFamily="Microsoft YaHei UI"
|
FontFamily="Microsoft YaHei UI"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Principal;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@@ -38,6 +39,12 @@ namespace Ink_Canvas
|
|||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
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对象
|
// 每一页一个Canvas对象
|
||||||
private List<System.Windows.Controls.Canvas> whiteboardPages = new List<System.Windows.Controls.Canvas>();
|
private List<System.Windows.Controls.Canvas> whiteboardPages = new List<System.Windows.Controls.Canvas>();
|
||||||
private int currentPageIndex;
|
private int currentPageIndex;
|
||||||
@@ -550,6 +557,12 @@ namespace Ink_Canvas
|
|||||||
ToggleSwitchAlwaysOnTop.IsOn = Settings.Advanced.IsAlwaysOnTop;
|
ToggleSwitchAlwaysOnTop.IsOn = Settings.Advanced.IsAlwaysOnTop;
|
||||||
ApplyAlwaysOnTop();
|
ApplyAlwaysOnTop();
|
||||||
|
|
||||||
|
// 初始化UIA置顶开关
|
||||||
|
ToggleSwitchUIAccessTopMost.IsOn = Settings.Advanced.EnableUIAccessTopMost;
|
||||||
|
UpdateUIAccessTopMostVisibility();
|
||||||
|
|
||||||
|
App.IsUIAccessTopMostEnabled = Settings.Advanced.EnableUIAccessTopMost;
|
||||||
|
|
||||||
// 初始化剪贴板监控
|
// 初始化剪贴板监控
|
||||||
InitializeClipboardMonitoring();
|
InitializeClipboardMonitoring();
|
||||||
|
|
||||||
@@ -2030,6 +2043,21 @@ namespace Ink_Canvas
|
|||||||
Settings.Advanced.IsAlwaysOnTop = toggle != null && toggle.IsOn;
|
Settings.Advanced.IsAlwaysOnTop = toggle != null && toggle.IsOn;
|
||||||
SaveSettingsToFile();
|
SaveSettingsToFile();
|
||||||
ApplyAlwaysOnTop();
|
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)
|
private void Window_Activated(object sender, EventArgs e)
|
||||||
@@ -2923,5 +2951,82 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#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
|
||||||
|
{
|
||||||
|
// 调用UIAccess DLL
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
{
|
||||||
|
PrepareUIAccessX64();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrepareUIAccessX86();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ namespace Ink_Canvas
|
|||||||
#region 主要的工具按鈕事件
|
#region 主要的工具按鈕事件
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 浮動工具欄的"套索選"按鈕事件,重定向到舊UI的<c>BtnSelect_Click</c>方法
|
/// 浮動工具欄的"套索選"按鈕事件,重定向到舊UI的<c>BtnSelect_Click</c>方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">sender</param>
|
/// <param name="sender">sender</param>
|
||||||
/// <param name="e">MouseButtonEventArgs</param>
|
/// <param name="e">MouseButtonEventArgs</param>
|
||||||
|
|||||||
@@ -591,6 +591,9 @@ namespace Ink_Canvas
|
|||||||
|
|
||||||
[JsonProperty("isAlwaysOnTop")]
|
[JsonProperty("isAlwaysOnTop")]
|
||||||
public bool IsAlwaysOnTop { get; set; } = true;
|
public bool IsAlwaysOnTop { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("enableUIAccessTopMost")]
|
||||||
|
public bool EnableUIAccessTopMost { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InkToShape
|
public class InkToShape
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user