我有一个应用程序在WPF中的Image对象内显示图像。图像包含在xaml看起来像的控件中:
<UserControl x:Class="MyProgram.NativeImageDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="UserControl_Loaded">
<Canvas Name="border" Background="Black" >
<Image Name="image" StretchDirection="Both" Stretch="Uniform" ClipToBounds="True"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="HighQuality"></Image>
</Canvas>
</UserControl>
其中两个控件包含在窗口的网格中,如下所示:
<Grid Grid.Row="2" Name="DisplayCanvas">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<l:NativeImageDisplay x:Name="imageDisplay2" Grid.Column="1" ClipToBounds="True"/>
<l:NativeImageDisplay x:Name="imageDisplay" Grid.Column="0" ClipToBounds="True"/>
</Grid>
我在这里一直称裁剪是真的。
用户可以使用鼠标上的滚动按钮放大图像,最终调用图像上的ScaleTransform:
private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (!thumbnail)
{
TransformGroup transformGroup = (TransformGroup)border.RenderTransform;
ScaleTransform transform = (ScaleTransform)transformGroup.Children[0];
double oldScaleX = transform.ScaleX;
double oldScaleY = transform.ScaleY;
double zoom = e.Delta;
transform.ScaleX += zoom / 10000;
transform.ScaleY += zoom / 10000;
if (transform.ScaleX > maxZoom || transform.ScaleY > maxZoom)
{
transform.ScaleX = maxZoom;
transform.ScaleY = maxZoom;
}
if (transform.ScaleX < minZoom || transform.ScaleY < minZoom)
{
transform.ScaleX = minZoom;
transform.ScaleY = minZoom;
}
Point thePoint = e.GetPosition(border);
transform.CenterY = 0;
transform.CenterX = 0;
foreach (UIElement child in border.Children)
{
if (child is Anchor)
{
TransformGroup group = (TransformGroup)child.RenderTransform;
ScaleTransform t = (ScaleTransform)group.Children[0];
t.ScaleX *= oldScaleX / transform.ScaleX;
t.ScaleY *= oldScaleY / transform.ScaleY;
}
}
}
}
调用该缩放变换后,图像不再包含在其画布边界或网格选择中。基本上,ClipToBounds被忽略了。如何让这个转换关注ClipToBounds?
答案 0 :(得分:19)
Canvas有点独特之处在于它并不像其他元素那样真正参与布局系统。它基本上充当无限大小的空间,具有固定位置的孩子,因此通常完全忽略剪裁。如果没有看到更多的代码,我无法确定,但如果你想将剪裁应用于缩放对象,将缩放移动到另一个元素可能会做你想要的。最简单的方法是在Canvas周围包裹一个Border,然后将ScaleTransform应用于它。边框应该给你更好的剪裁行为。
<Border x:Name="border" Background="Black" ClipToBounds="True">
<Canvas x:Name="imageHost">
...
</Canvas>
</Border>
答案 1 :(得分:0)
以上评论帮助我。将一个画布嵌套在另一个画布中,将ClipToBounds="True"
添加到父画布,并将嵌套的高度和宽度分别绑定到父属性。
这样就无需在父级上执行转换。
<Canvas ClipToBounds="True" Name="Outer">
<Canvas x:Name="Inner"
Height="{Binding ActualHeight, ElementName=Outer, Mode=OneWay}"
Width="{Binding ActualWidth, ElementName=Outer, Mode=OneWay}" />
</Canvas>