26

私が抱えている問題を示すために、簡単なWPFアプリケーションをまとめました。私のXAMLは以下のとおりです。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="427" Width="467" Loaded="MainWindow_OnLoaded">
    <Grid>
        <ScrollViewer Name="MyScrollViewer" CanContentScroll="True">
            <Image Name="MyImage" HorizontalAlignment="Left" VerticalAlignment="Top" MouseWheel="UIElement_OnMouseWheel" MouseDown="MyImage_OnMouseDown" MouseUp="MyImage_OnMouseUp"/>
        </ScrollViewer>
    </Grid>
</Window>

コードビハインドは以下のとおりです。

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void UIElement_OnMouseWheel(object sender, MouseWheelEventArgs e)
        {
            var matrix = MyImage.RenderTransform.Value;

            if (e.Delta > 0)
            {
                matrix.ScaleAt(1.5, 1.5, e.GetPosition(this).X, e.GetPosition(this).Y);
            }
            else
            {
                matrix.ScaleAt(1.0 / 1.5, 1.0 / 1.5, e.GetPosition(this).X, e.GetPosition(this).Y);
            }

            MyImage.RenderTransform = new MatrixTransform(matrix);
        }

        private WriteableBitmap writeableBitmap;

        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            var image = new WriteableBitmap(new BitmapImage(new Uri(@"C:\myImage.png", UriKind.Absolute)));

            MyImage.Width = image.Width;
            MyImage.Height = image.Height;

            image = BitmapFactory.ConvertToPbgra32Format(image);

            writeableBitmap = image;

            MyImage.Source = image;
        }

        private Point downPoint;
        private Point upPoint;

        private void MyImage_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            downPoint = e.GetPosition(MyImage);
        }

        private void MyImage_OnMouseUp(object sender, MouseButtonEventArgs e)
        {
            upPoint = e.GetPosition(MyImage);

            writeableBitmap.DrawRectangle(Convert.ToInt32(downPoint.X), Convert.ToInt32(downPoint.Y), Convert.ToInt32(upPoint.X), Convert.ToInt32(upPoint.Y), Colors.Red);
            MyImage.Source = writeableBitmap;
        }
    }
}

Nugetを使用してWriteableBitmapExを追加しました。これを実行し、myImage.pngをコンピューター上の実際の画像の場所に置き換えると、次のようなアプリケーションが見つかります。

アプリ

ボックスを移動する場所の左上をクリックし、ボックスを移動する場所の右下にドラッグすると、画像上にボックスを描画できます。赤い長方形が表示されます。真ん中のマウスでズームインしたり、長方形を近づけてより正確に描画したりすることもできます。これは期待どおりに機能します。

問題は、中マウスでスクロールすると、スクロールバーが再調整されないことです。これは、私が作成しているプログラムの要件です。私の質問は、画像が拡大されたときに、scrollviewerのスクロールバーを強制的に再調整するにはどうすればよいですか?

ScrollViewerのRenderTransformプロパティと関係があり、画像のRenderTransformプロパティ(UIElement_OnMouseWheel上)を更新すると同時に更新する必要があると確信していますが、これをどのように行うのか正確にはわかりません。 。

4

3 に答える 3

29

LayoutTransform画像ではなくを使用する必要がありRenderTransformます。

RenderTransformレイアウトが完了した後に発生し、視覚のみです。LayoutTransformレイアウトパスの前に行われるためScrollViewer、新しいサイズを通知できます。

詳細については、こちらを参照してください:http: //msdn.microsoft.com/en-us/library/system.windows.frameworkelement.layouttransform.aspx

于 2013-02-06T13:52:08.657 に答える
9

純粋なスクロールの場合は、ScaleTransformを使用したいので、それに応じてスクロールバーを調整する必要があります。問題が解決した場合は、以下のコードを試すことができます。

private double _zoomValue = 1.0;

private void UIElement_OnMouseWheel(object sender, MouseWheelEventArgs e)
{
  if (e.Delta > 0)
  {
    _zoomValue += 0.1;
  }
  else
  {
    _zoomValue -= 0.1;
  }

  ScaleTransform scale = new ScaleTransform(_zoomValue, _zoomValue);
  MyImage.LayoutTransform = scale;
  e.Handled = true;
}
于 2013-02-06T13:51:39.783 に答える
7

ViewBox_CanvasMain内にCanvas_Mainがあり、それがScrollViewer_CanvasMain内にあると仮定します。マウスホイールを回してズームインすると、ScrollViewerがオフセットを自動的に調整して、ズームイン/ズームアウト中に機能(Canvas_Mainでマウスが指している)が維持されるようにします。複雑ですが、マウスホイールのイベントハンドラーによって呼び出されるコードは次のとおりです。

    private void MouseWheelZoom(MouseWheelEventArgs e)
    {
        if(Canvas_Main.IsMouseOver)
        {

            Point mouseAtImage = e.GetPosition(Canvas_Main); // ScrollViewer_CanvasMain.TranslatePoint(middleOfScrollViewer, Canvas_Main);
            Point mouseAtScrollViewer = e.GetPosition(ScrollViewer_CanvasMain);

            ScaleTransform st = ViewBox_CanvasMain.LayoutTransform as ScaleTransform;
            if (st == null)
            {
                st = new ScaleTransform();
                ViewBox_CanvasMain.LayoutTransform = st;
            }

            if (e.Delta > 0)
            {
                st.ScaleX = st.ScaleY = st.ScaleX * 1.25;
                if (st.ScaleX > 64) st.ScaleX = st.ScaleY = 64;
            }
            else
            {
                st.ScaleX = st.ScaleY = st.ScaleX / 1.25;
                if (st.ScaleX < 1) st.ScaleX = st.ScaleY = 1;
            }
            #region [this step is critical for offset]
            ScrollViewer_CanvasMain.ScrollToHorizontalOffset(0);
            ScrollViewer_CanvasMain.ScrollToVerticalOffset(0);
            this.UpdateLayout();
            #endregion

            Vector offset = Canvas_Main.TranslatePoint(mouseAtImage, ScrollViewer_CanvasMain) - mouseAtScrollViewer; // (Vector)middleOfScrollViewer;
            ScrollViewer_CanvasMain.ScrollToHorizontalOffset(offset.X);
            ScrollViewer_CanvasMain.ScrollToVerticalOffset(offset.Y);
            this.UpdateLayout();

            e.Handled = true;
        }


    }
于 2014-11-04T22:53:26.020 に答える