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
}
}