⚡ 增加多文件备份, 尝试修复UI假死状态, 修复高分屏缩放导致的鼠标追随bug
This commit is contained in:
@@ -61,7 +61,7 @@
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<appSettings>
|
||||
<add key="Version" value="2.5.14" />
|
||||
<add key="Version" value="2.5.15" />
|
||||
<add key="GitHubUrl" value="https://github.com/BookerLiu/GeekDesk" />
|
||||
<add key="GiteeUrl" value="https://gitee.com/BookerLiu/GeekDesk/tree/master" />
|
||||
<add key="GitHubUpdateUrl" value="https://raw.githubusercontent.com/BookerLiu/GeekDesk/master/Update.json" />
|
||||
@@ -70,6 +70,7 @@
|
||||
<add key="ClientSettingsProvider.ServiceUri" value="" />
|
||||
<add key="CustomIconTeachUrl" value="https://mp.weixin.qq.com/s/LxoHAekho9HBVl4FRw_Law" />
|
||||
<add key="ShowPublicWeChat" value="Y" />
|
||||
<add key="BakDays" value="7" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<membership defaultProvider="ClientAuthenticationMembershipProvider">
|
||||
|
||||
28
App.xaml.cs
28
App.xaml.cs
@@ -1,8 +1,14 @@
|
||||
using GeekDesk.Constant;
|
||||
using GeekDesk.MyThread;
|
||||
using GeekDesk.Util;
|
||||
using GeekDesk.ViewModel;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace GeekDesk
|
||||
@@ -20,10 +26,13 @@ namespace GeekDesk
|
||||
this.Startup += new StartupEventHandler(App_Startup);
|
||||
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
SystemEvents.PowerModeChanged += OnPowerModeChanged;
|
||||
}
|
||||
|
||||
|
||||
private void App_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
//RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly; //禁用硬件加速
|
||||
mutex = new System.Threading.Mutex(true, Constants.MY_NAME, out bool ret);
|
||||
if (!ret)
|
||||
{
|
||||
@@ -40,6 +49,25 @@ namespace GeekDesk
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//电源监听
|
||||
private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
{
|
||||
switch (e.Mode)
|
||||
{
|
||||
case PowerModes.Resume:
|
||||
// 系统从休眠状态唤醒
|
||||
LogUtil.WriteLog("System resumed from sleep.");
|
||||
ProcessUtil.ReStartApp();
|
||||
break;
|
||||
case PowerModes.Suspend:
|
||||
// 系统进入休眠状态
|
||||
LogUtil.WriteLog("System is going to sleep.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
e.Handled = true;//使用这一行代码告诉运行时,该异常被处理了,不再作为UnhandledException抛出了。
|
||||
|
||||
@@ -22,7 +22,11 @@ namespace GeekDesk.Constant
|
||||
/// <summary>
|
||||
/// 备份文件路径
|
||||
/// </summary>
|
||||
public static string DATA_FILE_BAK_PATH = APP_DIR + "bak\\Data.bak"; //app备份数据文件路径
|
||||
public static string DATA_FILE_BAK_DIR_PATH = APP_DIR + "bak"; //app备份数据文件路径
|
||||
public static string DATA_FILE_TEMP_DIR_PATH = APP_DIR + "temp"; //app临时缓存文件路径
|
||||
|
||||
//public static string DATA_FILE_BAK_PATH = DATA_FILE_BAK_DIR_PATH + "\\Data.bak"; //app备份数据文件路径
|
||||
|
||||
|
||||
public static string PW_FILE_BAK_PATH = APP_DIR + "bak\\pw.txt"; //密码文件路径
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
<DependentUpon>SecondsWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Plugins\ShowSeconds\ViewModel\SecondsDataContext.cs" />
|
||||
<Compile Include="Task\ShowSecondTask.cs" />
|
||||
<Compile Include="Task\BakTask.cs" />
|
||||
<Compile Include="Task\ToDoTask.cs" />
|
||||
<Compile Include="MyThread\MouseHookThread.cs" />
|
||||
<Compile Include="MyThread\DispatcherBuild.cs" />
|
||||
|
||||
@@ -73,8 +73,11 @@ namespace GeekDesk
|
||||
MarginHide.StartHide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void Window_SourceInitialized(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
@@ -85,6 +88,8 @@ namespace GeekDesk
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -379,6 +384,9 @@ namespace GeekDesk
|
||||
EveryThingUtil.EnableEveryThing();
|
||||
}
|
||||
|
||||
//启动文件备份任务
|
||||
BakTask.Start();
|
||||
|
||||
Keyboard.Focus(SearchBox);
|
||||
|
||||
MessageUtil.ChangeWindowMessageFilter(MessageUtil.WM_COPYDATA, 1);
|
||||
@@ -388,6 +396,7 @@ namespace GeekDesk
|
||||
{
|
||||
Guide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -596,6 +605,7 @@ namespace GeekDesk
|
||||
if (appData.AppConfig.FollowMouse)
|
||||
{
|
||||
ShowWindowFollowMouse.Show(mainWindow, MousePosition.CENTER, 0, 0);
|
||||
//ShowWindowFollowMouse.FollowMouse(mainWindow);
|
||||
}
|
||||
|
||||
|
||||
@@ -853,19 +863,9 @@ namespace GeekDesk
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void ReStartApp(object sender, RoutedEventArgs e)
|
||||
public void ReStartApp(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (appData.AppConfig.MouseMiddleShow || 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();
|
||||
ProcessUtil.ReStartApp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace GeekDesk.MyThread
|
||||
}
|
||||
}
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_BAK_PATH);
|
||||
//CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_BAK_PATH);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -49,5 +49,5 @@ using System.Windows;
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.5.1.3")]
|
||||
[assembly: AssemblyFileVersion("2.5.1.3")]
|
||||
[assembly: AssemblyVersion("2.5.1.5")]
|
||||
[assembly: AssemblyFileVersion("2.5.1.5")]
|
||||
|
||||
92
Task/BakTask.cs
Normal file
92
Task/BakTask.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using GeekDesk.Constant;
|
||||
using GeekDesk.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Task
|
||||
{
|
||||
internal class BakTask
|
||||
{
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
System.Timers.Timer timer = new System.Timers.Timer
|
||||
{
|
||||
Enabled = true,
|
||||
Interval = 60 * 1000 * 60, //60秒 * 60分钟
|
||||
//Interval = 6000,
|
||||
};
|
||||
timer.Start();
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
}
|
||||
|
||||
private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(Constants.DATA_FILE_BAK_DIR_PATH);
|
||||
|
||||
string todayBakName = DateTime.Now.ToString("yyyy-MM-dd") + ".bak";
|
||||
|
||||
string bakDaysStr = ConfigurationManager.AppSettings["BakDays"];
|
||||
int bakDays = 7;
|
||||
if (bakDaysStr != null && !"".Equals(bakDaysStr.Trim()))
|
||||
{
|
||||
bakDays = Int32.Parse(bakDaysStr.Trim());
|
||||
}
|
||||
|
||||
string bakFilePath = Constants.DATA_FILE_BAK_DIR_PATH + "\\" + todayBakName;
|
||||
if (dirInfo.Exists)
|
||||
{
|
||||
// 获取文件信息并按创建时间倒序排序
|
||||
FileInfo[] files = dirInfo.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
FileInfo[] sortedFiles = files.OrderByDescending(file => file.CreationTime).ToArray();
|
||||
if (!sortedFiles[0].Name.Equals(todayBakName))
|
||||
{
|
||||
//今天未创建备份 开始创建今天的备份
|
||||
createBakFile(bakFilePath);
|
||||
}
|
||||
|
||||
//判断文件是否超过了7个 超过7个就删除
|
||||
if (sortedFiles.Length > bakDays)
|
||||
{
|
||||
for (int i = bakDays; i < sortedFiles.Length; i++)
|
||||
{
|
||||
sortedFiles[i].Delete();
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
//没有文件 直接创建今天的备份
|
||||
createBakFile(bakFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
dirInfo.Create();
|
||||
}
|
||||
}
|
||||
|
||||
//创建备份文件
|
||||
private static void createBakFile(string filePath)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
bf.Serialize(fs, MainWindow.appData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Task
|
||||
{
|
||||
internal class ShowSecondTask
|
||||
{
|
||||
|
||||
public static void SHowSecond()
|
||||
{
|
||||
System.Timers.Timer timer = new System.Timers.Timer
|
||||
{
|
||||
Enabled = true,
|
||||
Interval = 5000
|
||||
};
|
||||
timer.Start();
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
}
|
||||
|
||||
private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
Process[] pcArr = Process.GetProcessesByName("ShellExperienceHost.exe");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"title": "GeekDesk版本更新",
|
||||
"subTitle": "V2.5.14",
|
||||
"subTitle": "V2.5.15",
|
||||
"msgTitle": "本次更新内容如下",
|
||||
"msg": "['好久不见, 别来无恙, 辞职回老家了, 我是个多愁善感的人, 心里有些仿徨和迷茫, 祝所有人都前程似锦, 世界和平.', 'GeekDesk准备冲击一下Gitee GVP, 希望大家能给我点一下码云(Gitee)和GitHub的star❤❤❤', '之后我会抽时间编写一下开发者文档, 方便大家更清楚的了解项目结构, 从而有更多的人参与进来开发(一直没有编写是因为太懒了), 不多说了, 看下这次更新内容吧', '集成Everything搜索,设置-->其它-->勾选Everything插件开启', '增加了关联文件夹功能, 右键点击左侧栏-->新建关联菜单', '增加强制置顶开关,设置-->显示设置-->勾选/取消 置于顶层', '右侧栏图标列表增加了自适应列宽, 不会出现图标显示一半的情况了', '简单添加了新手引导提示', '加密菜单bug修复 By @1062406901', '多显示器拾色器bug修复 By @1062406901', '拖动图标到菜单的异常修复 By @Hsxxxxxx', '优化部分UI', '其它bug修复及功能优化','关注微信公众号\\'抓几个娃\\'可以第一时间收到更新通知(公众号也是佛系维护, 希望能关注的人多一点吧, 让作者这个穷B挣口饭吃)']",
|
||||
"msg": "['鸽了挺久, 我终于又来更新了, 废话不多说, 看下本次更新内容', '增加多文件备份, 数据文件损坏会自动寻找最近的一次备份数据, 不用担心数据文件损坏了, 备份数据默认为最近7天, 可以通过打开根目录下GeekDesk.exe.config, 找到BakDays修改', '修复高分屏缩放导致的鼠标追随bug', 'UI假死的情况, 由于并不是每个用户都出现这个bug, 这次做了尝试性修复, 各位可以看下是否还会出现切换菜单出现不会出现图标的情况']",
|
||||
"githubUrl": "https://github.com/BookerLiu/GeekDesk/releases",
|
||||
"giteeUrl": "https://gitee.com/BookerLiu/GeekDesk/releases",
|
||||
"statisticUrl": "http://43.138.23.39:8989/bookerService/geekDeskController/userCountStatistic",
|
||||
"version": "2.5.14"
|
||||
"version": "2.5.15"
|
||||
}
|
||||
|
||||
@@ -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