使用像素尺寸,避免DPI不同导致DIP尺寸与实际像素不一致

This commit is contained in:
李伟
2026-04-23 16:52:10 +08:00
parent 3aa64843c8
commit d5b421b811
2 changed files with 40 additions and 43 deletions
@@ -17,28 +17,20 @@
</UserControl.Resources>
<Border BorderBrush="Transparent" BorderThickness="1" ClipToBounds="True">
<Grid>
<!-- 图像显示区域(去掉左侧按钮列,全部空间给图像) -->
<!-- 图像显示区域 -->
<Grid x:Name="imageDisplayGrid" ClipToBounds="True">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="放大" Click="BtnZoomIn_Click" />
<MenuItem Header="缩小" Click="BtnZoomOut_Click" />
<MenuItem Header="适应窗口" Click="BtnReset_Click" />
</ContextMenu>
</Grid.ContextMenu>
<Grid x:Name="transformGrid"
RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RenderTransform>
<TransformGroup>
<Grid.LayoutTransform>
<ScaleTransform x:Name="scaleTransform"
ScaleX="{Binding ZoomScale, ElementName=root}"
ScaleY="{Binding ZoomScale, ElementName=root}" />
</Grid.LayoutTransform>
<Grid.RenderTransform>
<TranslateTransform x:Name="translateTransform"
X="{Binding PanOffsetX, ElementName=root}"
Y="{Binding PanOffsetY, ElementName=root}" />
</TransformGroup>
</Grid.RenderTransform>
<Canvas x:Name="mainCanvas"
@@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace XP.ImageProcessing.RoiControl.Controls
@@ -120,11 +121,17 @@ namespace XP.ImageProcessing.RoiControl.Controls
private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (PolygonRoiCanvas)d;
if (e.NewValue is ImageSource imageSource)
if (e.NewValue is BitmapSource bitmap)
{
// 使用像素尺寸,避免 DPI 不同导致 DIP 尺寸与实际像素不一致
control.CanvasWidth = bitmap.PixelWidth;
control.CanvasHeight = bitmap.PixelHeight;
control.ResetView();
}
else if (e.NewValue is ImageSource imageSource)
{
control.CanvasWidth = imageSource.Width;
control.CanvasHeight = imageSource.Height;
// 图像加载后自动适应窗口居中显示
control.ResetView();
}
}
@@ -411,35 +418,33 @@ namespace XP.ImageProcessing.RoiControl.Controls
public void ResetView()
{
// 自动适应显示窗口 (类似 PictureBox SizeMode.Zoom)
ZoomScale = 1.0;
PanOffsetX = 0;
PanOffsetY = 0;
if (imageDisplayGrid != null && CanvasWidth > 0 && CanvasHeight > 0)
if (imageDisplayGrid == null || CanvasWidth <= 0 || CanvasHeight <= 0)
{
// 使用 Dispatcher 延迟执行,确保布局已完成
ZoomScale = 1.0;
return;
}
// 延迟到布局完成后计算,确保 ActualWidth/Height 准确
Dispatcher.BeginInvoke(new Action(() =>
{
// 获取图像显示区域的实际尺寸
double viewportWidth = imageDisplayGrid.ActualWidth;
double viewportHeight = imageDisplayGrid.ActualHeight;
double viewW = imageDisplayGrid.ActualWidth;
double viewH = imageDisplayGrid.ActualHeight;
if (viewportWidth > 0 && viewportHeight > 0)
if (viewW > 0 && viewH > 0)
{
// 计算宽度和高度的缩放比例
double scaleX = viewportWidth / CanvasWidth;
double scaleY = viewportHeight / CanvasHeight;
ZoomScale = Math.Min(viewW / CanvasWidth, viewH / CanvasHeight);
}
else
{
ZoomScale = 1.0;
}
// 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比)
ZoomScale = Math.Min(scaleX, scaleY);
// 居中显示由 Grid 的 HorizontalAlignment 和 VerticalAlignment 自动处理
PanOffsetX = 0;
PanOffsetY = 0;
}
}), System.Windows.Threading.DispatcherPriority.Loaded);
}
}), System.Windows.Threading.DispatcherPriority.Render);
}
private void BtnZoomIn_Click(object sender, RoutedEventArgs e)