diff --git a/InkCanvasForClass/App.xaml.cs b/InkCanvasForClass/App.xaml.cs index 4cb2f65..cb01333 100644 --- a/InkCanvasForClass/App.xaml.cs +++ b/InkCanvasForClass/App.xaml.cs @@ -15,6 +15,8 @@ using Window = System.Windows.Window; using System.Windows.Shell; using Ookii.Dialogs.Wpf; using System.Diagnostics; +using Ink_Canvas.Popups; +using Ink_Canvas.Windows; using Lierda.WPFHelper; namespace Ink_Canvas @@ -115,6 +117,9 @@ namespace Ink_Canvas } mainWin.Show(); + var setW = new SettingsWindow(); + setW.Show(); + _taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon"); LierdaCracker cracker = new LierdaCracker(); diff --git a/InkCanvasForClass/InkCanvasForClass.csproj b/InkCanvasForClass/InkCanvasForClass.csproj index 10a855c..58955ad 100644 --- a/InkCanvasForClass/InkCanvasForClass.csproj +++ b/InkCanvasForClass/InkCanvasForClass.csproj @@ -25,6 +25,7 @@ False true Debug;Release;x86 Debug + false embedded @@ -597,6 +598,9 @@ PreserveNewest + + Always + diff --git a/InkCanvasForClass/InkCanvasForClass.csproj.user b/InkCanvasForClass/InkCanvasForClass.csproj.user index 403f6f0..9e6bd27 100644 --- a/InkCanvasForClass/InkCanvasForClass.csproj.user +++ b/InkCanvasForClass/InkCanvasForClass.csproj.user @@ -17,9 +17,6 @@ Code - - Code - Code @@ -29,6 +26,9 @@ Code + + Code + @@ -46,12 +46,6 @@ Designer - - Designer - - - Designer - Designer @@ -64,7 +58,7 @@ Designer - + Designer diff --git a/InkCanvasForClass/Popups/FloatingBarV2Resources.xaml b/InkCanvasForClass/Popups/FloatingBarV2Resources.xaml deleted file mode 100644 index cc1bd18..0000000 --- a/InkCanvasForClass/Popups/FloatingBarV2Resources.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml b/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml deleted file mode 100644 index a5f0349..0000000 --- a/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml.cs b/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml.cs deleted file mode 100644 index 8bf2c2d..0000000 --- a/InkCanvasForClass/Popups/FloatingBarWindowV2.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -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.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; - -namespace Ink_Canvas.Popups -{ - /// - /// FloatingBarWindowV2.xaml 的交互逻辑 - /// - public partial class FloatingBarWindowV2 : Window - { - public FloatingBarWindowV2() - { - InitializeComponent(); - } - } -} diff --git a/InkCanvasForClass/Resources/Themes/DarkFloatingBarTheme.xaml b/InkCanvasForClass/Resources/Themes/DarkFloatingBarTheme.xaml deleted file mode 100644 index a60cfa1..0000000 --- a/InkCanvasForClass/Resources/Themes/DarkFloatingBarTheme.xaml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/InkCanvasForClass/Windows/SettingsWindow.xaml b/InkCanvasForClass/Windows/SettingsWindow.xaml new file mode 100644 index 0000000..321f282 --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsWindow.xaml @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/InkCanvasForClass/Windows/SettingsWindow.xaml.cs b/InkCanvasForClass/Windows/SettingsWindow.xaml.cs new file mode 100644 index 0000000..4b94524 --- /dev/null +++ b/InkCanvasForClass/Windows/SettingsWindow.xaml.cs @@ -0,0 +1,329 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +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.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using iNKORE.UI.WPF.Helpers; +using OSVersionExtension; + +namespace Ink_Canvas.Windows { + public partial class SettingsWindow : Window { + + public SettingsWindow() { + InitializeComponent(); + + // 初始化侧边栏项目 + SidebarItemsControl.ItemsSource = SidebarItems; + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "启动时行为", + Name = "StartupItem", + IconSource = FindResource("StartupIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "画板和墨迹", + Name = "CanvasAndInkItem", + IconSource = FindResource("CanvasAndInkIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "手势操作", + Name = "GesturesItem", + IconSource = FindResource("GesturesIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Separator + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "个性化和外观", + Name = "AppearanceItem", + IconSource = FindResource("AppearanceIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "墨迹转形状", + Name = "InkRecognitionItem", + IconSource = FindResource("InkRecognitionIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "几何与形状绘制", + Name = "ShapeDrawingItem", + IconSource = FindResource("ShapeDrawingIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "自动化行为", + Name = "AutomationItem", + IconSource = FindResource("AutomationIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Separator + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "PowerPoint 支持", + Name = "PowerPointItem", + IconSource = FindResource("PowerPointIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "插件和脚本", + Name = "ExtensionsItem", + IconSource = FindResource("ExtensionsIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Separator + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "存储空间", + Name = "StorageItem", + IconSource = FindResource("StorageIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "截图和屏幕捕捉", + Name = "SnapshotItem", + IconSource = FindResource("SnapshotIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "点名器设置", + Name = "LuckyRandomItem", + IconSource = FindResource("LuckyRandomIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "高级选项", + Name = "AdvancedItem", + IconSource = FindResource("AdvancedIcon") as DrawingImage, + Selected = false, + }); + SidebarItems.Add(new SidebarItem() { + Type = SidebarItemType.Item, + Title = "关于 InkCanvasForClass", + Name = "AboutItem", + IconSource = FindResource("AboutIcon") as DrawingImage, + Selected = false, + }); + _selectedSidebarItemName = "AboutItem"; + UpdateSidebarItemsSelection(); + + // 关于页面图片横幅 + 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 enum SidebarItemType { + Item, + Separator + } + + public class SidebarItem { + public SidebarItemType Type { get; set; } + public string Title { get; set; } + public string Name { get; set; } + public ImageSource IconSource { get; set; } + public bool Selected { get; set; } + public Visibility _spVisibility { + get => this.Type == SidebarItemType.Separator ? Visibility.Visible : Visibility.Collapsed; + } + public Visibility _siVisibility { + get => this.Type == SidebarItemType.Item ? Visibility.Visible : Visibility.Collapsed; + } + + public SolidColorBrush _siBackground { + get => this.Selected + ? new SolidColorBrush(Color.FromRgb(217, 217, 217)) + : new SolidColorBrush(Colors.Transparent); + } + } + + public string _selectedSidebarItemName = ""; + public ObservableCollection SidebarItems = new ObservableCollection(); + + public void UpdateSidebarItemsSelection() { + foreach (var si in SidebarItems) { + si.Selected = si.Name == _selectedSidebarItemName; + if (si.Selected) SettingsWindowTitle.Text = si.Title; + } + CollectionViewSource.GetDefaultView(SidebarItems).Refresh(); + } + + 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 Border _sidebarItemMouseDownBorder = null; + + private void SidebarItem_MouseDown(object sender, MouseButtonEventArgs e) { + if (_sidebarItemMouseDownBorder != null || _sidebarItemMouseDownBorder == sender) return; + _sidebarItemMouseDownBorder = (Border)sender; + var bd = sender as Border; + if (bd.FindDescendantByName("MouseFeedbackBorder") is Border feedbackBd) feedbackBd.Opacity = 0.12; + } + + private void SidebarItem_MouseUp(object sender, MouseButtonEventArgs e) { + if (_sidebarItemMouseDownBorder == null || _sidebarItemMouseDownBorder != sender) return; + if (_sidebarItemMouseDownBorder.Tag is SidebarItem data) _selectedSidebarItemName = data.Name; + SidebarItem_MouseLeave(sender, null); + UpdateSidebarItemsSelection(); + } + + private void SidebarItem_MouseLeave(object sender, MouseEventArgs e) { + if (_sidebarItemMouseDownBorder == null || _sidebarItemMouseDownBorder != sender) return; + if (_sidebarItemMouseDownBorder.FindDescendantByName("MouseFeedbackBorder") is Border feedbackBd) feedbackBd.Opacity = 0; + _sidebarItemMouseDownBorder = null; + } + } +} diff --git a/InkCanvasForClass/icc-about-illustrations.png b/InkCanvasForClass/icc-about-illustrations.png new file mode 100644 index 0000000..43151b0 Binary files /dev/null and b/InkCanvasForClass/icc-about-illustrations.png differ