From 1a9ddf19697cb8962566f60c0be07795d14c46a0 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 6 Sep 2025 13:16:10 +0800 Subject: [PATCH] =?UTF-8?q?improve:=E5=A2=A8=E8=BF=B9=E6=B8=90=E9=9A=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/InkFadeManager.cs | 60 ++- Ink Canvas/Helpers/WindowZOrderManager.cs | 99 +++-- Ink Canvas/MainWindow.xaml.cs | 294 ++++++++++++++- .../MainWindow_cs/MW_FloatingBarIcons.cs | 6 +- Ink Canvas/Windows/RandWindow.xaml.cs | 15 + .../SettingsViews/SettingsWindow.xaml.cs | 348 ++++++++++++++++++ 6 files changed, 757 insertions(+), 65 deletions(-) diff --git a/Ink Canvas/Helpers/InkFadeManager.cs b/Ink Canvas/Helpers/InkFadeManager.cs index 3477b100..eec846ac 100644 --- a/Ink Canvas/Helpers/InkFadeManager.cs +++ b/Ink Canvas/Helpers/InkFadeManager.cs @@ -833,12 +833,8 @@ namespace Ink_Canvas.Helpers // 归一化方向向量 direction.Normalize(); - // 使用OpacityMask创建更自然的擦除效果 - var maskBrush = CreateEraseMaskBrush(stroke, strokeStart, strokeEnd, 1.0); - visual.OpacityMask = maskBrush; - - // 创建擦除动画 - 使用定时器来更新遮罩 - StartEraseMaskAnimation(visual, stroke, strokeStart, strokeEnd, duration); + // 创建精确的擦除动画 - 使用PathGeometry来避免变形 + CreatePreciseEraseAnimation(visual, stroke, bounds, strokeStart, strokeEnd, direction, length, duration); } catch (Exception ex) { @@ -848,6 +844,58 @@ namespace Ink_Canvas.Helpers } } + /// + /// 创建精确的擦除动画 - 使用动态裁剪区域避免墨迹移动 + /// + private void CreatePreciseEraseAnimation(UIElement visual, Stroke stroke, Rect bounds, Point strokeStart, Point strokeEnd, Vector direction, double length, int duration) + { + try + { + // 计算擦除方向上的移动距离 + var totalDistance = Math.Sqrt(Math.Pow(strokeEnd.X - strokeStart.X, 2) + Math.Pow(strokeEnd.Y - strokeStart.Y, 2)); + + if (totalDistance == 0) + { + // 如果墨迹没有长度,使用简单渐隐 + StartSimpleFadeAnimation(visual, stroke, visual.Opacity, duration); + return; + } + + // 创建动态裁剪区域 - 从完整墨迹开始,逐渐缩小 + var clipGeometry = new RectangleGeometry + { + Rect = bounds + }; + + visual.Clip = clipGeometry; + + // 创建擦除动画 - 裁剪区域从起点向终点移动并缩小 + // 使用更自然的擦除效果:从起点开始,逐渐向终点移动 + var eraseAnimation = new RectAnimation + { + From = bounds, // 从完整边界开始 + To = new Rect(strokeEnd.X, strokeEnd.Y, 0, bounds.Height), // 到终点位置,宽度为0 + Duration = TimeSpan.FromMilliseconds(duration), + EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } + }; + + // 添加动画完成事件 + eraseAnimation.Completed += (sender, e) => + { + OnAnimationCompleted(visual, stroke); + }; + + // 开始动画 + clipGeometry.BeginAnimation(RectangleGeometry.RectProperty, eraseAnimation); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"精确擦除动画失败: {ex}", LogHelper.LogType.Error); + // 失败时回退到简单动画 + StartSimpleFadeAnimation(visual, stroke, visual.Opacity, duration); + } + } + /// /// 动画完成后的统一处理 /// diff --git a/Ink Canvas/Helpers/WindowZOrderManager.cs b/Ink Canvas/Helpers/WindowZOrderManager.cs index f1d19f91..898b0c06 100644 --- a/Ink Canvas/Helpers/WindowZOrderManager.cs +++ b/Ink Canvas/Helpers/WindowZOrderManager.cs @@ -155,6 +155,22 @@ namespace Ink_Canvas.Helpers { // 更新创建时间,使其成为最新的窗口 windowInfo.CreatedTime = DateTime.Now; + + // 立即将窗口置顶 + var hwnd = new WindowInteropHelper(window).Handle; + if (hwnd != IntPtr.Zero) + { + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); + + // 确保窗口样式正确 + int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + if ((exStyle & WS_EX_TOPMOST) == 0) + { + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); + } + } + ApplyZOrder(); } } @@ -165,64 +181,12 @@ namespace Ink_Canvas.Helpers /// private static void ApplyZOrder() { - // 按创建时间排序,最新的窗口在最后 - var sortedWindows = _windowStack - .Where(w => IsWindow(w.Handle) && IsWindowVisible(w.Handle) && !IsIconic(w.Handle)) - .OrderBy(w => w.CreatedTime) - .ToList(); - - if (sortedWindows.Count == 0) return; - - // 获取主窗口(第一个注册的窗口) - var mainWindow = sortedWindows.FirstOrDefault(); - if (mainWindow == null) return; - - // 如果主窗口需要置顶且启用了无焦点模式 - if (mainWindow.IsTopmost && mainWindow.IsNoFocusMode) + // 简化逻辑:直接设置所有窗口为置顶,让Windows系统自然处理层级 + foreach (var windowInfo in _windowStack.ToList()) { - // 检查是否有子窗口在前景 - var foregroundWindow = GetForegroundWindow(); - var hasChildWindowInForeground = false; - - if (foregroundWindow != mainWindow.Handle) - { - var foregroundWindowProcessId = GetWindowThreadProcessId(foregroundWindow, out uint processId); - var currentProcessId = GetCurrentProcessId(); - - if (processId == currentProcessId) - { - // 检查前景窗口是否在我们的窗口列表中 - var foregroundWindowInfo = sortedWindows.FirstOrDefault(w => w.Handle == foregroundWindow); - if (foregroundWindowInfo != null) - { - hasChildWindowInForeground = true; - } - } - } - - if (!hasChildWindowInForeground) - { - // 没有子窗口在前景,主窗口置顶 - SetWindowPos(mainWindow.Handle, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); - - // 确保主窗口样式正确 - int exStyle = GetWindowLong(mainWindow.Handle, GWL_EXSTYLE); - if ((exStyle & WS_EX_TOPMOST) == 0) - { - SetWindowLong(mainWindow.Handle, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); - } - } - } - - // 处理其他窗口的层级 - for (int i = 1; i < sortedWindows.Count; i++) - { - var windowInfo = sortedWindows[i]; - - // 子窗口应该置顶于主窗口 - if (windowInfo.IsTopmost) + if (windowInfo.IsTopmost && IsWindow(windowInfo.Handle) && IsWindowVisible(windowInfo.Handle) && !IsIconic(windowInfo.Handle)) { + // 设置窗口为置顶 SetWindowPos(windowInfo.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); @@ -273,5 +237,28 @@ namespace Ink_Canvas.Helpers return _windowStack.Count; } } + + /// + /// 强制刷新所有窗口的置顶状态 + /// + public static void ForceRefreshAllWindows() + { + lock (_lockObject) + { + foreach (var windowInfo in _windowStack.ToList()) + { + if (windowInfo.IsTopmost && IsWindow(windowInfo.Handle)) + { + // 强制设置窗口为置顶 + SetWindowPos(windowInfo.Handle, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); + + // 确保窗口样式正确 + int exStyle = GetWindowLong(windowInfo.Handle, GWL_EXSTYLE); + SetWindowLong(windowInfo.Handle, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); + } + } + } + } } } \ No newline at end of file diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 54fdb76b..aa566704 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -16,6 +16,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Forms; using System.Windows.Ink; using System.Windows.Input; @@ -246,6 +247,9 @@ namespace Ink_Canvas // 为浮动栏按钮添加触摸事件支持 AddTouchSupportToFloatingBarButtons(); + + // 为滑块控件添加触摸事件支持 + AddTouchSupportToSliders(); } @@ -1755,6 +1759,9 @@ namespace Ink_Canvas // 先设置WPF的Topmost属性 Topmost = true; + // 立即应用置顶 + WindowZOrderManager.BringToTop(this); + // 如果启用了无焦点模式,需要特殊处理 if (Settings.Advanced.IsNoFocusMode) { @@ -1847,8 +1854,8 @@ namespace Ink_Canvas // 检查是否有子窗口在前景 if (!WindowZOrderManager.HasChildWindowInForeground()) { - // 没有子窗口在前景,重新应用Z-Order - WindowZOrderManager.SetWindowTopmost(this, true); + // 没有子窗口在前景,强制刷新所有窗口的置顶状态 + WindowZOrderManager.ForceRefreshAllWindows(); } } catch (Exception ex) @@ -2227,5 +2234,288 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"设置工具模式时出错: {ex.Message}", LogHelper.LogType.Error); } } + + #region 滑块触摸支持 + + /// + /// 为所有滑块控件添加触摸和手写笔事件支持 + /// + private void AddTouchSupportToSliders() + { + try + { + // 获取所有滑块控件并添加触摸支持 + var sliders = new List + { + InkFadeTimeSlider, + AutoStraightenLineThresholdSlider, + LineStraightenSensitivitySlider, + LineEndpointSnappingThresholdSlider, + ViewboxFloatingBarScaleTransformValueSlider, + ViewboxFloatingBarOpacityValueSlider, + ViewboxFloatingBarOpacityInPPTValueSlider, + PPTButtonLeftPositionValueSlider, + PPTButtonRightPositionValueSlider, + PPTButtonLBPositionValueSlider, + PPTButtonRBPositionValueSlider, + TouchMultiplierSlider, + NibModeBoundsWidthSlider, + FingerModeBoundsWidthSlider, + SideControlMinimumAutomationSlider, + RandWindowOnceCloseLatencySlider, + RandWindowOnceMaxStudentsSlider, + BoardInkWidthSlider, + BoardInkAlphaSlider, + BoardHighlighterWidthSlider, + InkWidthSlider, + InkAlphaSlider, + HighlighterWidthSlider + }; + + foreach (var slider in sliders) + { + if (slider != null) + { + AddTouchSupportToSlider(slider); + } + } + + LogHelper.WriteLogToFile("已为所有滑块控件添加触摸支持", LogHelper.LogType.Trace); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"添加滑块触摸支持时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 为单个滑块控件添加触摸和手写笔事件支持 + /// + /// 要添加触摸支持的滑块控件 + private void AddTouchSupportToSlider(Slider slider) + { + if (slider == null) return; + + // 启用触摸和手写笔支持 + slider.IsManipulationEnabled = true; + + // 添加触摸事件 + slider.TouchDown += Slider_TouchDown; + slider.TouchMove += Slider_TouchMove; + slider.TouchUp += Slider_TouchUp; + + // 添加手写笔事件 + slider.StylusDown += Slider_StylusDown; + slider.StylusMove += Slider_StylusMove; + slider.StylusUp += Slider_StylusUp; + + // 添加操作事件(用于更精确的触摸控制) + slider.ManipulationStarted += Slider_ManipulationStarted; + slider.ManipulationDelta += Slider_ManipulationDelta; + slider.ManipulationCompleted += Slider_ManipulationCompleted; + } + + /// + /// 滑块触摸按下事件处理 + /// + private void Slider_TouchDown(object sender, TouchEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 捕获触摸设备 + slider.CaptureTouch(e.TouchDevice); + + // 计算触摸位置对应的滑块值 + var touchPoint = e.GetTouchPoint(slider); + UpdateSliderValueFromPosition(slider, touchPoint.Position); + + e.Handled = true; + } + + /// + /// 滑块触摸移动事件处理 + /// + private void Slider_TouchMove(object sender, TouchEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 计算触摸位置对应的滑块值 + var touchPoint = e.GetTouchPoint(slider); + UpdateSliderValueFromPosition(slider, touchPoint.Position); + + e.Handled = true; + } + + /// + /// 滑块触摸释放事件处理 + /// + private void Slider_TouchUp(object sender, TouchEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 释放触摸捕获 + slider.ReleaseTouchCapture(e.TouchDevice); + + e.Handled = true; + } + + /// + /// 滑块手写笔按下事件处理 + /// + private void Slider_StylusDown(object sender, StylusDownEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 捕获手写笔设备 + slider.CaptureStylus(); + + // 计算手写笔位置对应的滑块值 + var stylusPoint = e.GetStylusPoints(slider); + if (stylusPoint.Count > 0) + { + UpdateSliderValueFromPosition(slider, stylusPoint[0].ToPoint()); + } + + e.Handled = true; + } + + /// + /// 滑块手写笔移动事件处理 + /// + private void Slider_StylusMove(object sender, StylusEventArgs e) + { + var slider = sender as Slider; + if (slider == null || !slider.IsStylusCaptured) return; + + // 计算手写笔位置对应的滑块值 + var stylusPoint = e.GetStylusPoints(slider); + if (stylusPoint.Count > 0) + { + UpdateSliderValueFromPosition(slider, stylusPoint[0].ToPoint()); + } + + e.Handled = true; + } + + /// + /// 滑块手写笔释放事件处理 + /// + private void Slider_StylusUp(object sender, StylusEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 释放手写笔捕获 + slider.ReleaseStylusCapture(); + + e.Handled = true; + } + + /// + /// 滑块操作开始事件处理 + /// + private void Slider_ManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + e.Handled = true; + } + + /// + /// 滑块操作变化事件处理 + /// + private void Slider_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + // 计算操作位置对应的滑块值 + var manipulationOrigin = e.ManipulationOrigin; + UpdateSliderValueFromPosition(slider, manipulationOrigin); + + e.Handled = true; + } + + /// + /// 滑块操作完成事件处理 + /// + private void Slider_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + var slider = sender as Slider; + if (slider == null) return; + + e.Handled = true; + } + + /// + /// 根据触摸/手写笔位置更新滑块值 + /// + /// 滑块控件 + /// 触摸/手写笔位置 + private void UpdateSliderValueFromPosition(Slider slider, Point position) + { + if (slider == null) return; + + try + { + // 计算滑块轨道的位置和长度 + var track = slider.Template.FindName("PART_Track", slider) as Track; + if (track == null) return; + + var thumb = track.Thumb; + if (thumb == null) return; + + // 获取滑块轨道的实际渲染位置 + track.Arrange(new Rect(track.DesiredSize)); + thumb.Arrange(new Rect(thumb.DesiredSize)); + + // 计算相对位置(0-1之间) + double relativePosition = 0; + + if (slider.Orientation == System.Windows.Controls.Orientation.Horizontal) + { + // 水平滑块 + var trackWidth = track.ActualWidth; + if (trackWidth > 0) + { + relativePosition = Math.Max(0, Math.Min(1, position.X / trackWidth)); + } + } + else + { + // 垂直滑块 + var trackHeight = track.ActualHeight; + if (trackHeight > 0) + { + relativePosition = Math.Max(0, Math.Min(1, position.Y / trackHeight)); + } + } + + // 计算新的滑块值 + var newValue = slider.Minimum + relativePosition * (slider.Maximum - slider.Minimum); + + // 如果启用了吸附到刻度,则调整到最近的刻度 + if (slider.IsSnapToTickEnabled && slider.TickFrequency > 0) + { + var tickCount = (int)((slider.Maximum - slider.Minimum) / slider.TickFrequency); + var tickIndex = (int)Math.Round(relativePosition * tickCount); + newValue = slider.Minimum + tickIndex * slider.TickFrequency; + } + + // 更新滑块值 + slider.Value = Math.Max(slider.Minimum, Math.Min(slider.Maximum, newValue)); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"更新滑块值时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + #endregion } } diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 3d6aeb34..a2dfdaa1 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -944,7 +944,11 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BoardBorderTools); AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel); - new RandWindow(Settings).Show(); + var randWindow = new RandWindow(Settings); + randWindow.Show(); + // 确保窗口显示后立即置顶 + randWindow.Activate(); + WindowZOrderManager.BringToTop(randWindow); } public void CheckEraserTypeTab() diff --git a/Ink Canvas/Windows/RandWindow.xaml.cs b/Ink Canvas/Windows/RandWindow.xaml.cs index be2f2194..d62a36d8 100644 --- a/Ink Canvas/Windows/RandWindow.xaml.cs +++ b/Ink Canvas/Windows/RandWindow.xaml.cs @@ -35,6 +35,9 @@ namespace Ink_Canvas // 添加窗口关闭事件处理 Closed += RandWindow_Closed; + + // 添加窗口显示事件处理 + Loaded += RandWindow_Loaded; } private void LoadBackground(Settings settings) @@ -86,6 +89,9 @@ namespace Ink_Canvas // 添加窗口关闭事件处理 Closed += RandWindow_Closed; + + // 添加窗口显示事件处理 + Loaded += RandWindow_Loaded; new Thread(() => { @@ -349,6 +355,15 @@ namespace Ink_Canvas } } + /// + /// 窗口加载事件处理 + /// + private void RandWindow_Loaded(object sender, RoutedEventArgs e) + { + // 窗口加载完成后,立即将其置顶 + WindowZOrderManager.BringToTop(this); + } + /// /// 窗口关闭事件处理 /// diff --git a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs index d74e4181..eea8efeb 100644 --- a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs +++ b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs @@ -218,6 +218,9 @@ namespace Ink_Canvas.Windows { _selectedSidebarItemName = "CanvasAndInkItem"; UpdateSidebarItemsSelection(); + + // 为自定义滑块控件添加触摸支持 + AddTouchSupportToCustomSliders(); } @@ -594,5 +597,350 @@ namespace Ink_Canvas.Windows { } } } + + #region 自定义滑块触摸支持 + + /// + /// 为自定义滑块控件添加触摸和手写笔事件支持 + /// + private void AddTouchSupportToCustomSliders() + { + try + { + // 延迟执行,确保UI元素已加载 + Dispatcher.BeginInvoke(new Action(() => + { + // 查找所有自定义滑块控件并添加触摸支持 + AddTouchSupportToCustomSliderInPane(CanvasAndInkPane); + AddTouchSupportToCustomSliderInPane(ThemePane); + AddTouchSupportToCustomSliderInPane(PowerPointPane); + AddTouchSupportToCustomSliderInPane(AutomationPane); + AddTouchSupportToCustomSliderInPane(LuckyRandomPane); + AddTouchSupportToCustomSliderInPane(AdvancedPane); + }), System.Windows.Threading.DispatcherPriority.Loaded); + } + catch (Exception ex) + { + // 记录错误但不影响程序运行 + System.Diagnostics.Debug.WriteLine($"添加自定义滑块触摸支持时出错: {ex.Message}"); + } + } + + /// + /// 为指定面板中的自定义滑块控件添加触摸支持 + /// + /// 面板控件 + private void AddTouchSupportToCustomSliderInPane(Grid pane) + { + if (pane == null) return; + + // 查找面板中的所有自定义滑块控件 + var customSliders = FindCustomSlidersInPanel(pane); + + foreach (var slider in customSliders) + { + AddTouchSupportToCustomSlider(slider); + } + } + + /// + /// 在面板中查找自定义滑块控件 + /// + /// 面板控件 + /// 自定义滑块控件列表 + private List FindCustomSlidersInPanel(DependencyObject panel) + { + var customSliders = new List(); + + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(panel); i++) + { + var child = VisualTreeHelper.GetChild(panel, i); + + // 检查是否是自定义滑块控件(包含GnomeSliderThumb图片的Grid) + if (child is Grid grid) + { + var customSlider = FindCustomSliderInGrid(grid); + if (customSlider != null) + { + customSliders.Add(customSlider); + } + } + + // 递归查找子元素 + customSliders.AddRange(FindCustomSlidersInPanel(child)); + } + + return customSliders; + } + + /// + /// 在Grid中查找自定义滑块控件 + /// + /// Grid控件 + /// 自定义滑块信息 + private CustomSliderInfo FindCustomSliderInGrid(Grid grid) + { + // 查找包含GnomeSliderThumb图片的Grid + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++) + { + var child = VisualTreeHelper.GetChild(grid, i); + + if (child is Image image && image.Source != null) + { + var sourceName = image.Source.ToString(); + if (sourceName.Contains("GnomeSliderThumb")) + { + // 找到滑块控件,创建自定义滑块信息 + var customSlider = new CustomSliderInfo + { + Container = grid, + ThumbImage = image, + TrackBorder = FindTrackBorderInGrid(grid), + ValueBorder = FindValueBorderInGrid(grid) + }; + + return customSlider; + } + } + } + + return null; + } + + /// + /// 在Grid中查找轨道Border + /// + /// Grid控件 + /// 轨道Border + private Border FindTrackBorderInGrid(Grid grid) + { + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++) + { + var child = VisualTreeHelper.GetChild(grid, i); + + if (child is Border border && border.Background != null) + { + var brush = border.Background as SolidColorBrush; + if (brush != null && brush.Color.ToString() == "#FFDEDEDE") + { + return border; + } + } + } + + return null; + } + + /// + /// 在Grid中查找值显示Border + /// + /// Grid控件 + /// 值显示Border + private Border FindValueBorderInGrid(Grid grid) + { + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++) + { + var child = VisualTreeHelper.GetChild(grid, i); + + if (child is Border border && border.Background != null) + { + var brush = border.Background as SolidColorBrush; + if (brush != null && brush.Color.ToString() == "#FF3584E4") + { + return border; + } + } + } + + return null; + } + + /// + /// 为自定义滑块控件添加触摸支持 + /// + /// 自定义滑块信息 + private void AddTouchSupportToCustomSlider(CustomSliderInfo customSlider) + { + if (customSlider?.Container == null) return; + + // 启用触摸和手写笔支持 + customSlider.Container.IsManipulationEnabled = true; + + // 添加触摸事件 + customSlider.Container.TouchDown += (s, e) => CustomSlider_TouchDown(s, e, customSlider); + customSlider.Container.TouchMove += (s, e) => CustomSlider_TouchMove(s, e, customSlider); + customSlider.Container.TouchUp += (s, e) => CustomSlider_TouchUp(s, e, customSlider); + + // 添加手写笔事件 + customSlider.Container.StylusDown += (s, e) => CustomSlider_StylusDown(s, e, customSlider); + customSlider.Container.StylusMove += (s, e) => CustomSlider_StylusMove(s, e, customSlider); + customSlider.Container.StylusUp += (s, e) => CustomSlider_StylusUp(s, e, customSlider); + + // 添加操作事件 + customSlider.Container.ManipulationStarted += (s, e) => CustomSlider_ManipulationStarted(s, e, customSlider); + customSlider.Container.ManipulationDelta += (s, e) => CustomSlider_ManipulationDelta(s, e, customSlider); + customSlider.Container.ManipulationCompleted += (s, e) => CustomSlider_ManipulationCompleted(s, e, customSlider); + } + + /// + /// 自定义滑块触摸按下事件处理 + /// + private void CustomSlider_TouchDown(object sender, TouchEventArgs e, CustomSliderInfo customSlider) + { + customSlider.Container.CaptureTouch(e.TouchDevice); + customSlider.IsTouchCaptured = true; + var touchPoint = e.GetTouchPoint(customSlider.Container); + UpdateCustomSliderValueFromPosition(customSlider, touchPoint.Position); + e.Handled = true; + } + + /// + /// 自定义滑块触摸移动事件处理 + /// + private void CustomSlider_TouchMove(object sender, TouchEventArgs e, CustomSliderInfo customSlider) + { + // 检查是否有触摸捕获 + if (!customSlider.IsTouchCaptured) return; + var touchPoint = e.GetTouchPoint(customSlider.Container); + UpdateCustomSliderValueFromPosition(customSlider, touchPoint.Position); + e.Handled = true; + } + + /// + /// 自定义滑块触摸释放事件处理 + /// + private void CustomSlider_TouchUp(object sender, TouchEventArgs e, CustomSliderInfo customSlider) + { + customSlider.Container.ReleaseTouchCapture(e.TouchDevice); + customSlider.IsTouchCaptured = false; + e.Handled = true; + } + + /// + /// 自定义滑块手写笔按下事件处理 + /// + private void CustomSlider_StylusDown(object sender, StylusDownEventArgs e, CustomSliderInfo customSlider) + { + customSlider.Container.CaptureStylus(); + var stylusPoint = e.GetStylusPoints(customSlider.Container); + if (stylusPoint.Count > 0) + { + UpdateCustomSliderValueFromPosition(customSlider, stylusPoint[0].ToPoint()); + } + e.Handled = true; + } + + /// + /// 自定义滑块手写笔移动事件处理 + /// + private void CustomSlider_StylusMove(object sender, StylusEventArgs e, CustomSliderInfo customSlider) + { + if (!customSlider.Container.IsStylusCaptured) return; + var stylusPoint = e.GetStylusPoints(customSlider.Container); + if (stylusPoint.Count > 0) + { + UpdateCustomSliderValueFromPosition(customSlider, stylusPoint[0].ToPoint()); + } + e.Handled = true; + } + + /// + /// 自定义滑块手写笔释放事件处理 + /// + private void CustomSlider_StylusUp(object sender, StylusEventArgs e, CustomSliderInfo customSlider) + { + customSlider.Container.ReleaseStylusCapture(); + e.Handled = true; + } + + /// + /// 自定义滑块操作开始事件处理 + /// + private void CustomSlider_ManipulationStarted(object sender, ManipulationStartedEventArgs e, CustomSliderInfo customSlider) + { + e.Handled = true; + } + + /// + /// 自定义滑块操作变化事件处理 + /// + private void CustomSlider_ManipulationDelta(object sender, ManipulationDeltaEventArgs e, CustomSliderInfo customSlider) + { + var manipulationOrigin = e.ManipulationOrigin; + UpdateCustomSliderValueFromPosition(customSlider, manipulationOrigin); + e.Handled = true; + } + + /// + /// 自定义滑块操作完成事件处理 + /// + private void CustomSlider_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e, CustomSliderInfo customSlider) + { + e.Handled = true; + } + + /// + /// 根据触摸/手写笔位置更新自定义滑块值 + /// + /// 自定义滑块信息 + /// 触摸/手写笔位置 + private void UpdateCustomSliderValueFromPosition(CustomSliderInfo customSlider, Point position) + { + if (customSlider?.TrackBorder == null || customSlider.ThumbImage == null) return; + + try + { + // 计算滑块轨道的实际位置和长度 + var trackWidth = customSlider.TrackBorder.ActualWidth; + if (trackWidth <= 0) return; + + // 计算相对位置(0-1之间) + var relativePosition = Math.Max(0, Math.Min(1, position.X / trackWidth)); + + // 更新滑块位置 + var thumbTransform = customSlider.ThumbImage.RenderTransform as TranslateTransform; + if (thumbTransform == null) + { + thumbTransform = new TranslateTransform(); + customSlider.ThumbImage.RenderTransform = thumbTransform; + } + + // 计算新的滑块位置 + var newX = relativePosition * trackWidth; + thumbTransform.X = newX; + + // 更新值显示Border的宽度 + if (customSlider.ValueBorder != null) + { + var valueWidth = relativePosition * trackWidth; + customSlider.ValueBorder.Width = Math.Max(0, valueWidth); + + // 调整值显示Border的位置 + var valueMargin = customSlider.ValueBorder.Margin; + customSlider.ValueBorder.Margin = new Thickness(0, valueMargin.Top, trackWidth - valueWidth, valueMargin.Bottom); + } + + // 这里可以根据需要添加值变化事件处理 + // 例如:OnCustomSliderValueChanged(customSlider, relativePosition); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"更新自定义滑块值时出错: {ex.Message}"); + } + } + + /// + /// 自定义滑块信息类 + /// + private class CustomSliderInfo + { + public Grid Container { get; set; } + public Image ThumbImage { get; set; } + public Border TrackBorder { get; set; } + public Border ValueBorder { get; set; } + public bool IsTouchCaptured { get; set; } = false; + } + + #endregion } }