⚡ 增加多文件备份, 尝试修复UI假死状态, 修复高分屏缩放导致的鼠标追随bug
This commit is contained in:
@@ -8,6 +8,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Windows;
|
||||
@@ -34,6 +35,7 @@ namespace GeekDesk.Util
|
||||
using (FileStream fs = File.Create(Constants.DATA_FILE_PATH)) { }
|
||||
appData = new AppData();
|
||||
SaveAppData(appData, Constants.DATA_FILE_PATH);
|
||||
return appData;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -49,51 +51,103 @@ namespace GeekDesk.Util
|
||||
{
|
||||
SavePassword(appData.AppConfig.MenuPassword);
|
||||
}
|
||||
return appData;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (File.Exists(Constants.DATA_FILE_BAK_PATH))
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(Constants.DATA_FILE_BAK_DIR_PATH);
|
||||
FileInfo[] files = dirInfo.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
try
|
||||
FileInfo[] sortedFiles = files.OrderByDescending(file => file.CreationTime).ToArray();
|
||||
//循环获取可用备份文件
|
||||
string bakFilePath = "";
|
||||
foreach (FileInfo bakFile in sortedFiles)
|
||||
{
|
||||
using (FileStream fs = new FileStream(Constants.DATA_FILE_BAK_PATH, FileMode.Open))
|
||||
if (!Directory.Exists(Constants.DATA_FILE_TEMP_DIR_PATH)) { Directory.CreateDirectory(Constants.DATA_FILE_TEMP_DIR_PATH); }
|
||||
bakFilePath = Constants.DATA_FILE_TEMP_DIR_PATH + "\\" + bakFile.Name;
|
||||
try
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
appData = bf.Deserialize(fs) as AppData;
|
||||
File.Copy(bakFile.FullName, bakFilePath, true);
|
||||
using (FileStream fs = new FileStream(bakFilePath, FileMode.Open))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
appData = bf.Deserialize(fs) as AppData;
|
||||
}
|
||||
DialogMsg msg = new DialogMsg();
|
||||
msg.msg = "不幸的是, GeekDesk当前的数据文件已经损坏, " +
|
||||
"现在已经启用系统自动备份的数据\n\n" +
|
||||
"如果你有较新的备份, " +
|
||||
"请退出GeekDesk, " +
|
||||
"将备份文件重命名为:Data, " +
|
||||
"然后将Data覆盖到GeekDesk的根目录即可\n\n" +
|
||||
"启用的备份文件为: \n" + bakFilePath +
|
||||
"\n\n如果当前数据就是你想要的数据, 那么请不用管它";
|
||||
GlobalMsgNotification gm = new GlobalMsgNotification(msg);
|
||||
HandyControl.Controls.Notification ntf = HandyControl.Controls.Notification.Show(gm, ShowAnimation.Fade, true);
|
||||
gm.ntf = ntf;
|
||||
File.Delete(bakFilePath);
|
||||
SaveAppData(appData, Constants.DATA_FILE_PATH);
|
||||
return appData;
|
||||
}
|
||||
catch {
|
||||
if (File.Exists(bakFilePath))
|
||||
{
|
||||
File.Delete(bakFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
DialogMsg msg = new DialogMsg();
|
||||
msg.msg = "不幸的是, GeekDesk当前的数据文件已经损坏, " +
|
||||
"现在已经启用系统自动备份的数据\n\n" +
|
||||
"如果你有较新的备份, " +
|
||||
"请退出GeekDesk, " +
|
||||
"将备份文件重命名为:Data, " +
|
||||
"然后将Data覆盖到GeekDesk的根目录即可\n\n" +
|
||||
"系统上次备份时间: \n" + appData.AppConfig.SysBakTime +
|
||||
"\n\n如果当前数据就是你想要的数据, 那么请不用管它";
|
||||
GlobalMsgNotification gm = new GlobalMsgNotification(msg);
|
||||
HandyControl.Controls.Notification ntf = HandyControl.Controls.Notification.Show(gm, ShowAnimation.Fade, true);
|
||||
gm.ntf = ntf;
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show("不幸的是, GeekDesk当前的数据文件已经损坏\n如果你有备份, 请将备份文件重命名为:Data 然后将Data覆盖到GeekDesk的根目录即可!");
|
||||
Application.Current.Shutdown();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
MessageBox.Show("不幸的是, GeekDesk当前的数据文件已经损坏\n如果你有备份, 请将备份文件重命名为:Data 然后将Data覆盖到GeekDesk的根目录即可!");
|
||||
Application.Current.Shutdown();
|
||||
return new AppData();
|
||||
} else
|
||||
{
|
||||
MessageBox.Show("不幸的是, GeekDesk当前的数据文件已经损坏\n如果你有备份, 请将备份文件重命名为:Data 然后将Data覆盖到GeekDesk的根目录即可!");
|
||||
Application.Current.Shutdown();
|
||||
return null;
|
||||
return new AppData();
|
||||
}
|
||||
|
||||
// if (File.Exists(Constants.DATA_FILE_BAK_PATH))
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// using (FileStream fs = new FileStream(Constants.DATA_FILE_BAK_PATH, FileMode.Open))
|
||||
// {
|
||||
// BinaryFormatter bf = new BinaryFormatter();
|
||||
// appData = bf.Deserialize(fs) as AppData;
|
||||
// }
|
||||
|
||||
// DialogMsg msg = new DialogMsg();
|
||||
// msg.msg = "不幸的是, GeekDesk当前的数据文件已经损坏, " +
|
||||
// "现在已经启用系统自动备份的数据\n\n" +
|
||||
// "如果你有较新的备份, " +
|
||||
// "请退出GeekDesk, " +
|
||||
// "将备份文件重命名为:Data, " +
|
||||
// "然后将Data覆盖到GeekDesk的根目录即可\n\n" +
|
||||
// "系统上次备份时间: \n" + appData.AppConfig.SysBakTime +
|
||||
// "\n\n如果当前数据就是你想要的数据, 那么请不用管它";
|
||||
// GlobalMsgNotification gm = new GlobalMsgNotification(msg);
|
||||
// HandyControl.Controls.Notification ntf = HandyControl.Controls.Notification.Show(gm, ShowAnimation.Fade, true);
|
||||
// gm.ntf = ntf;
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// MessageBox.Show("不幸的是, GeekDesk当前的数据文件已经损坏\n如果你有备份, 请将备份文件重命名为:Data 然后将Data覆盖到GeekDesk的根目录即可!");
|
||||
// Application.Current.Shutdown();
|
||||
// return null;
|
||||
// }
|
||||
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// MessageBox.Show("不幸的是, GeekDesk当前的数据文件已经损坏\n如果你有备份, 请将备份文件重命名为:Data 然后将Data覆盖到GeekDesk的根目录即可!");
|
||||
// Application.Current.Shutdown();
|
||||
// return null;
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
return appData;
|
||||
}
|
||||
|
||||
private readonly static object _MyLock = new object();
|
||||
@@ -105,10 +159,10 @@ namespace GeekDesk.Util
|
||||
{
|
||||
lock (_MyLock)
|
||||
{
|
||||
if (filePath.Equals(Constants.DATA_FILE_BAK_PATH))
|
||||
{
|
||||
appData.AppConfig.SysBakTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
//if (filePath.Equals(Constants.DATA_FILE_BAK_PATH))
|
||||
//{
|
||||
// appData.AppConfig.SysBakTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
//}
|
||||
if (!Directory.Exists(filePath.Substring(0, filePath.LastIndexOf("\\"))))
|
||||
{
|
||||
Directory.CreateDirectory(filePath.Substring(0, filePath.LastIndexOf("\\")));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using GeekDesk.Constant;
|
||||
using GeekDesk.MyThread;
|
||||
using GeekDesk.ViewModel;
|
||||
using HandyControl.Controls;
|
||||
using System;
|
||||
@@ -9,6 +10,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
@@ -241,6 +243,21 @@ namespace GeekDesk.Util
|
||||
}
|
||||
|
||||
|
||||
public static void ReStartApp()
|
||||
{
|
||||
if (MainWindow.appData.AppConfig.MouseMiddleShow || MainWindow.appData.AppConfig.SecondsWindow == true)
|
||||
{
|
||||
MouseHookThread.Dispose();
|
||||
}
|
||||
|
||||
Process p = new Process();
|
||||
p.StartInfo.FileName = Constants.APP_DIR + "GeekDesk.exe";
|
||||
p.StartInfo.WorkingDirectory = Constants.APP_DIR;
|
||||
p.Start();
|
||||
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum ProcessAccessFlags : uint
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using GeekDesk.Constant;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
@@ -18,6 +21,86 @@ namespace GeekDesk.Util
|
||||
RIGHT_CENTER = 7
|
||||
}
|
||||
|
||||
public static void FollowMouse(Window window)
|
||||
{
|
||||
// Get the mouse position
|
||||
var mousePosition = System.Windows.Forms.Control.MousePosition;
|
||||
|
||||
// Get the window size
|
||||
var windowWidth = window.Width;
|
||||
var windowHeight = window.Height;
|
||||
|
||||
Console.WriteLine("windowWidth + windowHeight:" + windowWidth + "+" + windowHeight);
|
||||
|
||||
// Get the screen where the mouse is located
|
||||
var screen = System.Windows.Forms.Screen.FromPoint(new System.Drawing.Point(mousePosition.X, mousePosition.Y));
|
||||
var workingArea = screen.WorkingArea;
|
||||
|
||||
// Get the DPI scaling factor for the screen
|
||||
//float dpiX, dpiY;
|
||||
//using (var graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero))
|
||||
//{
|
||||
// dpiX = graphics.DpiX / 96f; // 96 is the default DPI
|
||||
// dpiY = graphics.DpiY / 96f; // 96 is the default DPI
|
||||
//}
|
||||
|
||||
float dpiX = GetDpi( true);
|
||||
float dpiY = GetDpi(false);
|
||||
|
||||
// Convert mouse position to logical pixels based on DPI
|
||||
double mouseX = mousePosition.X / dpiX;
|
||||
double mouseY = mousePosition.Y / dpiY;
|
||||
|
||||
// Calculate target position to center the window on the mouse
|
||||
double targetLeft = mouseX - windowWidth / 2;
|
||||
double targetTop = mouseY - windowHeight / 2;
|
||||
|
||||
// Ensure the window does not exceed the screen boundaries
|
||||
if (targetLeft < workingArea.Left / dpiX)
|
||||
targetLeft = workingArea.Left / dpiX;
|
||||
if (targetLeft + windowWidth / dpiX > workingArea.Right / dpiX)
|
||||
targetLeft = workingArea.Right / dpiX - windowWidth / dpiX;
|
||||
|
||||
if (targetTop < workingArea.Top / dpiY)
|
||||
targetTop = workingArea.Top / dpiY;
|
||||
if (targetTop + windowHeight / dpiY > workingArea.Bottom / dpiY)
|
||||
targetTop = workingArea.Bottom / dpiY - windowHeight / dpiY;
|
||||
|
||||
// Update window position
|
||||
window.Left = targetLeft * dpiX;
|
||||
window.Top = targetTop * dpiY;
|
||||
}
|
||||
|
||||
private static float GetDpi(bool isX)
|
||||
{
|
||||
IntPtr hdc = WindowUtil.GetDC(IntPtr.Zero);
|
||||
int dpi = isX ? WindowUtil.GetDeviceCaps(hdc, LOGPIXELSX) : WindowUtil.GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
WindowUtil.ReleaseDC(IntPtr.Zero, hdc);
|
||||
return dpi / 96f;
|
||||
}
|
||||
|
||||
private static IntPtr GetScreenHandleFromMouse()
|
||||
{
|
||||
// Get the mouse position
|
||||
var mousePosition = System.Windows.Forms.Control.MousePosition;
|
||||
|
||||
// Convert mouse position to a POINT structure
|
||||
System.Drawing.Point point = new System.Drawing.Point(mousePosition.X, mousePosition.Y);
|
||||
|
||||
// Get the window handle from the point
|
||||
IntPtr windowHandle = WindowUtil.WindowFromPoint(point);
|
||||
|
||||
return windowHandle;
|
||||
}
|
||||
|
||||
// Constants for DPI
|
||||
private const int HORZRES = 8;
|
||||
private const int VERTRES = 10;
|
||||
private const int LOGPIXELSX = 88;
|
||||
private const int LOGPIXELSY = 90;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随鼠标位置显示面板
|
||||
/// </summary>
|
||||
@@ -25,6 +108,12 @@ namespace GeekDesk.Util
|
||||
{
|
||||
//获取鼠标位置
|
||||
System.Windows.Point p = MouseUtil.GetMousePosition();
|
||||
|
||||
float dpiX = GetDpi(true);
|
||||
float dpiY = GetDpi(false);
|
||||
p.X = p.X / dpiX;
|
||||
p.Y = p.Y / dpiY;
|
||||
|
||||
double left = SystemParameters.VirtualScreenLeft;
|
||||
double top = SystemParameters.VirtualScreenTop;
|
||||
double width = SystemParameters.VirtualScreenWidth;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@@ -9,6 +10,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
using static GeekDesk.Util.FileIcon;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
@@ -42,6 +44,9 @@ namespace GeekDesk.Util
|
||||
SWP_NOSENDCHANGING = 0x0400
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr WindowFromPoint(System.Drawing.Point p);
|
||||
|
||||
//取得前台窗口句柄函数
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
@@ -71,6 +76,60 @@ namespace GeekDesk.Util
|
||||
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); //获取线程ID
|
||||
/// <summary>
|
||||
/// 枚举窗口时的委托参数
|
||||
/// </summary>
|
||||
/// <param name="hWnd"></param>
|
||||
/// <param name="lParam"></param>
|
||||
/// <returns></returns>
|
||||
public delegate bool WndEnumProc(IntPtr hWnd, int lParam);
|
||||
/// <summary>
|
||||
/// 枚举所有窗口
|
||||
/// </summary>
|
||||
/// <param name="lpEnumFunc"></param>
|
||||
/// <param name="lParam"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam);
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口的父窗口句柄
|
||||
/// </summary>
|
||||
/// <param name="hWnd"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetParent(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);
|
||||
|
||||
// Import GetDC and ReleaseDC functions from user32.dll
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public readonly struct LPRECT
|
||||
{
|
||||
public readonly int Left;
|
||||
public readonly int Top;
|
||||
public readonly int Right;
|
||||
public readonly int Bottom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private const int GWL_STYLE = -16;
|
||||
@@ -82,6 +141,112 @@ namespace GeekDesk.Util
|
||||
SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MAXIMIZEBOX));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Win32 窗口的一些基本信息。
|
||||
/// </summary>
|
||||
public struct WindowInfo
|
||||
{
|
||||
public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this()
|
||||
{
|
||||
Hwnd = hWnd;
|
||||
ClassName = className;
|
||||
Title = title;
|
||||
IsVisible = isVisible;
|
||||
Bounds = bounds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口句柄。
|
||||
/// </summary>
|
||||
public IntPtr Hwnd { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口类名。
|
||||
/// </summary>
|
||||
public string ClassName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口标题。
|
||||
/// </summary>
|
||||
public string Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前窗口是否可见。
|
||||
/// </summary>
|
||||
public bool IsVisible { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口当前的位置和尺寸。
|
||||
/// </summary>
|
||||
public Rectangle Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口当前是否是最小化的。
|
||||
/// </summary>
|
||||
public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 遍历窗体处理的函数
|
||||
/// </summary>
|
||||
/// <param name="hWnd"></param>
|
||||
/// <param name="lparam"></param>
|
||||
/// <returns></returns>
|
||||
private static bool OnWindowEnum(IntPtr hWnd, int lparam)
|
||||
{
|
||||
|
||||
// 仅查找顶层窗口。
|
||||
//if (GetParent(hWnd) == IntPtr.Zero)
|
||||
//{
|
||||
// 获取窗口类名。
|
||||
var lpString = new StringBuilder(512);
|
||||
GetClassName(hWnd, lpString, lpString.Capacity);
|
||||
var className = lpString.ToString();
|
||||
|
||||
// 获取窗口标题。
|
||||
var lptrString = new StringBuilder(512);
|
||||
GetWindowText(hWnd, lptrString, lptrString.Capacity);
|
||||
var title = lptrString.ToString().Trim();
|
||||
|
||||
// 获取窗口可见性。
|
||||
var isVisible = IsWindowVisible(hWnd);
|
||||
|
||||
// 获取窗口位置和尺寸。
|
||||
LPRECT rect = default;
|
||||
GetWindowRect(hWnd, ref rect);
|
||||
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
|
||||
|
||||
// 添加到已找到的窗口列表。
|
||||
windowList.Add(new WindowInfo(hWnd, className, title, isVisible, bounds));
|
||||
//}
|
||||
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 默认的查找窗口的过滤条件。可见 + 非最小化 + 包含窗口标题。
|
||||
/// </summary>
|
||||
private static readonly Predicate<WindowInfo> DefaultPredicate = x => x.IsVisible && !x.IsMinimized && x.Title.Length > 0;
|
||||
/// <summary>
|
||||
/// 窗体列表
|
||||
/// </summary>
|
||||
private static List<WindowInfo> windowList;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查找当前用户空间下所有符合条件的(顶层)窗口。如果不指定条件,将仅查找可见且有标题栏的窗口。
|
||||
/// </summary>
|
||||
/// <param name="match">过滤窗口的条件。如果设置为 null,将仅查找可见和标题栏不为空的窗口。</param>
|
||||
/// <returns>找到的所有窗口信息</returns>
|
||||
public static IReadOnlyList<WindowInfo> FindAllWindows(Predicate<WindowInfo> match = null)
|
||||
{
|
||||
windowList = new List<WindowInfo>();
|
||||
//遍历窗口并查找窗口相关WindowInfo信息
|
||||
EnumWindows(OnWindowEnum, 0);
|
||||
return windowList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void SetOwner(Window window, Window parentWindow)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user