7

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>

これらのコントロールのうちの2つは、次のようにウィンドウのグリッドに含まれています。

    <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に注意を向けさせるにはどうすればよいですか?

4

2 に答える 2

21

Canvas は、他の要素のようにレイアウト システムに実際には参加しないという点で、一種のユニークな要素です。基本的に、固定位置の子を持つ無限サイズのスペースとして機能するため、通常、クリッピングは完全に無視されます。コードをもっと見ないとはっきりとは言えませんが、スケーリングされたオブジェクトにクリッピングを適用したい場合は、スケーリングを別の要素に移動すると、あなたが望むことができるかもしれません。最も簡単な方法は、キャンバスの周りに Border をラップし、代わりに ScaleTransform を適用することです。Border を使用すると、クリッピング動作が改善されます。

<Border x:Name="border" Background="Black" ClipToBounds="True">
    <Canvas x:Name="imageHost">
    ...
    </Canvas>
</Border>
于 2011-07-13T23:56:54.337 に答える