使用像素尺寸,避免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> </UserControl.Resources>
<Border BorderBrush="Transparent" BorderThickness="1" ClipToBounds="True"> <Border BorderBrush="Transparent" BorderThickness="1" ClipToBounds="True">
<Grid> <Grid>
<!-- 图像显示区域(去掉左侧按钮列,全部空间给图像) --> <!-- 图像显示区域 -->
<Grid x:Name="imageDisplayGrid" ClipToBounds="True"> <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" <Grid x:Name="transformGrid"
RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center"> VerticalAlignment="Center">
<Grid.LayoutTransform>
<ScaleTransform x:Name="scaleTransform"
ScaleX="{Binding ZoomScale, ElementName=root}"
ScaleY="{Binding ZoomScale, ElementName=root}" />
</Grid.LayoutTransform>
<Grid.RenderTransform> <Grid.RenderTransform>
<TransformGroup> <TranslateTransform x:Name="translateTransform"
<ScaleTransform x:Name="scaleTransform" X="{Binding PanOffsetX, ElementName=root}"
ScaleX="{Binding ZoomScale, ElementName=root}" Y="{Binding PanOffsetY, ElementName=root}" />
ScaleY="{Binding ZoomScale, ElementName=root}" />
<TranslateTransform x:Name="translateTransform"
X="{Binding PanOffsetX, ElementName=root}"
Y="{Binding PanOffsetY, ElementName=root}" />
</TransformGroup>
</Grid.RenderTransform> </Grid.RenderTransform>
<Canvas x:Name="mainCanvas" <Canvas x:Name="mainCanvas"
@@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace XP.ImageProcessing.RoiControl.Controls namespace XP.ImageProcessing.RoiControl.Controls
@@ -120,11 +121,17 @@ namespace XP.ImageProcessing.RoiControl.Controls
private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
var control = (PolygonRoiCanvas)d; 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.CanvasWidth = imageSource.Width;
control.CanvasHeight = imageSource.Height; control.CanvasHeight = imageSource.Height;
// 图像加载后自动适应窗口居中显示
control.ResetView(); control.ResetView();
} }
} }
@@ -411,35 +418,33 @@ namespace XP.ImageProcessing.RoiControl.Controls
public void ResetView() public void ResetView()
{ {
// 自动适应显示窗口 (类似 PictureBox SizeMode.Zoom)
ZoomScale = 1.0;
PanOffsetX = 0; PanOffsetX = 0;
PanOffsetY = 0; PanOffsetY = 0;
if (imageDisplayGrid != null && CanvasWidth > 0 && CanvasHeight > 0) if (imageDisplayGrid == null || CanvasWidth <= 0 || CanvasHeight <= 0)
{ {
// 使用 Dispatcher 延迟执行,确保布局已完成 ZoomScale = 1.0;
Dispatcher.BeginInvoke(new Action(() => return;
{
// 获取图像显示区域的实际尺寸
double viewportWidth = imageDisplayGrid.ActualWidth;
double viewportHeight = imageDisplayGrid.ActualHeight;
if (viewportWidth > 0 && viewportHeight > 0)
{
// 计算宽度和高度的缩放比例
double scaleX = viewportWidth / CanvasWidth;
double scaleY = viewportHeight / CanvasHeight;
// 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比)
ZoomScale = Math.Min(scaleX, scaleY);
// 居中显示由 Grid 的 HorizontalAlignment 和 VerticalAlignment 自动处理
PanOffsetX = 0;
PanOffsetY = 0;
}
}), System.Windows.Threading.DispatcherPriority.Loaded);
} }
// 延迟到布局完成后计算,确保 ActualWidth/Height 准确
Dispatcher.BeginInvoke(new Action(() =>
{
double viewW = imageDisplayGrid.ActualWidth;
double viewH = imageDisplayGrid.ActualHeight;
if (viewW > 0 && viewH > 0)
{
ZoomScale = Math.Min(viewW / CanvasWidth, viewH / CanvasHeight);
}
else
{
ZoomScale = 1.0;
}
PanOffsetX = 0;
PanOffsetY = 0;
}), System.Windows.Threading.DispatcherPriority.Render);
} }
private void BtnZoomIn_Click(object sender, RoutedEventArgs e) private void BtnZoomIn_Click(object sender, RoutedEventArgs e)