From 7f2dd8f8229e85145a8458bd7832b28d0c1f469a Mon Sep 17 00:00:00 2001 From: "zhengxuan.zhang" Date: Tue, 30 Jun 2026 13:51:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=9E=E6=97=B6=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=E5=9B=BE=E5=83=8F=E9=A2=84=E8=A7=88=E5=8C=BA?= =?UTF-8?q?=E4=BB=8D=E5=8F=AF=E6=8B=96=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B=E9=9D=9E=E5=AE=9E=E6=97=B6=E6=A8=A1=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E8=B7=9F=E9=9A=8F=E8=93=9D=E8=89=B2=E5=8D=81?= =?UTF-8?q?=E5=AD=97=E7=BA=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controls/PolygonRoiCanvas.xaml.cs | 22 ++++- .../ViewModels/Main/ViewportPanelViewModel.cs | 7 ++ XplorePlane/Views/Main/ViewportPanelView.xaml | 8 +- .../Views/Main/ViewportPanelView.xaml.cs | 88 +++++++++++++++++++ 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs b/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs index 3e7460b0..d5267d5a 100644 --- a/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs +++ b/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs @@ -190,6 +190,20 @@ namespace XP.ImageProcessing.RoiControl.Controls set => SetValue(IsWheelZoomEnabledProperty, value); } + /// + /// 是否允许拖动画布平移图像(默认允许)。 + /// 实时图像显示过程中可设为 false 以禁止图像拖动。 + /// + public static readonly DependencyProperty IsImagePanEnabledProperty = + DependencyProperty.Register(nameof(IsImagePanEnabled), typeof(bool), typeof(PolygonRoiCanvas), + new PropertyMetadata(true)); + + public bool IsImagePanEnabled + { + get => (bool)GetValue(IsImagePanEnabledProperty); + set => SetValue(IsImagePanEnabledProperty, value); + } + public static readonly DependencyProperty PanOffsetXProperty = DependencyProperty.Register(nameof(PanOffsetX), typeof(double), typeof(PolygonRoiCanvas), new PropertyMetadata(0.0, OnPanOffsetChanged)); @@ -2355,6 +2369,10 @@ namespace XP.ImageProcessing.RoiControl.Controls lastMousePosition = e.GetPosition(imageDisplayGrid); isDragging = false; + if (!IsImagePanEnabled) + { + return; + } mainCanvas.CaptureMouse(); } @@ -2447,7 +2465,7 @@ namespace XP.ImageProcessing.RoiControl.Controls return; } - if (e.LeftButton == MouseButtonState.Pressed && mainCanvas.IsMouseCaptured) + if (IsImagePanEnabled && e.LeftButton == MouseButtonState.Pressed && mainCanvas.IsMouseCaptured) { Point currentPosition = e.GetPosition(imageDisplayGrid); Vector delta = currentPosition - lastMousePosition; @@ -2733,4 +2751,4 @@ namespace XP.ImageProcessing.RoiControl.Controls #endregion Events } -} \ No newline at end of file +} diff --git a/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs b/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs index b5180e37..d926a43a 100644 --- a/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs +++ b/XplorePlane/ViewModels/Main/ViewportPanelViewModel.cs @@ -131,6 +131,7 @@ using XP.Common.Controls.ImageHistogram; { _mainViewportService.SetRealtimeDisplayEnabled(value); RaisePropertyChanged(nameof(IsWheelZoomEnabled)); + RaisePropertyChanged(nameof(IsImagePanEnabled)); } } } @@ -140,6 +141,11 @@ using XP.Common.Controls.ImageHistogram; /// public bool IsWheelZoomEnabled => !_isRealtimeEnabled; + /// + /// 是否允许拖动图像:实时显示过程中禁用,停止实时后可拖动。 + /// + public bool IsImagePanEnabled => !_isRealtimeEnabled; + // Task 5.3: IsDetectorConnected property (read-only, private setter) public bool IsDetectorConnected { @@ -322,6 +328,7 @@ using XP.Common.Controls.ImageHistogram; _isRealtimeEnabled = _mainViewportService.IsRealtimeDisplayEnabled; RaisePropertyChanged(nameof(IsRealtimeEnabled)); RaisePropertyChanged(nameof(IsWheelZoomEnabled)); + RaisePropertyChanged(nameof(IsImagePanEnabled)); // Task 5.8: Sync _isCncRunning from service and raise IsAnimatedSwitchEnabled _isCncRunning = _mainViewportService.IsCncRunning; diff --git a/XplorePlane/Views/Main/ViewportPanelView.xaml b/XplorePlane/Views/Main/ViewportPanelView.xaml index 7e892fc8..343bece3 100644 --- a/XplorePlane/Views/Main/ViewportPanelView.xaml +++ b/XplorePlane/Views/Main/ViewportPanelView.xaml @@ -31,10 +31,11 @@ Text="实时图像" /> - + @@ -66,6 +67,11 @@ IsHitTestVisible="False" Visibility="Collapsed" /> + + + UpdateHistogramFromCurrentImage(); @@ -568,6 +569,88 @@ namespace XplorePlane.Views #endregion + #region 鼠标跟随蓝色十字线 + + private System.Windows.Shapes.Line _mouseCrosshairH; + private System.Windows.Shapes.Line _mouseCrosshairV; + + /// + /// 初始化鼠标跟随十字线(在构造函数中调用)。 + /// + private void InitializeMouseCrosshair() + { + var brush = new SolidColorBrush(Color.FromArgb(200, 0, 120, 255)); + brush.Freeze(); + + _mouseCrosshairH = new System.Windows.Shapes.Line + { + Stroke = brush, + StrokeThickness = 1, + IsHitTestVisible = false, + SnapsToDevicePixels = true + }; + + _mouseCrosshairV = new System.Windows.Shapes.Line + { + Stroke = brush, + StrokeThickness = 1, + IsHitTestVisible = false, + SnapsToDevicePixels = true + }; + + MouseCrosshairOverlay.Children.Add(_mouseCrosshairH); + MouseCrosshairOverlay.Children.Add(_mouseCrosshairV); + + // 在图像区域 Grid 上监听鼠标事件 + ImageAreaGrid.MouseMove += OnImageAreaMouseMove; + ImageAreaGrid.MouseLeave += OnImageAreaMouseLeave; + } + + private void OnImageAreaMouseMove(object sender, System.Windows.Input.MouseEventArgs e) + { + var vm = DataContext as ViewportPanelViewModel; + if (vm == null || vm.IsRealtimeEnabled) + { + MouseCrosshairOverlay.Visibility = Visibility.Collapsed; + return; + } + + MouseCrosshairOverlay.Visibility = Visibility.Visible; + + var pos = e.GetPosition(ImageAreaGrid); + double w = ImageAreaGrid.ActualWidth; + double h = ImageAreaGrid.ActualHeight; + + _mouseCrosshairH.X1 = 0; + _mouseCrosshairH.Y1 = pos.Y; + _mouseCrosshairH.X2 = w; + _mouseCrosshairH.Y2 = pos.Y; + + _mouseCrosshairV.X1 = pos.X; + _mouseCrosshairV.Y1 = 0; + _mouseCrosshairV.X2 = pos.X; + _mouseCrosshairV.Y2 = h; + } + + private void OnImageAreaMouseLeave(object sender, System.Windows.Input.MouseEventArgs e) + { + MouseCrosshairOverlay.Visibility = Visibility.Collapsed; + } + + /// + /// 当 IsRealtimeEnabled 变化时,隐藏鼠标十字线(开启实时后不再显示)。 + /// + private void OnRealtimeStateChangedForMouseCrosshair() + { + var vm = DataContext as ViewportPanelViewModel; + if (vm != null && vm.IsRealtimeEnabled) + { + MouseCrosshairOverlay.Visibility = Visibility.Collapsed; + } + } + + #endregion + private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { AttachHistogramViewModel(e.NewValue as INotifyPropertyChanged); @@ -596,6 +679,11 @@ namespace XplorePlane.Views { UpdateHistogramFromCurrentImage(); } + + if (e.PropertyName == nameof(ViewportPanelViewModel.IsRealtimeEnabled)) + { + OnRealtimeStateChangedForMouseCrosshair(); + } } private void UpdateHistogramFromCurrentImage()