Browse Source

Merge pull request #155 from BookerLiu/2.5.15

2.5.15
Booker 7 months ago
parent
commit
7f0e228f78
39 changed files with 1314 additions and 261 deletions
  1. 3 2
      App.config
  2. 28 0
      App.xaml.cs
  3. 7 3
      Constant/Constants.cs
  4. 17 0
      Constant/DictConst.cs
  5. 34 0
      Control/Other/BGNmaeDialog.xaml
  6. 42 0
      Control/Other/BGNmaeDialog.xaml.cs
  7. 15 6
      Control/Other/GradientBGDialog.xaml
  8. 42 4
      Control/Other/GradientBGDialog.xaml.cs
  9. 17 3
      Control/UserControls/Config/ThemeControl.xaml
  10. 11 1
      Control/UserControls/Config/ThemeControl.xaml.cs
  11. 10 0
      Control/UserControls/PannelCard/LeftCardControl.xaml.cs
  12. 18 1
      Control/UserControls/PannelCard/RightCardControl.xaml
  13. 58 1
      Control/UserControls/PannelCard/RightCardControl.xaml.cs
  14. 4 0
      Control/Windows/ConfigWindow.xaml
  15. 1 0
      Control/Windows/PixelColorPickerWindow.xaml
  16. 79 28
      Control/Windows/PixelColorPickerWindow.xaml.cs
  17. 1 1
      Control/Windows/ToDoInfoWindow.xaml
  18. 39 0
      Converts/Boolean2VisibilityConverter.cs
  19. 30 0
      Converts/TextToColorConverter.cs
  20. 32 0
      Converts/ValueConvert.cs
  21. 16 4
      GeekDesk.csproj
  22. 14 14
      MainWindow.xaml.cs
  23. 1 1
      MyThread/RelativePathThread.cs
  24. 15 1
      Plugins/ShowSeconds/SecondsWindow.xaml.cs
  25. 2 2
      Properties/AssemblyInfo.cs
  26. 93 0
      Task/BakTask.cs
  27. 0 31
      Task/ShowSecondTask.cs
  28. 29 28
      Task/UpdateTask.cs
  29. 3 3
      Update.json
  30. 90 35
      Util/CommonCode.cs
  31. 28 0
      Util/DeepCopyUtil.cs
  32. 24 4
      Util/ProcessUtil.cs
  33. 228 64
      Util/ShowWindowFollowMouse.cs
  34. 180 11
      Util/WindowUtil.cs
  35. 67 6
      ViewModel/AppConfig.cs
  36. 16 2
      ViewModel/GradientBGParam.cs
  37. 16 1
      ViewModel/IconInfo.cs
  38. 3 3
      ViewModel/Temp/GradientBGParamList.cs
  39. 1 1
      packages.config

+ 3 - 2
App.config

@@ -61,15 +61,16 @@
 		</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" />
 		<add key="GiteeUpdateUrl" value="https://gitee.com/BookerLiu/GeekDesk/raw/master/Update.json" />
-		<!--<add key="GiteeUpdateUrl" value="file:///D:/WorkSpace/workspace-VS/GeekDesk/Update.json" />-->
+		<!--<add key="GiteeUpdateUrl" value="file:///D:/WorkSpace/VS/GeekDesk/Update.json" />-->
 		<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 - 0
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抛出了。

+ 7 - 3
Constant/Constants.cs

@@ -22,11 +22,15 @@ 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";  //密码文件路径
 
-        public static string UUID_FILE_BAK_PATH = APP_DIR + "bak\\uuid.txt";  //密码文件路径
+        public static string PW_FILE_BAK_PATH = APP_DIR + "bak\\pw.txt";  //密码文件路径
+        
+        public static string UUID_FILE_BAK_PATH = APP_DIR + "bak\\uuid.txt";  //uuid文件路径
 
         public static string LOG_FILE_PATH = APP_DIR + "logs\\log.log"; //日志文件
 

+ 17 - 0
Constant/DictConst.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace GeekDesk.Constant
+{
+    public class DictConst
+    {
+        public static readonly Dictionary<bool, string> batchMenuHeaderDict = new Dictionary<bool, string>();
+        static DictConst() {
+            batchMenuHeaderDict.Add(true, "取消批量操作");
+            batchMenuHeaderDict.Add(false, "批量操作");
+        }
+    }
+}

+ 34 - 0
Control/Other/BGNmaeDialog.xaml

@@ -0,0 +1,34 @@
+<Border x:Class="GeekDesk.Control.Other.BGNmaeDialog"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:hc="https://handyorg.github.io/handycontrol"
+        xmlns:cvt="clr-namespace:GeekDesk.Converts"
+        CornerRadius="4"
+        Width="350"
+        Height="160"
+        Style="{StaticResource BorderBG}"
+        >
+    <Border.Resources>
+        <Style x:Key="LeftTB" TargetType="TextBlock" BasedOn="{StaticResource TextBlockBaseStyle}">
+            <Setter Property="Width" Value="75"/>
+            <Setter Property="TextAlignment" Value="Left"/>
+            <Setter Property="HorizontalAlignment" Value="Left"/>
+            <Setter Property="VerticalAlignment" Value="Center"/>
+            <Setter Property="Margin" Value="5,8,0,0"/>
+            <Setter Property="FontSize" Value="14"/>
+        </Style>
+        <cvt:StringAppendConvert x:Key="StringAppendConvert"/>
+    </Border.Resources>
+    <hc:SimplePanel Margin="10" VerticalAlignment="Center">
+        <StackPanel>
+            <Button Width="22"  Height="22" Command="hc:ControlCommands.Close" Style="{StaticResource ButtonIcon}" Foreground="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" hc:IconElement.Geometry="{StaticResource ErrorGeometry}" Padding="0" HorizontalAlignment="Right" VerticalAlignment="Top"/>
+            <hc:UniformSpacingPanel Spacing="10" Margin="0,15,0,0">
+                <TextBlock Text="起个名字吧:"  Style="{StaticResource LeftTB}"/>
+                <TextBox x:Name="BGName" Style="{StaticResource MyTextBoxStyle}" Text="{Binding Name, Mode=OneWay}" Width="230" FontSize="14"/>
+            </hc:UniformSpacingPanel>
+            <hc:UniformSpacingPanel Margin="0,25,0,0" Spacing="10"  Grid.ColumnSpan="4">
+                <Button Content="保存" Style="{StaticResource MyBtnStyle}" Click="Save" Margin="265,10,0,0"/>
+            </hc:UniformSpacingPanel>
+        </StackPanel>
+    </hc:SimplePanel>
+</Border>

+ 42 - 0
Control/Other/BGNmaeDialog.xaml.cs

@@ -0,0 +1,42 @@
+using GeekDesk.Constant;
+using GeekDesk.Util;
+using GeekDesk.ViewModel;
+using Microsoft.Win32;
+using System;
+using System.Windows;
+using System.Windows.Media.Imaging;
+
+
+namespace GeekDesk.Control.Other
+{
+    /// <summary>
+    /// TextDialog.xaml 的交互逻辑
+    /// </summary>
+    public partial class BGNmaeDialog
+    {
+        public HandyControl.Controls.Dialog dialog;
+
+        public BGNmaeDialog()
+        {
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// 保存
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void Save(object sender, RoutedEventArgs e)
+        {
+            GradientBGParam bg = new GradientBGParam();
+            bg.Id = Guid.NewGuid().ToString();
+            bg.Name = BGName.Text;
+            bg.Color1 = MainWindow.appData.AppConfig.GradientBGParam.Color1;
+            bg.Color2 = MainWindow.appData.AppConfig.GradientBGParam.Color2;
+            MainWindow.appData.AppConfig.CustomBGParams.Add(bg);
+            MainWindow.appData.AppConfig.CustomBGParams = DeepCopyUtil.DeepCopy(MainWindow.appData.AppConfig.CustomBGParams);
+            dialog.Close();
+        }
+
+    }
+}

+ 15 - 6
Control/Other/GradientBGDialog.xaml

@@ -20,19 +20,27 @@
                                             Width="600"
                                             Height="400"
                                             Margin="0,-620,0,0">
+
                 <Border Style="{StaticResource BorderBG}">
                     <Grid>
+                        <TextBlock Text="提示: 右键点击可以删除自定义的背景颜色哦" Foreground="Gray" HorizontalAlignment="Center" Margin="0,5,0,0"/>
+
                         <ListBox x:Name="GradientBGs"
-                     ItemsSource="{Binding}"
-                     Background="Transparent"
-                     Margin="20,20,20,50"
-                     BorderThickness="0"
-                     >
+                                 ItemsSource="{Binding}"
+                                 Background="Transparent"
+                                 Margin="20,20,20,50"
+                                 BorderThickness="0"
+                                 >
+                            <ListBox.Resources>
+                                <ContextMenu x:Key="CMDialog" Width="200">
+                                    <MenuItem Header="删除" Click="Delete" Tag="{Binding}"/>
+                                </ContextMenu>
+                            </ListBox.Resources>
                             <ListBox.ItemContainerStyle>
                                 <Style TargetType="ListBoxItem">
+                                    <Setter Property="ContextMenu" Value="{StaticResource CMDialog}"/>
                                     <Setter Property="Margin" Value="10"/>
                                     <Setter Property="Effect" Value="{StaticResource EffectShadow2}"/>
-                                    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                                 </Style>
                             </ListBox.ItemContainerStyle>
                             <ListBox.ItemsPanel>
@@ -40,6 +48,7 @@
                                     <WrapPanel Background="Transparent"/>
                                 </ItemsPanelTemplate>
                             </ListBox.ItemsPanel>
+                            
                             <ListBox.ItemTemplate>
                                 <DataTemplate>
                                     <Border CornerRadius="4" Width="100" Height="100"

+ 42 - 4
Control/Other/GradientBGDialog.xaml.cs

@@ -1,6 +1,8 @@
 using GeekDesk.Util;
 using GeekDesk.ViewModel;
 using GeekDesk.ViewModel.Temp;
+using System;
+using System.Collections.ObjectModel;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
@@ -16,7 +18,13 @@ namespace GeekDesk.Control.Other
 
         public GradientBGDialog()
         {
-            this.DataContext = GradientBGParamList.GradientBGParams;
+            ObservableCollection<GradientBGParam> bgArr = DeepCopyUtil.DeepCopy(GradientBGParamList.GradientBGParams);
+            foreach(var bg in MainWindow.appData.AppConfig.CustomBGParams)
+            {
+                bgArr.Add(bg);
+            }
+
+            this.DataContext = DeepCopyUtil.DeepCopy(bgArr);
             InitializeComponent();
         }
 
@@ -45,8 +53,38 @@ namespace GeekDesk.Control.Other
             }
         }
 
-
-
-
+        private void Delete(object sender, RoutedEventArgs e)
+        {
+            HandyControl.Controls.Growl.Ask("确认删除吗?", isConfirmed =>
+            {
+                if (isConfirmed)
+                {
+                    GradientBGParam bg = (GradientBGParam)(((MenuItem)sender).Tag);
+                    ObservableCollection<GradientBGParam> bgArr = (ObservableCollection<GradientBGParam>)this.DataContext;
+                    bgArr.Remove(bg);
+                    MainWindow.appData.AppConfig.CustomBGParams.Remove(bg);
+                    for (int i = MainWindow.appData.AppConfig.CustomBGParams.Count - 1; i >= 0; i--)
+                    {
+                        var cbg = MainWindow.appData.AppConfig.CustomBGParams[i];
+                        if (cbg.Id == null)
+                        {
+                            if (cbg.Color1.Equals(bg.Color1) && cbg.Color2.Equals(bg.Color2))
+                            {
+                                MainWindow.appData.AppConfig.CustomBGParams.RemoveAt(i);
+                            }
+                        } else
+                        {
+                            if (cbg.Id.Equals(bg.Id))
+                            {
+                                MainWindow.appData.AppConfig.CustomBGParams.RemoveAt(i);
+                            }
+                        }
+                        
+                    }
+                    MainWindow.appData.AppConfig.CustomBGParams = DeepCopyUtil.DeepCopy(MainWindow.appData.AppConfig.CustomBGParams);
+                }
+                return true;
+            }, "ConfigWindowAskGrowl");
+        }
     }
 }

+ 17 - 3
Control/UserControls/Config/ThemeControl.xaml

@@ -16,6 +16,7 @@
         <cvt:BGStyleConvert x:Key="BGStyleConvert"/>
         <cvt:StringAppendConvert x:Key="StringAppendConvert"/>
         <cvt:Visibility2BooleanConverter x:Key="Visibility2BooleanConverter"/>
+        <cvt:TextToColorConverter x:Key="TextToColorConverter"/>
     </UserControl.Resources>
     <Grid>
         <Grid Background="Transparent">
@@ -70,7 +71,8 @@
                             </hc:UniformSpacingPanel>
                             <hc:UniformSpacingPanel Spacing="10" Margin="20,0,0,0" Grid.ColumnSpan="4">
                                 <TextBlock Text="色彩1:" VerticalAlignment="Center" Margin="0,5,0,0"/>
-                                <TextBlock Text="{Binding GradientBGParam.Color1, NotifyOnTargetUpdated=True}"
+                                <Rectangle Width="10" Height="10" Stroke="White"  Margin="0,0,0,5" Fill="{Binding Path=GradientBGParam.Color1, Converter={StaticResource TextToColorConverter}}"/>
+                                <TextBlock Text="{Binding GradientBGParam.Color1, NotifyOnTargetUpdated=True, Mode=OneWay}"
                                            TargetUpdated="Color_TargetUpdated"
                                            Width="65" 
                                            Margin="0,5,0,0"
@@ -83,7 +85,8 @@
                             </hc:UniformSpacingPanel>
                             <hc:UniformSpacingPanel Spacing="10" Margin="20,5,0,0" Grid.ColumnSpan="4">
                                 <TextBlock Text="色彩2:" VerticalAlignment="Center" Margin="0,5,0,0"/>
-                                <TextBlock Text="{Binding GradientBGParam.Color2, NotifyOnTargetUpdated=True}" 
+                                <Rectangle Width="10" Height="10" Stroke="White" Margin="0,0,0,5" Fill="{Binding Path=GradientBGParam.Color2, Converter={StaticResource TextToColorConverter}}"/>
+                                <TextBlock Text="{Binding GradientBGParam.Color2, NotifyOnTargetUpdated=True, Mode=OneWay}" 
                                            TargetUpdated="Color_TargetUpdated"
                                            Width="65" 
                                            Margin="0,5,0,0"
@@ -95,7 +98,7 @@
                                         />
 
                             </hc:UniformSpacingPanel>
-
+                            <hc:UniformSpacingPanel HorizontalAlignment="Center"  Spacing="10" Grid.ColumnSpan="4">
                             <Button Content="系统预设"
                                     Style="{StaticResource MyBtnStyle}"
                                     Margin="0,5,0,0"
@@ -105,6 +108,12 @@
                                     hc:Poptip.Placement="Top"
                                     Click="SysBG_Click"
                                     />
+                            <Button Content="保存当前颜色到系统预设"
+                                    Style="{StaticResource MyBtnStyle}"
+                                    Margin="0,5,0,0"
+                                    Click="NewBGBtn_Click"
+                                    />
+                            </hc:UniformSpacingPanel>
                         </StackPanel>
                     </hc:TransitioningContentControl>
                 </UniformGrid>
@@ -133,6 +142,10 @@
                     <CheckBox Style="{StaticResource MyCheckBoxStyle}"  Content="显示主面板Logo" IsChecked="{Binding TitleLogoVisible, Mode=TwoWay, Converter={StaticResource Visibility2BooleanConverter}}"/>
                 </hc:UniformSpacingPanel>
 
+                <hc:UniformSpacingPanel Spacing="10" Margin="5,10,0,0"  Grid.ColumnSpan="4">
+                    <CheckBox Style="{StaticResource MyCheckBoxStyle}"  Content="显示图标标题" IsChecked="{Binding ShowIconTitle, Mode=TwoWay}"/>
+                </hc:UniformSpacingPanel>
+
 
                 <StackPanel Margin="0,15,0,0">
                     <hc:UniformSpacingPanel Spacing="10" Grid.ColumnSpan="4">
@@ -216,6 +229,7 @@
                 <hc:Divider LineStrokeDashArray="3,3" LineStroke="Black" Grid.ColumnSpan="4"/>
                 <hc:UniformSpacingPanel Spacing="10" Grid.ColumnSpan="4">
                     <TextBlock VerticalAlignment="Center" Text="图标字体颜色:" />
+                    <Rectangle Width="10" Height="10" Stroke="White" Margin="0,0,0,5" Fill="{Binding Path=TextColor, Converter={StaticResource TextToColorConverter}}"/>
                     <TextBlock VerticalAlignment="Center" Text="{Binding TextColor}" Foreground="{Binding TextColor}" Width="100"/>
                     <Button Style="{StaticResource MyBtnStyle}" Content="选择" Margin="0,-10,0,0" Tag="Text"  Click="ColorButton_Click"/>
                 </hc:UniformSpacingPanel>

+ 11 - 1
Control/UserControls/Config/ThemeControl.xaml.cs

@@ -167,6 +167,16 @@ namespace GeekDesk.Control.UserControls.Config
             }
             appConfig.IsShow = null;
         }
-  
+
+        /// <summary>
+        /// 保存当前颜色到系统预设
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void NewBGBtn_Click(object sender, RoutedEventArgs e)
+        {
+            BGNmaeDialog dialog = new BGNmaeDialog();
+            dialog.dialog = HandyControl.Controls.Dialog.Show(dialog, "ConfigWindowDialog");
+        }
     }
 }

+ 10 - 0
Control/UserControls/PannelCard/LeftCardControl.xaml.cs

@@ -463,6 +463,10 @@ namespace GeekDesk.Control.UserControls.PannelCard
                         {
                             int index = MenuListBox.ItemContainerGenerator.IndexFromContainer(lbi);
                             MenuListBox.SelectedIndex = index;
+                            if (appData.AppConfig.IconBatch_NoWrite)
+                            {
+                                appData.AppConfig.IconBatch_NoWrite = false;
+                            }
                         }
                     });
                 });
@@ -487,6 +491,12 @@ namespace GeekDesk.Control.UserControls.PannelCard
             MenuInfo mi = lbi.DataContext as MenuInfo;
             int index = MenuListBox.Items.IndexOf(mi);
             MenuListBox.SelectedIndex = index;
+
+            if (appData.AppConfig.IconBatch_NoWrite)
+            {
+                appData.AppConfig.IconBatch_NoWrite = false;
+                MainWindow.mainWindow.RightCard.IconListBox.SelectionMode = SelectionMode.Extended;
+            }
         }
 
 

+ 18 - 1
Control/UserControls/PannelCard/RightCardControl.xaml

@@ -111,6 +111,10 @@
         <cvt:OpcityConvert x:Key="OpcityConvert"/>
         <cvt:GetWidthByWWConvert x:Key="GetWidthByWWConvert"/>
         <temp:SearchIconList x:Key="SearchIconList"/>
+        <cvt:Boolean2VisibilityConverter x:Key="MyBoolean2VisibilityConverter"/>
+        <cvt:ValueConvert x:Key="ValueConvert"/>
+        <cst:RunTimeStatus x:Key="RunTimeStatus"/>
+        <cst:DictConst x:Key="DictConst"/>
     </UserControl.Resources>
     <!--右侧栏-->
     <Grid>
@@ -148,6 +152,8 @@
                     <MenuItem Header="添加URL项目" Click="AddUrlIcon"/>
                     <MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
                     <MenuItem x:Name="CardLockCM" Header="锁定主面板" Click="LockAppPanel"/>
+                    <MenuItem x:Name="showTitle" Header="隐藏/显示标题" Click="ShowTitle_Click"/>
+                    <MenuItem Header="{Binding AppConfig.IconBatch_NoWrite, Mode=OneWay, Converter={StaticResource ValueConvert}, ConverterParameter={x:Static cst:DictConst.batchMenuHeaderDict}}" Click="BatchHandle" Tag="{Binding}"/>
                 </ContextMenu>
             </hc:Card.ContextMenu>
             <hc:DialogContainer>
@@ -169,6 +175,7 @@
                                      ItemsSource="{Binding AppConfig.SelectedMenuIcons, Mode=OneWay}" 
                                      BorderThickness="0"
                                      Padding="0,10,0,0"
+                                     SelectionChanged="IconListBox_SelectionChanged"
                                      ScrollViewer.CanContentScroll ="True"
                                      VirtualizingPanel.VirtualizationMode="Recycling"  
                                      VirtualizingPanel.IsVirtualizing="True" 
@@ -223,7 +230,12 @@
                                         <MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
                                         <MenuItem Header="资源管理器菜单" Click="SystemContextMenu" Tag="{Binding}"/>
                                         <MenuItem Header="属性" Click="PropertyConfig" Tag="{Binding}"/>
-                                        <MenuItem Header="从列表移除" Click="RemoveIcon" Tag="{Binding}"/>
+                                        <MenuItem Header="从列表移除"
+                                                  Click="RemoveIcon"
+                                                  Tag="{Binding}"/>
+                                        <!--MenuItem Header="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.IconBatch_NoWrite, Mode=OneWay, Converter={StaticResource ValueConvert}, ConverterParameter={x:Static cst:DictConst.batchMenuHeaderDict}}"
+                                                  Click="BatchHandle"
+                                                  Tag="{Binding}"/>-->
                                     </ContextMenu>
                                 </ListBox.Resources>
 
@@ -247,12 +259,16 @@
                                                                  MouseLeftButtonDown="Icon_MouseLeftButtonDown"
                                                                  MouseLeftButtonUp="Icon_MouseLeftButtonUp"
                                                                  >
+                                            <!--<CheckBox IsChecked="{Binding IsChecked_NoWrite}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.IconBatch_NoWrite, Mode=OneWay, Converter={StaticResource Boolean2VisibilityConverter}}" Margin="0,0,0,-20" HorizontalAlignment="Right"/>-->
                                             <!--<StackPanel Background="#00FFFFFF"
                                             MouseEnter="CursorPanel_MouseEnter"
                                             MouseLeave="CursorPanel_MouseLeave"
                                             Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageWidth, Mode=OneWay}">-->
                                             <Image Style="{StaticResource ImageStyle}"  
                                                 RenderOptions.BitmapScalingMode="HighQuality"/>
+                                            <!--Width="{Binding AppConfig.WindowWidth, Mode=OneWay, 
+ Converter={StaticResource GetWidthByWWConvert}, 
+ ConverterParameter={x:Static cst:WidthTypeEnum.RIGHT_CARD_70}}"-->
                                             <TextBlock MaxWidth="80"
                                                     Margin="0,5,0,0"
                                                     MaxHeight="40"
@@ -262,6 +278,7 @@
                                                     TextAlignment="Center" 
                                                     VerticalAlignment="Center" 
                                                     Foreground="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.TextColor}"
+                                                    Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ShowIconTitle, Converter={StaticResource MyBoolean2VisibilityConverter}, ConverterParameter={x:Static Visibility.Collapsed}, Mode=TwoWay}"
                                                     Text="{Binding Name}"/>
                                             <!--</StackPanel>-->
 

+ 58 - 1
Control/UserControls/PannelCard/RightCardControl.xaml.cs

@@ -7,10 +7,12 @@ using GeekDesk.Util;
 using GeekDesk.ViewModel;
 using GeekDesk.ViewModel.Temp;
 using HandyControl.Controls;
+using Newtonsoft.Json.Linq;
 using System;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
 using System.IO;
+using System.Linq;
 using System.Reflection;
 using System.Threading;
 using System.Windows;
@@ -105,6 +107,11 @@ namespace GeekDesk.Control.UserControls.PannelCard
 
         private void Icon_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         {
+            if (appData.AppConfig.IconBatch_NoWrite)
+            {
+                
+                return;
+            }
             if (appData.AppConfig.DoubleOpen)
             {
                 IconClick(sender, e);
@@ -113,6 +120,18 @@ namespace GeekDesk.Control.UserControls.PannelCard
 
         private void Icon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
         {
+            //Console.WriteLine("选中:" + IconListBox.SelectedItems.Count);
+            if (appData.AppConfig.IconBatch_NoWrite)
+            {
+                //查找checkbox更改选中状态
+                Panel p = sender as Panel;
+                var ens = p.Children.OfType<CheckBox>();
+                foreach (CheckBox cb in ens)
+                {
+                    cb.IsChecked = !cb.IsChecked;
+                }
+                return;
+            }
             if (!appData.AppConfig.DoubleOpen)
             {
                 IconClick(sender, e);
@@ -352,9 +371,14 @@ namespace GeekDesk.Control.UserControls.PannelCard
             Panel sp = sender as Panel;
 
             DependencyObject dos = sp.Parent;
+            Image img = null;
 
-            Image img = sp.Children[0] as Image;
+            foreach (var imgBak in sp.Children.OfType<Image>())
+            {
+                img = (Image)imgBak;
 
+            }
+            if (img == null) return;
             double afterHeight = img.Height;
             double afterWidth = img.Width;
 
@@ -683,6 +707,39 @@ namespace GeekDesk.Control.UserControls.PannelCard
             MyPoptip.VerticalOffset = 30;
         }
 
+        /// <summary>
+        /// 控制图标标题显示及隐藏
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void ShowTitle_Click(object sender, RoutedEventArgs e)
+        {
+            appData.AppConfig.ShowIconTitle = !appData.AppConfig.ShowIconTitle;
+        }
 
+        /// <summary>
+        /// 批量操作
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void BatchHandle(object sender, RoutedEventArgs e)
+        {
+            if (!appData.AppConfig.IconBatch_NoWrite)
+            {
+                //开启批量操作时把所有的状态更改为未选中
+               foreach(var ic in IconListBox.Items)
+                {
+                    IconInfo info = ic as IconInfo;
+                    info.IsChecked_NoWrite = false;
+                }
+            }
+            appData.AppConfig.IconBatch_NoWrite = !appData.AppConfig.IconBatch_NoWrite;
+            IconListBox.SelectionMode = SelectionMode.Multiple;
+        }
+
+        private void IconListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            //Console.WriteLine(sender.ToString()); 
+        }
     }
 }

+ 4 - 0
Control/Windows/ConfigWindow.xaml

@@ -21,10 +21,13 @@
            >
 
     <Grid Margin="30">
+
         <Grid.Effect>
             <DropShadowEffect BlurRadius="20" Direction="-90" Color="Gray"
                               RenderingBias="Quality" ShadowDepth="2"/>
         </Grid.Effect>
+        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Panel.ZIndex="9999" hc:Growl.GrowlParent="False" hc:Growl.Token="ConfigWindowAskGrowl" Grid.Column="1" Grid.Row="1"/>
+
         <Grid  hc:Dialog.Token="ConfigWindowDialog">
             <hc:DialogContainer  Margin="10">
                 <Border Style="{StaticResource BorderBG}">
@@ -36,6 +39,7 @@
                             <ColumnDefinition Width="140"/>
                             <ColumnDefinition Width="*"/>
                         </Grid.ColumnDefinitions>
+                        
 
                         <hc:Card Grid.Row="0" Grid.Column="0" Background="Transparent" BorderThickness="0">
 

+ 1 - 0
Control/Windows/PixelColorPickerWindow.xaml

@@ -11,6 +11,7 @@
     MouseLeftButtonDown="Window_MouseLeftButtonDown"
     MouseRightButtonDown="Window_MouseRightButtonDown"
     MouseWheel="Window_MouseWheel"
+    Loaded="Window_Loaded"
     >
     <Window.Resources>
         <Style x:Key="TextKey" TargetType="TextBlock">

+ 79 - 28
Control/Windows/PixelColorPickerWindow.xaml.cs

@@ -11,6 +11,7 @@ using System.Windows.Input;
 using System.Windows.Interop;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
 using Cursors = System.Windows.Input.Cursors;
 using KeyEventArgs = System.Windows.Input.KeyEventArgs;
 using MouseEventArgs = System.Windows.Input.MouseEventArgs;
@@ -22,12 +23,14 @@ namespace GeekDesk.Control.Windows
     /// </summary>
     public partial class PixelColorPickerWindow : IWindowCommon
     {
-        private static int PIXEL_REC_LENGTH = 20;
+        private static int PIXEL_REC_LENGTH = 10;
 
         private static readonly int MIN_LENGTH = 10;
         private static readonly int MAX_LENGTH = 50;
 
-        private static System.Drawing.Bitmap bgBitmap;
+        //private static System.Drawing.Bitmap bgBitmap;
+
+        private static RenderTargetBitmap renderTargetBitmap;
 
         private readonly ColorPicker colorPicker;
 
@@ -58,8 +61,7 @@ namespace GeekDesk.Control.Windows
             int x = 0;
             int y = 0;
 
-            //获取缩放比例
-            double scale = ScreenUtil.GetScreenScalingFactor();
+           
 
             foreach (var screen in screens)
             {
@@ -69,11 +71,10 @@ namespace GeekDesk.Control.Windows
                 x = Math.Min(x, rect.X);
                 y = Math.Min(y, rect.Y);
             }
-            //如果主显示器是最左边和最上边,则显示主显示器的缩放比例,反之则缩放比例不添加缩放比例
-            if (Screen.PrimaryScreen.Bounds.X != x || Screen.PrimaryScreen.Bounds.Y != y)
-            {
-                scale = 1;
-            }
+
+            //获取缩放比例
+            double scale = ScreenUtil.GetScreenScalingFactor();
+        
 
             this.Width = allWidth;
             this.Height = allHeight;
@@ -85,7 +86,7 @@ namespace GeekDesk.Control.Windows
             DesktopBG.Height = this.Height;
             this.Topmost = true;
 
-            bgBitmap = new System.Drawing.Bitmap(
+            System.Drawing.Bitmap bgBitmap = new System.Drawing.Bitmap(
                     (int)(Width * scale),
                     (int)(Height * scale),
                     System.Drawing.Imaging.PixelFormat.Format32bppArgb
@@ -111,10 +112,23 @@ namespace GeekDesk.Control.Windows
             VisualBrush b = (VisualBrush)PixelBG.Fill;
             b.Visual = DesktopBG;
             Mouse.OverrideCursor = Cursors.Cross;
+
+            
+        }
+
+
+        private void Window_Loaded(object sender, RoutedEventArgs e)
+        {
+            // 创建一个RenderTargetBitmap,捕获窗口的内容
+            renderTargetBitmap = new RenderTargetBitmap((int)this.Width, (int)this.Height, 96, 96, PixelFormats.Pbgra32);
+            renderTargetBitmap.Render(this);
+
             SetPixelAbout(null);
         }
 
 
+
+
         public void OnKeyDown(object sender, KeyEventArgs e)
         {
             if (e.Key == Key.Escape)
@@ -128,9 +142,7 @@ namespace GeekDesk.Control.Windows
         {
             Mouse.OverrideCursor = null;
             Point pos = e.MouseDevice.GetPosition(DesktopBG);
-            System.Drawing.Color colorD = bgBitmap.GetPixel((int)pos.X, (int)pos.Y);
-            colorPicker.SelectedBrush = new SolidColorBrush(Color.FromArgb(colorD.A, colorD.R, colorD.G, colorD.B));
-            DeleteObject(bgBitmap.GetHbitmap());
+            colorPicker.SelectedBrush = new SolidColorBrush(GetColorAtPosition(Mouse.GetPosition(this)));
             this.Close();
             ClickColorPickerToggleButton(colorPicker);
         }
@@ -158,19 +170,27 @@ namespace GeekDesk.Control.Windows
         [System.Runtime.InteropServices.DllImport("gdi32.dll")]
         public static extern bool DeleteObject(IntPtr onj);
 
+
+        // Constants for DPI
+        private const int HORZRES = 8;
+        private const int VERTRES = 10;
+        private const int LOGPIXELSX = 88;
+        private const int LOGPIXELSY = 90;
+        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 void SetPixelAbout(MouseEventArgs e)
         {
             VisualBrush b = (VisualBrush)PixelBG.Fill;
 
-            Point pos;
-            if (e == null)
-            {
-                pos = MouseUtil.GetMousePosition();
-            }
-            else
-            {
-                pos = e.MouseDevice.GetPosition(DesktopBG);
-            }
+            Point pos = Mouse.GetPosition(this);
+
+
             Rect viewBox = b.Viewbox;
 
             viewBox.Width = PIXEL_REC_LENGTH;
@@ -182,29 +202,59 @@ namespace GeekDesk.Control.Windows
 
             double x = pos.X + 10;
             double y = pos.Y + 10;
-            if (x + ColorCanvas.Width > SystemParameters.VirtualScreenWidth)
+
+
+
+            //获取缩放比例
+            double scale = ScreenUtil.GetScreenScalingFactor();
+            if (x + ColorCanvas.Width > this.Width / scale)
             {
                 x = pos.X - ColorCanvas.Width - 10;
             }
-            if (y + ColorCanvas.Height > SystemParameters.VirtualScreenHeight)
+            if (y + ColorCanvas.Height > this.Height / scale)
             {
                 y = pos.Y - ColorCanvas.Height - 10;
             }
 
+
             Canvas.SetLeft(ColorCanvas, x);
             Canvas.SetTop(ColorCanvas, y);
 
 
-            System.Drawing.Color dColor = bgBitmap.GetPixel((int)pos.X, (int)pos.Y);
 
-            PixelColor_HTML.Text = "#" + dColor.Name.ToUpper();
+
+            Color wColor = GetColorAtPosition(pos);
+
+            System.Drawing.Color dColor = System.Drawing.Color.FromArgb(wColor.A, wColor.R, wColor.G, wColor.B);
+
+            PixelColor_HTML.Text = "#" + dColor.Name.ToUpper().Substring(2);
             PixelColor_RGB.Text = dColor.R + "," + dColor.G + "," + dColor.B;
-            Pixel_XY.Text = pos.X + "*" + pos.Y;
+            Pixel_XY.Text = (int)pos.X + "*" + (int)pos.Y;
 
             SolidColorBrush scb = (SolidColorBrush)PixelColor.Fill;
-            scb.Color = Color.FromArgb(dColor.A, dColor.R, dColor.G, dColor.B);
+            scb.Color = wColor;
+            //scb.Color = Color.FromArgb(dColor.A, dColor.R, dColor.G, dColor.B);
+        }
+
+        private Color GetColorAtPosition(Point position)
+        {
+            // 使用CroppedBitmap裁剪出鼠标位置的一个像素
+            CroppedBitmap croppedBitmap = new CroppedBitmap(renderTargetBitmap, new Int32Rect((int)position.X, (int)position.Y, 1, 1));
+            // 将像素数据复制到数组中
+            byte[] pixels = new byte[4];
+            croppedBitmap.CopyPixels(pixels, 4, 0);
+            // 如果像素数据有效,则返回颜色
+            //if (pixels.Length == 4)
+            //{
+                
+            //}
+            return Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
+            //return Color.FromArgb(0, 0, 0, 0);
         }
 
+
+
+
         /// <summary>
         /// 滚轮控制缩放区域
         /// </summary>
@@ -238,5 +288,6 @@ namespace GeekDesk.Control.Windows
             //关闭
             this.Close();
         }
+
     }
 }

+ 1 - 1
Control/Windows/ToDoInfoWindow.xaml

@@ -75,7 +75,7 @@
                             <TextBlock Text="指定时间:"  Style="{StaticResource LeftTB}"/>
                             <TextBlock Text="*" Foreground="Red"/>
                         </WrapPanel>
-                        <hc:DateTimePicker x:Name="ExeTime" Text="{Binding ExeTime, Mode=OneWay}" ErrorStr="Error!"  Width="200" Margin="1.6,0,0,0">
+                        <hc:DateTimePicker x:Name="ExeTime" Text="{Binding ExeTime, Mode=OneWay}" Width="200" Margin="1.6,0,0,0">
                             <hc:DateTimePicker.Background>
                                 <SolidColorBrush Color="White" Opacity="0.7"/>
                             </hc:DateTimePicker.Background>

+ 39 - 0
Converts/Boolean2VisibilityConverter.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace GeekDesk.Converts
+{
+    internal class Boolean2VisibilityConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            bool param = false;
+            if (value != null)
+            {
+                param = (bool)value;
+            }
+            if (param)
+            {
+                return Visibility.Visible;
+            } else
+            {
+                return (Visibility)parameter;
+            }
+            
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if ((bool)value)
+            {
+                return Visibility.Visible;
+            }
+            else
+            {
+                return Visibility.Hidden;
+            }
+        }
+    }
+}

+ 30 - 0
Converts/TextToColorConverter.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace GeekDesk.Converts
+{
+    internal class TextToColorConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+            {
+                return null;
+            }
+            string str = value as string;
+            return new SolidColorBrush((Color)ColorConverter.ConvertFromString(str));
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+            {
+                return null;
+            }
+            string str = value as string;
+            return new SolidColorBrush((Color)ColorConverter.ConvertFromString(str));
+        }
+    }
+}

+ 32 - 0
Converts/ValueConvert.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace GeekDesk.Converts
+{
+    internal class ValueConvert : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is bool) {
+                Dictionary<bool, string> dict = (Dictionary<bool, string>)parameter;
+                bool val = (bool)value;
+                return dict[val];
+            }
+            return null;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is bool)
+            {
+                Dictionary<bool, string> dict = (Dictionary<bool, string>)parameter;
+                bool val = (bool)value;
+                return dict[val];
+            }
+            return null;
+        }
+    }
+}

+ 16 - 4
GeekDesk.csproj

@@ -85,8 +85,8 @@
     <Reference Include="Gma.System.MouseKeyHook, Version=5.6.130.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>packages\MouseKeyHook.5.6.0\lib\net40\Gma.System.MouseKeyHook.dll</HintPath>
     </Reference>
-    <Reference Include="HandyControl, Version=3.3.0.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
-      <HintPath>packages\HandyControl.3.3.0\lib\net472\HandyControl.dll</HintPath>
+    <Reference Include="HandyControl, Version=3.5.1.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
+      <HintPath>packages\HandyControl.3.5.1\lib\net472\HandyControl.dll</HintPath>
     </Reference>
     <Reference Include="KeyMouseHook, Version=1.0.6.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>packages\KeyMouseHook.1.0.6\lib\net40\KeyMouseHook.dll</HintPath>
@@ -168,6 +168,7 @@
     <Compile Include="Command\DelegateCommandBase.cs" />
     <Compile Include="Constant\AppHideType.cs" />
     <Compile Include="Constant\Constants.cs" />
+    <Compile Include="Constant\DictConst.cs" />
     <Compile Include="Constant\HotKeyType.cs" />
     <Compile Include="Constant\IconType.cs" />
     <Compile Include="Constant\CommonEnum.cs" />
@@ -193,6 +194,9 @@
     <Compile Include="Control\Other\GradientBGDialog.xaml.cs">
       <DependentUpon>GradientBGDialog.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Control\Other\BGNmaeDialog.xaml.cs">
+      <DependentUpon>BGNmaeDialog.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Control\Other\PasswordDialog.xaml.cs">
       <DependentUpon>PasswordDialog.xaml</DependentUpon>
     </Compile>
@@ -259,6 +263,7 @@
     <Compile Include="Control\Windows\UpdateWindow.xaml.cs">
       <DependentUpon>UpdateWindow.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Converts\ValueConvert.cs" />
     <Compile Include="Converts\CountGreZero2BoolConvert.cs" />
     <Compile Include="Converts\Count2VisibleConvert.cs" />
     <Compile Include="Converts\GetWidthByWWConvert.cs" />
@@ -274,6 +279,8 @@
     <Compile Include="Converts\BGStyleConvert.cs" />
     <Compile Include="Converts\UpdateTypeConvert.cs" />
     <Compile Include="Converts\ReverseBoolConvert.cs" />
+    <Compile Include="Converts\Boolean2VisibilityConverter.cs" />
+    <Compile Include="Converts\TextToColorConverter.cs" />
     <Compile Include="Converts\Visibility2BooleanConverter.cs" />
     <Compile Include="CustomComponent\DraggAnimatedPanel\DraggAnimatedPanel.cs" />
     <Compile Include="CustomComponent\DraggAnimatedPanel\DraggAnimatedPanel.Drag.cs" />
@@ -289,15 +296,16 @@
       <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" />
-    <Compile Include="MyThread\UpdateThread.cs" />
+    <Compile Include="Task\UpdateTask.cs" />
     <Compile Include="Util\AeroGlassHelper.cs" />
     <Compile Include="Util\BGSettingUtil.cs" />
     <Compile Include="Util\BlurGlassUtil.cs" />
     <Compile Include="Util\ColorUtil.cs" />
+    <Compile Include="Util\DeepCopyUtil.cs" />
     <Compile Include="Util\DefaultIcons.cs" />
     <Compile Include="Util\DragAdorner.cs" />
     <Compile Include="Util\FileWatcher.cs" />
@@ -364,6 +372,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="Control\Other\BGNmaeDialog.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="Control\Other\PasswordDialog.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>

+ 14 - 14
MainWindow.xaml.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>
@@ -361,8 +366,8 @@ namespace GeekDesk
             FileWatcher.EnableLinkMenuWatcher(appData);
 
 
-            //更新线程开启  检测更新
-            UpdateThread.Update();
+            //更新任务开启  检测更新
+            UpdateTask.Start();
 
             //建立相对路径
             RelativePathThread.MakeRelativePath();
@@ -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>

+ 1 - 1
MyThread/RelativePathThread.cs

@@ -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)
                 {

+ 15 - 1
Plugins/ShowSeconds/SecondsWindow.xaml.cs

@@ -122,9 +122,23 @@ namespace ShowSeconds
             }
         }
 
+
         private void SecondsHookSetFuc(object sender, MouseEventExtArgs e)
         {
-           
+
+            //IntPtr taskBarWnd = WindowUtil.FindWindow("Shell_TrayWnd", null);
+            //IntPtr tray = WindowUtil.FindWindowEx(taskBarWnd, IntPtr.Zero, "TrayNotifyWnd", null);
+            ////IntPtr trayclock = WindowUtil.FindWindowEx(tray, IntPtr.Zero, "TrayClockWClass", null);
+            //IntPtr trayclock = WindowUtil.GetForegroundWindow();
+            //StringBuilder title = new StringBuilder(256);
+            //WindowUtil.GetWindowText(trayclock, title, title.Capacity);//得到窗口的标题
+            ////Console.WriteLine(title.ToString());
+            //if (title.Equals("通知中心"))
+            //{
+                
+            //}
+
+
             if (e.Button == System.Windows.Forms.MouseButtons.Left)
             {
                 if (ScreenUtil.IsPrimaryFullScreen()) return;

+ 2 - 2
Properties/AssemblyInfo.cs

@@ -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")]

+ 93 - 0
Task/BakTask.cs

@@ -0,0 +1,93 @@
+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 * 2, //60秒 * 60 * 2 2小时触发一次
+                //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()
+                    .Where(f => f.Extension.Equals(".bak", StringComparison.OrdinalIgnoreCase)).ToArray();
+                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);
+            }
+        }
+
+
+    }
+}

+ 0 - 31
Task/ShowSecondTask.cs

@@ -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);
-        }
-    }
-}

+ 29 - 28
MyThread/UpdateThread.cs → Task/UpdateTask.cs

@@ -4,47 +4,47 @@ using GeekDesk.Util;
 using GeekDesk.ViewModel;
 using Newtonsoft.Json.Linq;
 using System;
+using System.Collections.Generic;
 using System.Configuration;
-using System.Threading;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 
-namespace GeekDesk.MyThread
+namespace GeekDesk.Task
 {
-    public class UpdateThread
+    internal class UpdateTask
     {
+
         private static AppConfig appConfig = MainWindow.appData.AppConfig;
-        public static void Update()
+        public static void Start()
         {
-            System.Threading.Thread t = new System.Threading.Thread(new ThreadStart(UpdateApp))
+            System.Timers.Timer timer = new System.Timers.Timer
             {
-                IsBackground = true
+                Enabled = true,
+                Interval = 60 * 1000 * 60 * 12, //60秒 * 60 * 12  12小时触发一次
+                //Interval = 6000,
             };
-            t.Start();
+            timer.Start();
+            timer.Elapsed += Timer_Elapsed; ;
         }
 
-        private static void UpdateApp()
+        private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
         {
             try
             {
-
-                //等待1分钟后再检查更新  有的网络连接过慢
-                int sleepTime = 60 * 1000;
-                if (Constants.DEV)
-                {
-                    sleepTime = 1;
-                }
-
-                System.Threading.Thread.Sleep(sleepTime);
-
-                string updateUrl;
+                string updateUrl = ConfigurationManager.AppSettings["GiteeUpdateUrl"];
                 string nowVersion = ConfigurationManager.AppSettings["Version"];
-                switch (appConfig.UpdateType)
+                if (appConfig != null)
                 {
-                    case UpdateType.GitHub:
-                        updateUrl = ConfigurationManager.AppSettings["GitHubUpdateUrl"];
-                        break;
-                    default:
-                        updateUrl = ConfigurationManager.AppSettings["GiteeUpdateUrl"];
-                        break;
+                    switch (appConfig.UpdateType)
+                    {
+                        case UpdateType.GitHub:
+                            updateUrl = ConfigurationManager.AppSettings["GitHubUpdateUrl"];
+                            break;
+                        default:
+                            updateUrl = ConfigurationManager.AppSettings["GiteeUpdateUrl"];
+                            break;
+                    }
                 }
                 string updateInfo = HttpUtil.Get(updateUrl);
                 if (!StringUtil.IsEmpty(updateInfo))
@@ -63,9 +63,10 @@ namespace GeekDesk.MyThread
                                 HttpUtil.Get(statisticUrl);
                             }
                         }
-                    } catch (Exception){}
+                    }
+                    catch (Exception) { }
+
 
-                   
 
                     string onlineVersion = jo["version"].ToString();
                     if (onlineVersion.CompareTo(nowVersion) > 0)

+ 3 - 3
Update.json

@@ -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": "['鸽了挺久, 我终于又来更新了, 废话不多说, 看下本次更新内容, 没有点star的记得给我star哦^_^', '增加自动多文件备份在根目录下bak文件夹, 数据文件损坏会自动寻找最近的一次备份数据, 基本不用担心数据文件损坏了!!! 备份数据默认为最近7天, 可以通过打开根目录下GeekDesk.exe.config, 找到BakDays修改', '修复多块屏幕下高分屏缩放比例不同导致的鼠标追随bug, 显示时可以正确的追随鼠标位置了', '修复多块屏幕下高分屏缩放比例不同导致的拾色器bug, 可以正常拾色了', '增加自定义纯色背景的保存功能', '修复按照使用次数排序不会自动根据使用次数排序的bug', '另外UI假死的情况, 由于并不是每个用户都出现这个bug, 这次做了尝试性修复, 各位可以看下是否还会出现切换菜单出现不会出现图标的情况', '其它优化', 'PS:最新版的windows11已经可以打开秒数显示了, 各位可以不用开启时钟显秒插件了', '升级前建议备份原目录']",
 	"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"
 }

+ 90 - 35
Util/CommonCode.cs

@@ -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,104 @@ 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()
+                        .Where(f => f.Extension.Equals(".bak", StringComparison.OrdinalIgnoreCase)).ToArray(); ;
+                    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 +160,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("\\")));
@@ -294,11 +349,11 @@ namespace GeekDesk.Util
         /// <summary>
         /// 排序图标
         /// </summary>
-        public static void SortIconList()
+        public static void SortIconList(bool sort = true)
         {
             try
             {
-                if (MainWindow.appData.AppConfig.IconSortType != SortType.CUSTOM)
+                if (MainWindow.appData.AppConfig.IconSortType != SortType.CUSTOM && sort)
                 {
                     ObservableCollection<MenuInfo> menuList = MainWindow.appData.MenuList;
                     //List<IconInfo> list = new List<IconInfo>(menuList[MainWindow.appData.AppConfig.SelectedMenuIndex].IconList);

+ 28 - 0
Util/DeepCopyUtil.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace GeekDesk.Util
+{
+    public static class DeepCopyUtil
+    {
+        // 使用序列化和反序列化实现深度拷贝
+        public static T DeepCopy<T>(T obj)
+        {
+            if (obj == null)
+                throw new ArgumentNullException(nameof(obj));
+
+            using (var memoryStream = new MemoryStream())
+            {
+                var formatter = new BinaryFormatter();
+                formatter.Serialize(memoryStream, obj); // 序列化
+                memoryStream.Seek(0, SeekOrigin.Begin);
+                return (T)formatter.Deserialize(memoryStream); // 反序列化
+            }
+        }
+    }
+}

+ 24 - 4
Util/ProcessUtil.cs

@@ -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
 {
@@ -142,10 +144,10 @@ namespace GeekDesk.Util
                     icon.Count++;
 
                     //隐藏搜索框
-                    if (RunTimeStatus.SEARCH_BOX_SHOW)
-                    {
-                        MainWindow.mainWindow.HidedSearchBox();
-                    }
+                    //if (RunTimeStatus.SEARCH_BOX_SHOW)
+                    //{
+                    //    MainWindow.mainWindow.HidedSearchBox();
+                    //}
                 }
                 catch (Exception e)
                 {
@@ -159,6 +161,9 @@ namespace GeekDesk.Util
                         LogUtil.WriteErrorLog(e, "程序启动失败:path=" + icon.Path + ",type=" + type);
                     }
                 }
+
+                //启动后根据是否开启了使用次数排序判断是否执行一次排序
+                CommonCode.SortIconList(MainWindow.appData.AppConfig.IconSortType == (SortType.COUNT_LOW|SortType.COUNT_UP) ? true : false);
             });
         }
 
@@ -241,6 +246,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
         {

+ 228 - 64
Util/ShowWindowFollowMouse.cs

@@ -1,6 +1,11 @@
 using GeekDesk.Constant;
 using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
 using System.Windows;
+using System.Windows.Forms;
+using System.Windows.Input;
+using static GeekDesk.Util.ShowWindowFollowMouse;
 
 namespace GeekDesk.Util
 {
@@ -18,89 +23,248 @@ 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>
         public static void Show(Window window, MousePosition position, double widthOffset = 0, double heightOffset = 0)
         {
             //获取鼠标位置
-            System.Windows.Point p = MouseUtil.GetMousePosition();
-            double left = SystemParameters.VirtualScreenLeft;
-            double top = SystemParameters.VirtualScreenTop;
-            double width = SystemParameters.VirtualScreenWidth;
-            double height = SystemParameters.WorkArea.Height;
-            double right = width - Math.Abs(left);
-            double bottom = height - Math.Abs(top);
-
-            double afterWidth;
-            double afterHeight;
-
-            switch (position)
-            {
+            System.Drawing.Point p = System.Windows.Forms.Cursor.Position;
 
-                case MousePosition.LEFT_BOTTOM:
-                    afterWidth = 0;
-                    afterHeight = window.Height;
-                    break;
-                case MousePosition.LEFT_TOP:
-                    afterWidth = 0;
-                    afterHeight = 0;
-                    break;
-                case MousePosition.LEFT_CENTER:
-                    afterWidth = 0;
-                    afterHeight = window.Height / 2;
-                    break;
-                case MousePosition.RIGHT_BOTTOM:
-                    afterWidth = window.Width;
-                    afterHeight = window.Height;
-                    break;
-                case MousePosition.RIGHT_TOP:
-                    afterWidth = window.Width;
-                    afterHeight = 0;
-                    break;
-                case MousePosition.RIGHT_CENTER:
-                    afterWidth = window.Width;
-                    afterHeight = window.Height / 2;
-                    break;
-                default:
-                    afterWidth = window.Width / 2;
-                    afterHeight = window.Height / 2;
-                    break;
-            }
+            // 获取鼠标所在的屏幕
+            Screen currentScreen = Screen.FromPoint(p);
+            float dpiX = GetDpi(true);
+            float dpiY = GetDpi(false);
 
-            afterWidth += widthOffset;
-            afterHeight -= heightOffset;
+            p.X = (int)(p.X / dpiX);
+            p.Y = (int)(p.Y / dpiY);
 
-            if (p.X - afterWidth < left)
+            //工作区宽度
+            double screenWidth = currentScreen.WorkingArea.Width / dpiX;
+            //工作区高度
+            double screenHeight = currentScreen.WorkingArea.Height / dpiY;
+            double screenX = currentScreen.WorkingArea.X / dpiX;
+            double screenY = currentScreen.WorkingArea.Y / dpiY;
+
+            //判断是否超出最左边缘
+            if (p.X - window.Width / 2 < screenX)
             {
-                //判断是否在最左边缘
-                window.Left = left - Constants.SHADOW_WIDTH;
-            }
-            else if (p.X + afterWidth > right)
+                //超出最左边缘
+                window.Left = screenX - Constants.SHADOW_WIDTH;
+            } else
             {
-                //判断是否在最右边缘
-                window.Left = right - window.Width + Constants.SHADOW_WIDTH;
+                window.Left = p.X - window.Width / 2 + Constants.SHADOW_WIDTH;
             }
-            else
+
+            //判断是否超出最右边缘
+            if (p.X + window.Width / 2 > screenWidth + screenX)
             {
-                window.Left = p.X - afterWidth;
+                //超出最右边缘
+                window.Left = screenWidth + screenX - window.Width + Constants.SHADOW_WIDTH;
             }
+            
 
-
-            if (p.Y - afterHeight < top)
+            //判断是否超出最上边缘
+            if (p.Y - window.Height / 2 < screenY)
             {
-                //判断是否在最上边缘
-                window.Top = top - Constants.SHADOW_WIDTH;
-            }
-            else if (p.Y + afterHeight > bottom)
+                //超出最上边缘
+                window.Top = screenY - Constants.SHADOW_WIDTH;
+            } else
             {
-                //判断是否在最下边缘
-                window.Top = bottom - window.Height + Constants.SHADOW_WIDTH;
+                window.Top = p.Y - window.Height / 2 + Constants.SHADOW_WIDTH;
             }
-            else
+
+            //判断是否超出最下边缘
+            if (p.Y + window.Height / 2 > screenHeight + screenY)
             {
-                window.Top = p.Y - afterHeight;
+                //超出最下边缘
+                window.Top = screenHeight + screenY - window.Height + Constants.SHADOW_WIDTH;
             }
+            
+
+
+
+
+
+            //// 显示屏幕信息
+            //Console.WriteLine("鼠标当前所在屏幕的信息:");
+            //Console.WriteLine($"屏幕设备名称: {currentScreen.DeviceName}");
+            //Console.WriteLine($"屏幕分辨率: {currentScreen.Bounds.Width}x{currentScreen.Bounds.Height}");
+            //Console.WriteLine($"屏幕工作区: {currentScreen.WorkingArea}");
+            //Console.WriteLine($"主屏幕: {currentScreen.Primary}");
+
+            //Console.WriteLine(p.X + "=" + p.Y);
+            //float dpiX = GetDpi(true);
+            //float dpiY = GetDpi(false);
+            //p.X = (int)(p.X / dpiX);
+            //p.Y = (int)(p.Y / dpiY);
+            //Console.WriteLine(p.X + "=" + p.Y);
+            //double left = SystemParameters.VirtualScreenLeft;
+            //double top = SystemParameters.VirtualScreenTop;
+            //double width = SystemParameters.VirtualScreenWidth;
+            //double height = SystemParameters.WorkArea.Bottom;
+
+            //Console.WriteLine("VirtualScreenTop:" + SystemParameters.VirtualScreenTop);
+            //Console.WriteLine("VirtualScreenLeft:" + SystemParameters.VirtualScreenLeft);
+            //Console.WriteLine("VirtualScreenWidth:" + SystemParameters.VirtualScreenWidth);
+            //Console.WriteLine("VirtualScreenHeight:" + SystemParameters.VirtualScreenHeight);
+            //Console.WriteLine("WorkArea.Bottom:" + SystemParameters.WorkArea.Bottom);
+            //Console.WriteLine(" window.Height:" + window.Height);
+            //double right = width - Math.Abs(left);
+            //double bottom = height - Math.Abs(top);
+
+            //double afterWidth;
+            //double afterHeight;
+
+            //switch (position)
+            //{
+
+            //    case MousePosition.LEFT_BOTTOM:
+            //        afterWidth = 0;
+            //        afterHeight = window.Height;
+            //        break;
+            //    case MousePosition.LEFT_TOP:
+            //        afterWidth = 0;
+            //        afterHeight = 0;
+            //        break;
+            //    case MousePosition.LEFT_CENTER:
+            //        afterWidth = 0;
+            //        afterHeight = window.Height / 2;
+            //        break;
+            //    case MousePosition.RIGHT_BOTTOM:
+            //        afterWidth = window.Width;
+            //        afterHeight = window.Height;
+            //        break;
+            //    case MousePosition.RIGHT_TOP:
+            //        afterWidth = window.Width;
+            //        afterHeight = 0;
+            //        break;
+            //    case MousePosition.RIGHT_CENTER:
+            //        afterWidth = window.Width;
+            //        afterHeight = window.Height / 2;
+            //        break;
+            //    default:
+            //        afterWidth = window.Width / 2;
+            //        afterHeight = window.Height / 2;
+            //        break;
+            //}
+
+            //afterWidth += widthOffset;
+            //afterHeight -= heightOffset;
+
+            //if (p.X - afterWidth < left)
+            //{
+            //    //判断是否在最左边缘
+            //    window.Left = left - Constants.SHADOW_WIDTH;
+            //}
+            //else if (p.X + afterWidth > right)
+            //{
+            //    //判断是否在最右边缘
+            //    window.Left = right - window.Width + Constants.SHADOW_WIDTH;
+            //}
+            //else
+            //{
+            //    window.Left = p.X - afterWidth;
+            //}
+
+
+            //if (p.Y - afterHeight < top)
+            //{
+            //    //判断是否在最上边缘
+            //    window.Top = top - Constants.SHADOW_WIDTH;
+            //}
+            //else if (p.Y + afterHeight > bottom)
+            //{
+            //    Console.WriteLine("p.Y:" + p.Y);
+            //    Console.WriteLine("afterHeight:" + afterHeight);
+            //    Console.WriteLine("bottom:" + bottom);
+            //    //判断是否在最下边缘
+            //    window.Top = bottom - window.Height + Constants.SHADOW_WIDTH;
+            //}
+            //else
+            //{
+            //    window.Top = p.Y - afterHeight;
+            //}
         }
 
     }

+ 180 - 11
Util/WindowUtil.cs

@@ -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,31 +44,92 @@ namespace GeekDesk.Util
             SWP_NOSENDCHANGING = 0x0400
         }
 
+        [DllImport("user32.dll")]
+        public static extern IntPtr WindowFromPoint(System.Drawing.Point p);
+
         //取得前台窗口句柄函数 
         [DllImport("user32.dll")]
-        private static extern IntPtr GetForegroundWindow();
+        public static extern IntPtr GetForegroundWindow();
         //取得桌面窗口句柄函数 
         [DllImport("user32.dll")]
-        private static extern IntPtr GetDesktopWindow();
+        public static extern IntPtr GetDesktopWindow();
         [DllImport("user32.dll", CharSet = CharSet.Auto)]
-        private static extern IntPtr FindWindow(string className, string windowName);
+        public static extern IntPtr FindWindow(string className, string windowName);
+
+        [DllImport("user32.dll")]
+        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string windowName);
+
         [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
-        private static extern IntPtr GetWindow(HandleRef hWnd, int nCmd);
+        public static extern IntPtr GetWindow(HandleRef hWnd, int nCmd);
         [DllImport("user32.dll")]
-        private static extern IntPtr SetParent(IntPtr child, IntPtr parent);
+        public static extern IntPtr SetParent(IntPtr child, IntPtr parent);
         [DllImport("user32.dll", EntryPoint = "GetDCEx", CharSet = CharSet.Auto, ExactSpelling = true)]
-        private static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, int flags);
+        public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, int flags);
         [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
-        private static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy, int flags);
+        public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy, int flags);
         [DllImport("user32.dll")]
-        private static extern int ReleaseDC(IntPtr window, IntPtr handle);
+        public static extern int ReleaseDC(IntPtr window, IntPtr handle);
         [DllImport("user32.dll")]
-        static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+        public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
 
         [DllImport("user32.dll")]
-        private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
+        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")]
-        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+        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;
@@ -78,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)
         {

+ 67 - 6
ViewModel/AppConfig.cs

@@ -58,7 +58,7 @@ namespace GeekDesk.ViewModel
         private string customIconUrl; //自定义图标url
         private string customIconJsonUrl;  //自定义图标json信息url
 
-        private bool blurEffect = false; //毛玻璃效果 默认否
+        private bool blurEffect = true; //毛玻璃效果 默认是
         private double blurValue;
 
         private UpdateType updateType = UpdateType.Gitee; //更新源 默认gitee源
@@ -74,7 +74,7 @@ namespace GeekDesk.ViewModel
         private int imageWidth = (int)CommonEnum.IMAGE_WIDTH; //图片宽度
         private int imageHeight = (int)CommonEnum.IMAGE_HEIGHT; //图片高度
 
-        private bool mouseMiddleShow = false;  //鼠标中键呼出 默认不启用
+        private bool mouseMiddleShow = true;  //鼠标中键呼出 默认启用
 
         private bool showBarIcon = true; //显示托盘图标  默认显示
 
@@ -105,10 +105,60 @@ namespace GeekDesk.ViewModel
 
         private bool? secondsWindow; //秒数窗口 默认打开
 
-        private bool? enableEveryThing;
+        private bool? enableEveryThing; //开启everything
 
-        private bool? alwaysTopmost;
+        private bool? alwaysTopmost; //是否置顶
 
+        private bool? showIconTitle = true; //是否显示iconTitle
+
+        private bool iconBatch = false; //批量操作图标状态
+
+        private ObservableCollection<GradientBGParam> customBGParams; //自定义纯色背景
+
+
+        public ObservableCollection<GradientBGParam> CustomBGParams
+        {
+            get
+            {
+                if (customBGParams == null)
+                {
+                    customBGParams = new ObservableCollection<GradientBGParam>();
+                }
+                return customBGParams;
+            }
+            set
+            {
+                customBGParams = value;
+                OnPropertyChanged("CustomBGParams");
+            }
+        }
+
+        public bool IconBatch_NoWrite
+        {
+            get
+            {
+                return iconBatch;
+            }
+            set
+            {
+                iconBatch = value;
+                OnPropertyChanged("IconBatch_NoWrite");
+            }
+        }
+
+        public bool? ShowIconTitle
+        {
+            get
+            {
+                if (showIconTitle == null) showIconTitle = true;
+                return showIconTitle;
+            }
+            set
+            {
+                showIconTitle = value;
+                OnPropertyChanged("ShowIconTitle");
+            }
+        }
 
         public bool? AlwaysTopmost
         {
@@ -290,7 +340,7 @@ namespace GeekDesk.ViewModel
             {
                 if (gradientBGParam == null)
                 {
-                    gradientBGParam = GradientBGParamList.GradientBGParams[0];
+                    gradientBGParam = DeepCopyUtil.DeepCopy(GradientBGParamList.GradientBGParams[0]);
                 }
                 return gradientBGParam;
             }
@@ -674,6 +724,14 @@ namespace GeekDesk.ViewModel
         {
             get
             {
+                if (blurEffect)
+                {
+                    BlurValue = 100;
+                }
+                else
+                {
+                    BlurValue = 0;
+                }
                 return blurValue;
             }
             set
@@ -1019,7 +1077,10 @@ namespace GeekDesk.ViewModel
         private void OnPropertyChanged(string propertyName)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
-            CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
+            if (propertyName != null && !propertyName.Contains("NoWrite"))
+            {
+                CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
+            }
         }
 
         #endregion

+ 16 - 2
ViewModel/GradientBGParam.cs

@@ -8,6 +8,8 @@ namespace GeekDesk.ViewModel
     [Serializable]
     public class GradientBGParam : INotifyPropertyChanged
     {
+        private string id;
+
         private string color1;
 
         private string color2;
@@ -16,14 +18,26 @@ namespace GeekDesk.ViewModel
 
         public GradientBGParam() { }
 
-        public GradientBGParam(string name, string color1, string color2)
+        public GradientBGParam(string id, string name, string color1, string color2)
         {
+            this.id = id;
             this.name = name;
             this.color1 = color1;
             this.color2 = color2;
         }
 
-
+        public string Id
+        {
+            get
+            {
+                return id;
+            }
+            set
+            {
+                id = value;
+                OnPropertyChanged("Id");
+            }
+        }
 
         public string Color1
         {

+ 16 - 1
ViewModel/IconInfo.cs

@@ -28,6 +28,21 @@ namespace GeekDesk.ViewModel
 
         private IconType iconType = IconType.OTHER;
 
+        private bool isChecked = false; //是否选中
+
+
+        public bool IsChecked_NoWrite
+        {
+            get
+            {
+                return isChecked;
+            }
+            set
+            {
+                isChecked = value;
+                OnPropertyChanged("IsChecked_NoWrite");
+            }
+        }
 
         public string RelativePath_NoWrite
         {
@@ -347,7 +362,7 @@ namespace GeekDesk.ViewModel
         private void OnPropertyChanged(string propertyName)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
-            if (propertyName!=null && propertyName.Contains("NoWrite"))
+            if (propertyName!=null && !propertyName.Contains("NoWrite"))
             {
                 CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
             }

+ 3 - 3
ViewModel/Temp/GradientBGParamList.cs

@@ -13,9 +13,9 @@ namespace GeekDesk.ViewModel.Temp
             //gradientBGParams = (ObservableCollection<GradientBGParam>)ConfigurationManager.GetSection("SystemBGs")
             gradientBGParams = new ObservableCollection<GradientBGParam>
             {
-                new GradientBGParam("魅惑妖术", "#EE9CA7", "#FFDDE1"),
-                new GradientBGParam ("森林之友", "#EBF7E3", "#A8E4C0"),
-                new GradientBGParam("完美谢幕", "#D76D77", "#FFAF7B")
+                new GradientBGParam("1E7BFD15-92CE-1332-F583-94E1C39729FF", "魅惑妖术", "#EE9CA7", "#FFDDE1"),
+                new GradientBGParam ("F54F9B03-8F50-8FFB-54C6-1BCCA03BF0F8", "森林之友", "#EBF7E3", "#A8E4C0"),
+                new GradientBGParam("36C16080-0516-0DAC-FE09-721CC6AB57A4", "完美谢幕", "#D76D77", "#FFAF7B")
             };
         }
 

+ 1 - 1
packages.config

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="CommonServiceLocator" version="2.0.6" targetFramework="net452" requireReinstallation="true" />
-  <package id="HandyControl" version="3.3.0" targetFramework="net472" />
+  <package id="HandyControl" version="3.5.1" targetFramework="net472" />
   <package id="KeyMouseHook" version="1.0.6" targetFramework="net472" developmentDependency="true" />
   <package id="Microsoft.Build.Tasks.Git" version="1.0.0" targetFramework="net472" developmentDependency="true" />
   <package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net472" />