From fa276183e83dcab07d2714034985555127435087 Mon Sep 17 00:00:00 2001 From: kriastans Date: Sun, 8 Sep 2024 21:42:18 +0800 Subject: [PATCH] [update] SettingsV2 --- InkCanvasForClass/App.xaml.cs | 7 +- .../Helpers/ConfigurationHelper.cs | 133 ++++++++++ InkCanvasForClass/InkCanvasForClass.csproj | 4 + .../InkCanvasForClass.csproj.user | 12 + InkCanvasForClass/MainWindow.xaml.cs | 4 + .../Popups/FloatingToolBarV2.xaml.cs | 1 + .../Resources/ICCConfiguration.cs | 61 +++++ InkCanvasForClass/Settings.icc.config.txt | 68 ----- .../SpecialLuckyRandomConfig.icc.config.txt | 19 -- .../Windows/SettingsViews/AboutPanel.xaml | 194 ++++++++++++++ .../Windows/SettingsViews/AboutPanel.xaml.cs | 243 ++++++++++++++++++ .../SettingsViews/SettingsBaseView.xaml | 24 ++ .../SettingsViews/SettingsBaseView.xaml.cs | 108 ++++++++ InkCanvasForClass/Windows/SettingsWindow.xaml | 136 +--------- .../Windows/SettingsWindow.xaml.cs | 133 +--------- InkCanvasForClass/icc.toml | 39 +++ 16 files changed, 838 insertions(+), 348 deletions(-) create mode 100644 InkCanvasForClass/Helpers/ConfigurationHelper.cs create mode 100644 InkCanvasForClass/Resources/ICCConfiguration.cs delete mode 100644 InkCanvasForClass/Settings.icc.config.txt delete mode 100644 InkCanvasForClass/SpecialLuckyRandomConfig.icc.config.txt create mode 100644 InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml create mode 100644 InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml.cs create mode 100644 InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml create mode 100644 InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml.cs create mode 100644 InkCanvasForClass/icc.toml diff --git a/InkCanvasForClass/App.xaml.cs b/InkCanvasForClass/App.xaml.cs index e097783..9989103 100644 --- a/InkCanvasForClass/App.xaml.cs +++ b/InkCanvasForClass/App.xaml.cs @@ -16,6 +16,8 @@ using System.Runtime.InteropServices; using System.Security.Principal; using Windows.Data.Xml.Dom; using Windows.UI.Notifications; +using Ink_Canvas.Properties; +using Ink_Canvas.Resources.ICCConfiguration; namespace Ink_Canvas { @@ -34,6 +36,7 @@ namespace Ink_Canvas { public static string[] StartArgs = null; public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\"; + public static ICCConfiguration SettingsV2 = new ICCConfiguration(); public App() { this.Startup += new StartupEventHandler(App_Startup); @@ -62,6 +65,8 @@ namespace Ink_Canvas { RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; + SettingsV2 = ConfigurationHelper.ReadConfiguration(); + LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString())); bool ret; @@ -113,8 +118,6 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error); } - - mainWin = new MainWindow(); if (isUsingWindowChrome && DwmCompositionHelper.DwmIsCompositionEnabled()) { diff --git a/InkCanvasForClass/Helpers/ConfigurationHelper.cs b/InkCanvasForClass/Helpers/ConfigurationHelper.cs new file mode 100644 index 0000000..5702315 --- /dev/null +++ b/InkCanvasForClass/Helpers/ConfigurationHelper.cs @@ -0,0 +1,133 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; +using Ink_Canvas.Resources.ICCConfiguration; +using Tomlyn; +using Tomlyn.Model; + +namespace Ink_Canvas.Helpers { + public static class ConfigurationHelper { + public static ICCConfiguration ReadConfiguration() { + try { + if (File.Exists(App.RootPath + "icc.toml")) { + try { + string text = File.ReadAllText(App.RootPath + "icc.toml"); + var tomlTable = Toml.ToModel(text); + var conf = new ICCConfiguration(); + + // FloatingBar + var fb = tomlTable["FloatingBar"] as TomlTable; + if (fb != null) { + if (fb["SemiTransparent"] is bool) conf.FloatingBar.SemiTransparent = (bool)fb["SemiTransparent"]; + if (fb["NearSnap"] is bool) conf.FloatingBar.NearSnap = (bool)fb["NearSnap"]; + InitialPositionTypes _InitialPositionType; + ElementCornerRadiusTypes _ElementCornerRadiusType; + if (fb["InitialPosition"] is TomlArray) { + var arr = ((TomlArray)fb["InitialPosition"]); + conf.FloatingBar.InitialPosition = InitialPositionTypes.Custom; + if ((arr[0] is double || arr[0] is long) && + (arr[1] is double || arr[1] is long)) + conf.FloatingBar.InitialPositionPoint = new Point(Math.Min(Math.Max(0,Convert.ToDouble(arr[0])),65535), + Math.Min(Math.Max(0,Convert.ToDouble(arr[1])),65535)); + } else if (fb["InitialPosition"] is string && + Enum.TryParse((string)fb["InitialPosition"], + out _InitialPositionType)) { + conf.FloatingBar.InitialPosition = _InitialPositionType; + } + if (fb["ElementCornerRadius"] is double || fb["ElementCornerRadius"] is long) { + conf.FloatingBar.ElementCornerRadiusType = ElementCornerRadiusTypes.Custom; + conf.FloatingBar.ElementCornerRadiusValue = Math.Min(Math.Max(0, Convert.ToDouble(fb["ElementCornerRadius"])),24); + } else if (fb["ElementCornerRadius"] is string && + Enum.TryParse((string)fb["ElementCornerRadius"], + out _ElementCornerRadiusType)) { + conf.FloatingBar.ElementCornerRadiusType = _ElementCornerRadiusType; + } + if (fb["ParallaxEffect"] is bool) conf.FloatingBar.ParallaxEffect = (bool)fb["ParallaxEffect"]; + if (fb["MiniMode"] is bool) conf.FloatingBar.MiniMode = (bool)fb["MiniMode"]; + if (fb["ClearButtonColor"] is TomlArray) { + var arr = (TomlArray)fb["ClearButtonColor"]; + conf.FloatingBar.ClearButtonColor = Color.FromRgb(Convert.ToByte(arr[0]), Convert.ToByte(arr[1]), Convert.ToByte(arr[2])); + } + if (fb["ClearButtonPressColor"] is TomlArray) { + var arr = (TomlArray)fb["ClearButtonPressColor"]; + conf.FloatingBar.ClearButtonPressColor = Color.FromRgb(Convert.ToByte(arr[0]), Convert.ToByte(arr[1]), Convert.ToByte(arr[2])); + } + if (fb["ToolButtonSelectedBgColor"] is TomlArray) { + var arr = (TomlArray)fb["ToolButtonSelectedBgColor"]; + conf.FloatingBar.ToolButtonSelectedBgColor = Color.FromRgb(Convert.ToByte(arr[0]), Convert.ToByte(arr[1]), Convert.ToByte(arr[2])); + } + if (fb["MovingLimitationNoSnap"] is long || fb["MovingLimitationNoSnap"] is double) + conf.FloatingBar.MovingLimitationNoSnap = Math.Min(Math.Max(0, Convert.ToDouble(fb["MovingLimitationNoSnap"])),32); + if (fb["MovingLimitationSnapped"] is long || fb["MovingLimitationSnapped"] is double) + conf.FloatingBar.MovingLimitationSnapped = Math.Min(Math.Max(0, Convert.ToDouble(fb["MovingLimitationSnapped"])),32); + if (fb["NearSnapAreaSize"] is TomlTable) { + var _tb = fb["NearSnapAreaSize"] as TomlTable; + if (_tb["TopLeft"] is TomlArray) { + var _arr = _tb["TopLeft"] as TomlArray; + conf.FloatingBar.NearSnapAreaSize.TopLeft = new []{ + Math.Min(Math.Max(0,Convert.ToDouble(_arr[0])),64), Math.Min(Math.Max(0,Convert.ToDouble(_arr[1])),64) + }; + } + if (_tb["TopRight"] is TomlArray) { + var _arr = _tb["TopRight"] as TomlArray; + conf.FloatingBar.NearSnapAreaSize.TopRight = new []{ + Math.Min(Math.Max(0,Convert.ToDouble(_arr[0])),64), Math.Min(Math.Max(0,Convert.ToDouble(_arr[1])),64) + }; + } + if (_tb["BottomLeft"] is TomlArray) { + var _arr = _tb["BottomLeft"] as TomlArray; + conf.FloatingBar.NearSnapAreaSize.BottomLeft = new []{ + Math.Min(Math.Max(0,Convert.ToDouble(_arr[0])),64), Math.Min(Math.Max(0,Convert.ToDouble(_arr[1])),64) + }; + } + if (_tb["BottomRight"] is TomlArray) { + var _arr = _tb["BottomRight"] as TomlArray; + conf.FloatingBar.NearSnapAreaSize.BottomRight = new []{ + Math.Min(Math.Max(0,Convert.ToDouble(_arr[0])),64), Math.Min(Math.Max(0,Convert.ToDouble(_arr[1])),64) + }; + } + if (_tb["TopCenter"] is long || _tb["TopCenter"] is double) + conf.FloatingBar.NearSnapAreaSize.TopCenter = Math.Min(Math.Max(0, Convert.ToDouble(_tb["TopCenter"])), 64); + if (_tb["BottomCenter"] is long || _tb["BottomCenter"] is double) + conf.FloatingBar.NearSnapAreaSize.BottomCenter = Math.Min(Math.Max(0, Convert.ToDouble(_tb["BottomCenter"])), 64); + } + if (fb["ToolBarItems"] is TomlTable) { + var _tb = fb["ToolBarItems"] as TomlTable; + if (_tb["CursorMode"] is TomlArray) { + conf.FloatingBar.ToolBarItemsInCursorMode = + Array.ConvertAll(((TomlArray)_tb["CursorMode"]).ToArray(),p=>p.ToString()); + } + if (_tb["MiniMode"] is TomlArray) { + conf.FloatingBar.ToolBarItemsInMiniMode = + Array.ConvertAll(((TomlArray)_tb["MiniMode"]).ToArray(),p=>p.ToString()); + } + if (_tb["AnnotationMode"] is TomlArray) { + conf.FloatingBar.ToolBarItemsInAnnotationMode = + Array.ConvertAll(((TomlArray)_tb["AnnotationMode"]).ToArray(),p=>p.ToString()); + } + } + } + + return conf; + } + catch { + return new ICCConfiguration(); + } + } else { + return new ICCConfiguration(); + } + } + catch (Exception ex) { + LogHelper.WriteLogToFile(ex.ToString(), LogHelper.LogType.Error); + return new ICCConfiguration(); + } + } + } +} diff --git a/InkCanvasForClass/InkCanvasForClass.csproj b/InkCanvasForClass/InkCanvasForClass.csproj index 6e9f395..21faee2 100644 --- a/InkCanvasForClass/InkCanvasForClass.csproj +++ b/InkCanvasForClass/InkCanvasForClass.csproj @@ -184,6 +184,7 @@ + @@ -630,6 +631,9 @@ + + Always + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/InkCanvasForClass/InkCanvasForClass.csproj.user b/InkCanvasForClass/InkCanvasForClass.csproj.user index 8543433..f69f544 100644 --- a/InkCanvasForClass/InkCanvasForClass.csproj.user +++ b/InkCanvasForClass/InkCanvasForClass.csproj.user @@ -29,6 +29,12 @@ Code + + Code + + + Code + Code @@ -64,6 +70,12 @@ Designer + + Designer + + + Designer + Designer diff --git a/InkCanvasForClass/MainWindow.xaml.cs b/InkCanvasForClass/MainWindow.xaml.cs index 5635407..4339250 100644 --- a/InkCanvasForClass/MainWindow.xaml.cs +++ b/InkCanvasForClass/MainWindow.xaml.cs @@ -23,6 +23,7 @@ using Ink_Canvas.Popups; using iNKORE.UI.WPF.Modern.Controls; using System.Windows.Forms; using System.Windows.Input; +using Ink_Canvas.Resources.ICCConfiguration; using Vanara.PInvoke; using Application = System.Windows.Application; using Button = System.Windows.Controls.Button; @@ -178,6 +179,7 @@ namespace Ink_Canvas { #region Definitions and Loading public static Settings Settings = new Settings(); + public static ICCConfiguration SettingsV2 = new ICCConfiguration(); public static string settingsFileName = "Settings.json"; public bool isLoaded = false; @@ -225,6 +227,8 @@ namespace Ink_Canvas { //TextBlockVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString(); LogHelper.WriteLogToFile("Ink Canvas Loaded", LogHelper.LogType.Event); + var app = Application.Current; + isLoaded = true; FloatingToolBarV2 = new FloatingToolBarV2(); diff --git a/InkCanvasForClass/Popups/FloatingToolBarV2.xaml.cs b/InkCanvasForClass/Popups/FloatingToolBarV2.xaml.cs index e4fd327..6652c9c 100644 --- a/InkCanvasForClass/Popups/FloatingToolBarV2.xaml.cs +++ b/InkCanvasForClass/Popups/FloatingToolBarV2.xaml.cs @@ -83,6 +83,7 @@ namespace Ink_Canvas //var clonedDrawing = (FindResource("CursorIcon") as DrawingImage).Clone(); //((clonedDrawing.Drawing as DrawingGroup).Children[0] as // GeometryDrawing).Brush = new SolidColorBrush(Colors.Black); + ToolbarItems.Add(new FloatingBarItem() { Name = "Cursor", IconSource = FindResource("CursorIcon") as DrawingImage, diff --git a/InkCanvasForClass/Resources/ICCConfiguration.cs b/InkCanvasForClass/Resources/ICCConfiguration.cs new file mode 100644 index 0000000..5a866e0 --- /dev/null +++ b/InkCanvasForClass/Resources/ICCConfiguration.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; + +namespace Ink_Canvas.Resources.ICCConfiguration { + public enum InitialPositionTypes { + TopLeft, TopRight, BottomLeft, BottomRight, TopCenter, BottomCenter, Custom + } + public enum ElementCornerRadiusTypes { + SuperEllipse, Circle, Custom, None + } + public class NearSnapAreaSize { + public double[] TopLeft { get; set; } = {24,24}; + public double[] TopRight { get; set; } = {24,24}; + public double[] BottomLeft { get; set; } = {24,24}; + public double[] BottomRight { get; set; } = {24,24}; + public double TopCenter { get; set; } = 24; + public double BottomCenter { get; set; } = 24; + } + public class ICCFloatingBarConfiguration { + public bool SemiTransparent { get; set; } = false; + public bool NearSnap { get; set; } = true; + public InitialPositionTypes InitialPosition { get; set; } = InitialPositionTypes.BottomCenter; + public Point InitialPositionPoint { get; set; } = new Point(0, 0); + public double ElementCornerRadiusValue = 0; + public ElementCornerRadiusTypes ElementCornerRadiusType { get; set; } = ElementCornerRadiusTypes.SuperEllipse; + + public bool ParallaxEffect { get; set; } = true; + public bool MiniMode { get; set; } = false; + public Color ClearButtonColor { get; set; } = Color.FromRgb(224, 27, 36); + public Color ClearButtonPressColor { get; set; } = Color.FromRgb(254, 226, 226); + public Color ToolButtonSelectedBgColor { get; set; } = Color.FromRgb(37, 99, 235); + public double MovingLimitationNoSnap { get; set; } = 12; + public double MovingLimitationSnapped { get; set; } = 24; + + public NearSnapAreaSize NearSnapAreaSize { get; set; } = new NearSnapAreaSize() { + TopLeft = new double[] { 24, 24 }, + TopRight = new double[] { 24, 24 }, + BottomLeft = new double[] { 24, 24 }, + BottomRight = new double[] { 24, 24 }, + }; + + public string[] ToolBarItemsInCursorMode { get; set; } = new string[] { + "Cursor", "Pen", "Clear", "Separator", "Whiteboard", "Gesture", "Menu", "Fold" + }; + public string[] ToolBarItemsInMiniMode { get; set; } = new string[] { + "Cursor", "Pen", "Clear" + }; + public string[] ToolBarItemsInAnnotationMode { get; set; } = new string[] { + "Cursor", "Pen", "Clear", "Separator", "Eraser", "ShapeDrawing", "Select", "Separator", "Undo", "Redo", "Separator", "Whiteboard", "Gesture", "Menu", "Fold" + }; + } + + public class ICCConfiguration { + public ICCFloatingBarConfiguration FloatingBar { get; set; } = new ICCFloatingBarConfiguration(); + } +} diff --git a/InkCanvasForClass/Settings.icc.config.txt b/InkCanvasForClass/Settings.icc.config.txt deleted file mode 100644 index 7d8032c..0000000 --- a/InkCanvasForClass/Settings.icc.config.txt +++ /dev/null @@ -1,68 +0,0 @@ -# icc 的配置文件 -# ================================================ -# 语法说明: -# 1. 井号后面是注释内容,不会被解释器识别 -# 2. 单个项目使用 Key=Value 的格式 -# 3. 有子项目的使用 Key:(subKey1=value1,subKey2=value2) 的格式 -# 4. 有子项目的且项目本身可以设置值的使用 Key=Value:(subKey1=value1,subKey2=value2) 的格式 -# 5. 开为 1 ,关为 0,字符串不需要刻意加引号,自动识别,也可以加上双引号。 -# ================================================ - -{icc.config="Default"} - -[config="appearance"] -floatingBar:(label=0,icons=1111111111,eraser=0,onlyEraser=0,logo=0,scale=1.00,alpha=1.00,alphaPpt=1.00) -whiteBoard:(scale=0.80,time=1,cs=0;csSource=0) -quickPanel=0:(icon=0) -trayIcon=0 - -[config="startup"] -run=0:(fold=0,hide=0,admin=0,winChrome=0) - -[config="canvas"] -canvas:(cursor=0,eraser=2,hideWExit=0,clearTm=0) -whiteBoard:(color=0,pattern=0,defClr=0,defPtrn=0,inkClr=0) -select:(mode=0,stylusTip=1,fully=0,clickLock=0) - -[config="gesture"] -2fingerMove=0 -2fingerRotateInk=0 -oldTouchGesture=1:(spScreen=0,multiple=1,boundsW=5;20,threshold=2.5;2.5,eraserS=0.8;0.8,quadIr=0) -mouseGesture=1:(right=1,wheel=0,fWheel=0) -winInk:(eraser=0,barrel=0) - -[config="ink-recognition"] -inkRecognition=1:(rectSP=1,triSP=1,asShape=1,triRecog=1,rectRecog=1,ellipseRecog=1) - -[config="powerpoint"] -powerpoint=1 -wpsOffice=0 -slideShowToolBtn=1:(lb=1,rb=1,ls=1,rs=1,bConf=100,sConf=110,clickable=0,autoInk=0,2finger=1,autoSnap=0,autosave=1,memLastIndex=0,hiddenSlide=1,autoplayN=0) - -[config="experimental"] -fullScreenHelper=0 -edgeGesture=0 -preventClose=1 -forceTopmost=1 -alwaysVisible=1 -floatingBarAlwaysV=1 - -[config="automation"] -autoFold=1011110011000000110 -autoKill=0000 -autoKillFr=00 -ddb=0001101 - -[config="storage"] -storage=fr -userLocation= - -[config="snapshot"] -magnificationApi=0 -hideIccWin=0 -clipboard=1 -ink=0 -onlyMaxmizeWin=0 -filename="Screenshot-[YYYY]-[MM]-[DD]-[HH]-[mm]-[ss].png" - -/{icc.config="Settings"} \ No newline at end of file diff --git a/InkCanvasForClass/SpecialLuckyRandomConfig.icc.config.txt b/InkCanvasForClass/SpecialLuckyRandomConfig.icc.config.txt deleted file mode 100644 index ce29c59..0000000 --- a/InkCanvasForClass/SpecialLuckyRandomConfig.icc.config.txt +++ /dev/null @@ -1,19 +0,0 @@ -# icc 随机点名特殊配置文件 -# 这个语法是 icc 自己实现的,所以比较简陋 - -[config="test.luckyrand.list.txt"] -forceEnabled=true # 是否强制启用特殊配置,强制启用后不会隐藏设置中的开关,但是可以让开关失效(不保存到文件) - -whiteList[0]=孙笑川 # 井号后面是注释内容,不会识别 -whiteList[1]=蔡徐坤 # 此处设置的是全局白名单,这个白名单内的名字在所有情况下都不会被随机点名匹配到 - -# 此处设置姓名的匹配模式,是包含还是全等于还是开头 -# 包含 contains , 全等于 equals , 开头 startsWith -nameMatchingMode=contains - -# 设置动态白名单的开关和数据来源,目前仅支持配置内定义 -dynamicWhiteListEnabled=true -dynamicWhiteListSource=specialConfig - -dynamicWhiteList[0][time]=Mon/Tue/Wed/Thur/Fri;(08:00:00-08:40:00|08:50:00-09:30:00|10:00:00-10:40:00|10:50:00-11:30:00|11:40:00-12:25:00|14:30:00-15:10:00|15:30:00-16:10:00|16:20:00-17:40:00|17:50:00-18:30:00|17:50:00-18:20:00|19:00:00-19:50:00|20:00:00-20:50:00) -dynamicWhiteList[0][rule]= \ No newline at end of file diff --git a/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml b/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml new file mode 100644 index 0000000..d09ffd5 --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml.cs b/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml.cs new file mode 100644 index 0000000..30dffb6 --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsViews/AboutPanel.xaml.cs @@ -0,0 +1,243 @@ +using OSVersionExtension; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using iNKORE.UI.WPF.Helpers; +using static Ink_Canvas.Windows.SettingsWindow; + +namespace Ink_Canvas.Windows.SettingsViews { + /// + /// AboutPanel.xaml 的交互逻辑 + /// + public partial class AboutPanel : UserControl { + public AboutPanel() { + InitializeComponent(); + + // 关于页面图片横幅 + if (File.Exists(App.RootPath + "icc-about-illustrations.png")) { + try { + CopyrightBannerImage.Visibility = Visibility.Visible; + CopyrightBannerImage.Source = + new BitmapImage(new Uri($"file://{App.RootPath + "icc-about-illustrations.png"}")); + } + catch { } + } else { + CopyrightBannerImage.Visibility = Visibility.Collapsed; + } + + // 关于页面构建时间 + var buildTime = FileBuildTimeHelper.GetBuildDateTime(System.Reflection.Assembly.GetExecutingAssembly()); + if (buildTime != null) { + var bt = ((DateTimeOffset)buildTime).LocalDateTime; + var m = bt.Month.ToString().PadLeft(2, '0'); + var d = bt.Day.ToString().PadLeft(2, '0'); + var h = bt.Hour.ToString().PadLeft(2, '0'); + var min = bt.Minute.ToString().PadLeft(2, '0'); + var s = bt.Second.ToString().PadLeft(2, '0'); + AboutBuildTime.Text = + $"build-{bt.Year}-{m}-{d}-{h}:{min}:{s}"; + } + + // 关于页面系统版本 + AboutSystemVersion.Text = $"{OSVersion.GetOperatingSystem()} {OSVersion.GetOSVersion().Version}"; + + // 关于页面触摸设备 + var _t_touch = new Thread(() => { + var touchcount = TouchTabletDetectHelper.GetTouchTabletDevices().Count; + var support = TouchTabletDetectHelper.IsTouchEnabled(); + Dispatcher.BeginInvoke(() => + AboutTouchTabletText.Text = $"{touchcount}个设备,{(support ? "支持触摸设备" : "无触摸支持")}"); + }); + _t_touch.Start(); + } + + public static class TouchTabletDetectHelper { + [System.Runtime.InteropServices.DllImport("user32.dll")] + public static extern int GetSystemMetrics(int nIndex); + + public static bool IsTouchEnabled() + { + const int MAXTOUCHES_INDEX = 95; + int maxTouches = GetSystemMetrics(MAXTOUCHES_INDEX); + + return maxTouches > 0; + } + + public class USBDeviceInfo + { + public USBDeviceInfo(string deviceID, string pnpDeviceID, string description) + { + this.DeviceID = deviceID; + this.PnpDeviceID = pnpDeviceID; + this.Description = description; + } + public string DeviceID { get; private set; } + public string PnpDeviceID { get; private set; } + public string Description { get; private set; } + } + + public static List GetTouchTabletDevices() + { + List devices = new List(); + + ManagementObjectCollection collection; + using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity")) + collection = searcher.Get(); + + foreach (var device in collection) { + var name = new StringBuilder((string)device.GetPropertyValue("Name")).ToString(); + if (!name.Contains("Pentablet")) continue; + devices.Add(new USBDeviceInfo( + (string)device.GetPropertyValue("DeviceID"), + (string)device.GetPropertyValue("PNPDeviceID"), + (string)device.GetPropertyValue("Description") + )); + } + + collection.Dispose(); + return devices; + } + } + + public static class FileBuildTimeHelper { + public struct _IMAGE_FILE_HEADER + { + public ushort Machine; + public ushort NumberOfSections; + public uint TimeDateStamp; + public uint PointerToSymbolTable; + public uint NumberOfSymbols; + public ushort SizeOfOptionalHeader; + public ushort Characteristics; + }; + + public static DateTimeOffset? GetBuildDateTime(Assembly assembly) + { + var path = assembly.Location; + if (File.Exists(path)) + { + var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)]; + using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)) + { + fileStream.Position = 0x3C; + fileStream.Read(buffer, 0, 4); + fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset + fileStream.Read(buffer, 0, 4); // "PE\0\0" + fileStream.Read(buffer, 0, buffer.Length); + } + var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); + try + { + var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER)); + return DateTimeOffset.FromUnixTimeSeconds(coffHeader.TimeDateStamp); + } + finally + { + pinnedBuffer.Free(); + } + } + else + { + return null; + } + } + } + + public event EventHandler IsTopBarNeedShadowEffect; + public event EventHandler IsTopBarNeedNoShadowEffect; + + private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) { + var scrollViewer = (ScrollViewer)sender; + if (scrollViewer.VerticalOffset >= 10) { + IsTopBarNeedShadowEffect?.Invoke(this, new RoutedEventArgs()); + } else { + IsTopBarNeedNoShadowEffect?.Invoke(this, new RoutedEventArgs()); + } + } + + private void ScrollBar_Scroll(object sender, RoutedEventArgs e) { + var scrollbar = (ScrollBar)sender; + var scrollviewer = scrollbar.FindAscendant(); + if (scrollviewer != null) scrollviewer.ScrollToVerticalOffset(scrollbar.Track.Value); + } + + private void ScrollBarTrack_MouseEnter(object sender, MouseEventArgs e) { + var border = (Border)sender; + if (border.Child is Track track) { + track.Width = 16; + track.Margin = new Thickness(0, 0, -2, 0); + var scrollbar = track.FindAscendant(); + if (scrollbar != null) scrollbar.Width = 16; + var grid = track.FindAscendant(); + if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) { + backgroundBorder.Width = 8; + backgroundBorder.CornerRadius = new CornerRadius(4); + backgroundBorder.Opacity = 1; + } + var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ; + if (thumb != null) { + var _thumb = thumb as Border; + _thumb.CornerRadius = new CornerRadius(4); + _thumb.Width = 8; + _thumb.Margin = new Thickness(-0.75, 0, 1, 0); + _thumb.Background = new SolidColorBrush(Color.FromRgb(138, 138, 138)); + } + } + } + + private void ScrollBarTrack_MouseLeave(object sender, MouseEventArgs e) { + var border = (Border)sender; + border.Background = new SolidColorBrush(Colors.Transparent); + border.CornerRadius = new CornerRadius(0); + if (border.Child is Track track) { + track.Width = 6; + track.Margin = new Thickness(0, 0, 0, 0); + var scrollbar = track.FindAscendant(); + if (scrollbar != null) scrollbar.Width = 6; + var grid = track.FindAscendant(); + if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) { + backgroundBorder.Width = 3; + backgroundBorder.CornerRadius = new CornerRadius(1.5); + backgroundBorder.Opacity = 0; + } + var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ; + if (thumb != null) { + var _thumb = thumb as Border; + _thumb.CornerRadius = new CornerRadius(1.5); + _thumb.Width = 3; + _thumb.Margin = new Thickness(0); + _thumb.Background = new SolidColorBrush(Color.FromRgb(195, 195, 195)); + } + } + } + + private void ScrollbarThumb_MouseDown(object sender, MouseButtonEventArgs e) { + var thumb = (Thumb)sender; + var border = thumb.Template.FindName("ScrollbarThumbEx",thumb); + ((Border)border).Background = new SolidColorBrush(Color.FromRgb(95, 95, 95)); + } + + private void ScrollbarThumb_MouseUp(object sender, MouseButtonEventArgs e) { + var thumb = (Thumb)sender; + var border = thumb.Template.FindName("ScrollbarThumbEx",thumb); + ((Border)border).Background = new SolidColorBrush(Color.FromRgb(138, 138, 138)); + } + } +} diff --git a/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml b/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml new file mode 100644 index 0000000..a5d752c --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + diff --git a/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml.cs b/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml.cs new file mode 100644 index 0000000..5c6d458 --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsViews/SettingsBaseView.xaml.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using iNKORE.UI.WPF.Helpers; + +namespace Ink_Canvas.Windows.SettingsViews { + /// + /// SettingsBaseView.xaml 的交互逻辑 + /// + public partial class SettingsBaseView : UserControl { + public SettingsBaseView() { + InitializeComponent(); + } + + public event EventHandler IsTopBarNeedShadowEffect; + public event EventHandler IsTopBarNeedNoShadowEffect; + + private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) { + var scrollViewer = (ScrollViewer)sender; + if (scrollViewer.VerticalOffset >= 10) { + IsTopBarNeedShadowEffect?.Invoke(this, new RoutedEventArgs()); + } else { + IsTopBarNeedNoShadowEffect?.Invoke(this, new RoutedEventArgs()); + } + } + + private void ScrollBar_Scroll(object sender, RoutedEventArgs e) { + var scrollbar = (ScrollBar)sender; + var scrollviewer = scrollbar.FindAscendant(); + if (scrollviewer != null) scrollviewer.ScrollToVerticalOffset(scrollbar.Track.Value); + } + + private void ScrollBarTrack_MouseEnter(object sender, MouseEventArgs e) { + var border = (Border)sender; + if (border.Child is Track track) { + track.Width = 16; + track.Margin = new Thickness(0, 0, -2, 0); + var scrollbar = track.FindAscendant(); + if (scrollbar != null) scrollbar.Width = 16; + var grid = track.FindAscendant(); + if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) { + backgroundBorder.Width = 8; + backgroundBorder.CornerRadius = new CornerRadius(4); + backgroundBorder.Opacity = 1; + } + var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ; + if (thumb != null) { + var _thumb = thumb as Border; + _thumb.CornerRadius = new CornerRadius(4); + _thumb.Width = 8; + _thumb.Margin = new Thickness(-0.75, 0, 1, 0); + _thumb.Background = new SolidColorBrush(Color.FromRgb(138, 138, 138)); + } + } + } + + private void ScrollBarTrack_MouseLeave(object sender, MouseEventArgs e) { + var border = (Border)sender; + border.Background = new SolidColorBrush(Colors.Transparent); + border.CornerRadius = new CornerRadius(0); + if (border.Child is Track track) { + track.Width = 6; + track.Margin = new Thickness(0, 0, 0, 0); + var scrollbar = track.FindAscendant(); + if (scrollbar != null) scrollbar.Width = 6; + var grid = track.FindAscendant(); + if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) { + backgroundBorder.Width = 3; + backgroundBorder.CornerRadius = new CornerRadius(1.5); + backgroundBorder.Opacity = 0; + } + var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ; + if (thumb != null) { + var _thumb = thumb as Border; + _thumb.CornerRadius = new CornerRadius(1.5); + _thumb.Width = 3; + _thumb.Margin = new Thickness(0); + _thumb.Background = new SolidColorBrush(Color.FromRgb(195, 195, 195)); + } + } + } + + private void ScrollbarThumb_MouseDown(object sender, MouseButtonEventArgs e) { + var thumb = (Thumb)sender; + var border = thumb.Template.FindName("ScrollbarThumbEx",thumb); + ((Border)border).Background = new SolidColorBrush(Color.FromRgb(95, 95, 95)); + } + + private void ScrollbarThumb_MouseUp(object sender, MouseButtonEventArgs e) { + var thumb = (Thumb)sender; + var border = thumb.Template.FindName("ScrollbarThumbEx",thumb); + ((Border)border).Background = new SolidColorBrush(Color.FromRgb(138, 138, 138)); + } + } + +} diff --git a/InkCanvasForClass/Windows/SettingsWindow.xaml b/InkCanvasForClass/Windows/SettingsWindow.xaml index b39c028..f39bc7a 100644 --- a/InkCanvasForClass/Windows/SettingsWindow.xaml +++ b/InkCanvasForClass/Windows/SettingsWindow.xaml @@ -5,6 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Ink_Canvas.Windows" xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern" + xmlns:settingsViews="clr-namespace:Ink_Canvas.Windows.SettingsViews" WindowStartupLocation="CenterScreen" d:DesignHeight="19198" mc:Ignorable="d" WindowStyle="None" ResizeMode="CanMinimize" Background="Transparent" Title="InkCanvasForClass 设置" Height="691" Width="910" UseLayoutRounding="False"> @@ -556,132 +557,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1314,7 +1190,7 @@ - + @@ -1452,9 +1328,9 @@ - + - + @@ -3366,7 +3242,7 @@ - + diff --git a/InkCanvasForClass/Windows/SettingsWindow.xaml.cs b/InkCanvasForClass/Windows/SettingsWindow.xaml.cs index 0c052ac..3c9d667 100644 --- a/InkCanvasForClass/Windows/SettingsWindow.xaml.cs +++ b/InkCanvasForClass/Windows/SettingsWindow.xaml.cs @@ -16,6 +16,7 @@ using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; +using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; @@ -156,7 +157,7 @@ namespace Ink_Canvas.Windows { }; SettingsPaneScrollViewers = new ScrollViewer[] { - AboutScrollViewerEx, + SettingsAboutPanel.AboutScrollViewerEx, CanvasAndInkScrollViewerEx, GesturesScrollViewerEx, StartupScrollViewerEx, @@ -166,42 +167,8 @@ namespace Ink_Canvas.Windows { PowerPointScrollViewerEx }; - // 关于页面图片横幅 - if (File.Exists(App.RootPath + "icc-about-illustrations.png")) { - try { - CopyrightBannerImage.Visibility = Visibility.Visible; - CopyrightBannerImage.Source = - new BitmapImage(new Uri($"file://{App.RootPath + "icc-about-illustrations.png"}")); - } - catch { } - } else { - CopyrightBannerImage.Visibility = Visibility.Collapsed; - } - - // 关于页面构建时间 - var buildTime = FileBuildTimeHelper.GetBuildDateTime(System.Reflection.Assembly.GetExecutingAssembly()); - if (buildTime != null) { - var bt = ((DateTimeOffset)buildTime).LocalDateTime; - var m = bt.Month.ToString().PadLeft(2, '0'); - var d = bt.Day.ToString().PadLeft(2, '0'); - var h = bt.Hour.ToString().PadLeft(2, '0'); - var min = bt.Minute.ToString().PadLeft(2, '0'); - var s = bt.Second.ToString().PadLeft(2, '0'); - AboutBuildTime.Text = - $"build-{bt.Year}-{m}-{d}-{h}:{min}:{s}"; - } - - // 关于页面系统版本 - AboutSystemVersion.Text = $"{OSVersion.GetOperatingSystem()} {OSVersion.GetOSVersion().Version}"; - - // 关于页面触摸设备 - var _t_touch = new Thread(() => { - var touchcount = TouchTabletDetectHelper.GetTouchTabletDevices().Count; - var support = TouchTabletDetectHelper.IsTouchEnabled(); - Dispatcher.BeginInvoke(() => - AboutTouchTabletText.Text = $"{touchcount}个设备,{(support ? "支持触摸设备" : "无触摸支持")}"); - }); - _t_touch.Start(); + SettingsAboutPanel.IsTopBarNeedShadowEffect += (o, s) => DropShadowEffectTopBar.Opacity = 0.25; + SettingsAboutPanel.IsTopBarNeedNoShadowEffect += (o, s) => DropShadowEffectTopBar.Opacity = 0; } public Grid[] SettingsPanes = new Grid[] { }; @@ -256,98 +223,6 @@ namespace Ink_Canvas.Windows { } } - public static class TouchTabletDetectHelper { - [System.Runtime.InteropServices.DllImport("user32.dll")] - public static extern int GetSystemMetrics(int nIndex); - - public static bool IsTouchEnabled() - { - const int MAXTOUCHES_INDEX = 95; - int maxTouches = GetSystemMetrics(MAXTOUCHES_INDEX); - - return maxTouches > 0; - } - - public class USBDeviceInfo - { - public USBDeviceInfo(string deviceID, string pnpDeviceID, string description) - { - this.DeviceID = deviceID; - this.PnpDeviceID = pnpDeviceID; - this.Description = description; - } - public string DeviceID { get; private set; } - public string PnpDeviceID { get; private set; } - public string Description { get; private set; } - } - - public static List GetTouchTabletDevices() - { - List devices = new List(); - - ManagementObjectCollection collection; - using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity")) - collection = searcher.Get(); - - foreach (var device in collection) { - var name = new StringBuilder((string)device.GetPropertyValue("Name")).ToString(); - if (!name.Contains("Pentablet")) continue; - devices.Add(new USBDeviceInfo( - (string)device.GetPropertyValue("DeviceID"), - (string)device.GetPropertyValue("PNPDeviceID"), - (string)device.GetPropertyValue("Description") - )); - } - - collection.Dispose(); - return devices; - } - } - - public static class FileBuildTimeHelper { - public struct _IMAGE_FILE_HEADER - { - public ushort Machine; - public ushort NumberOfSections; - public uint TimeDateStamp; - public uint PointerToSymbolTable; - public uint NumberOfSymbols; - public ushort SizeOfOptionalHeader; - public ushort Characteristics; - }; - - public static DateTimeOffset? GetBuildDateTime(Assembly assembly) - { - var path = assembly.Location; - if (File.Exists(path)) - { - var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)]; - using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - fileStream.Position = 0x3C; - fileStream.Read(buffer, 0, 4); - fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset - fileStream.Read(buffer, 0, 4); // "PE\0\0" - fileStream.Read(buffer, 0, buffer.Length); - } - var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); - try - { - var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER)); - return DateTimeOffset.FromUnixTimeSeconds(coffHeader.TimeDateStamp); - } - finally - { - pinnedBuffer.Free(); - } - } - else - { - return null; - } - } - } - private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) { var scrollViewer = (ScrollViewer)sender; if (scrollViewer.VerticalOffset >= 10) { diff --git a/InkCanvasForClass/icc.toml b/InkCanvasForClass/icc.toml new file mode 100644 index 0000000..26f1870 --- /dev/null +++ b/InkCanvasForClass/icc.toml @@ -0,0 +1,39 @@ +# InkCanvasForClass 配置文件 +# 版本:v1.0 2024-9-12 +Version = 1.0 +# +# +[FloatingBar] # 浮动工具栏 +SemiTransparent = false # 半透明工具栏 +# 开启半透明工具栏后,所有按钮都会呈现为半透明状态 +NearSnap = false # 靠近屏幕角落自动吸附 +InitialPosition = "Center" # 初始位置 +# 初始位置可以是 "TopLeft" "TopRight" "BottomLeft" "BottomRight" "BottomCenter" "TopCenter" +# 或者以数组形式传入浮动工具栏左上角定位的坐标 +ElementCornerRadius = "SuperEllipse" # 圆角类型 +# 圆角类型可以是 "SuperEllipse" "Circle" "None" +# 也可以是具体的数字大小,如 1.14 5.14 2 16 +# 最大圆角值为 24,相当于 "Circle","SuperEllipse" 是超椭圆 +ParallaxEffect = true # 视差效果 +MiniMode = true # 迷你模式 +MiniModeTrigger = false # 浮动工具栏迷你模式触发器,暂未实现 +# 可选 "HeadIconMouseButtonRight" "HeadIconMouseButtonCenter" "HeadIconMouseButtonLeftWithCtrlKey" +# 可使用 KeyStroke 来填入触发器 +ClearButtonColor = [224, 27, 36] # 清空按钮颜色 +ClearButtonPressColor = [254, 226, 226] # 清空按钮按下时颜色 +ToolButtonSelectedBgColor = [37, 99, 235] # 工具按钮选中颜色 +MovingLimitationNoSnap = 12 # 移动限制 无Snap,0 关闭 +MovingLimitationSnapped = 24 # 移动限制 Snaped,0 关闭 +# +[FloatingBar.NearSnapAreaSize] # 浮动工具栏角落吸附区域大小 +TopLeft = 24 # 左上角 +TopRight = 24 # 右上角 +BottomLeft = [24,24] # 左下角 +BottomRight = [24,24] # 右下角 +TopCenter = 24 # 顶部 +BottomCenter = 24 # 底部 +# +[FloatingBar.ToolBarItems] # 浮动工具栏工具按钮排序和显示 +CursorMode = [ "Cursor", "Pen", "Clear" , "Separator", "Whiteboard", "Gesture", "Menu", "Fold" ] +MiniMode = [ "Cursor", "Pen", "Clear" ] +AnnotationMode = [ "Cursor", "Pen", "Clear", "Separator", "Eraser", "ShapeDrawing", "Select", "Separator", "Undo", "Redo", "Separator", "Whiteboard", "Gesture", "Menu", "Fold" ] \ No newline at end of file