2013-02-06 3 views
14

シンプルなWPFアプリケーションを使用して、私が抱えている問題を実証しました。私のXAMLは以下の通りです:WPF - スクロールビューアー内の画像をズームインし、それに応じてスクロールバーを調整する

<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を追加しました。あなたは上のボックスを描画することができます

App

:あなたはこれを実行し、コンピュータ上の実際の画像の位置がmyImage.pngを交換する場合は、次のようになりますアプリケーションを見つけるだろうボックスを移動したい場所の左上をクリックし、ボックスを移動する場所の右下にドラッグすると、赤い四角形が表示されます。中マウスを使用してズームインしたり、より正確にするために四角形を近づけたりすることもできます。これは期待どおりに機能します。

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

ScrollViewerのRenderTransformプロパティと関係があり、UIElement_OnMouseWheelのイメージのRenderTransformプロパティを更新すると同時に更新する必要があると確信していますが、これについて行く。

答えて

18

あなたはあなたのイメージにLayoutTransformの代わりRenderTransformを使用する必要があります。

RenderTransformは、レイアウトの完了後に発生し、視覚的にのみ表示されます。レイアウトパスの前にLayoutTransformが完了したので、新しいサイズのScrollViewerを通知することができます。

詳細はこちらをご覧ください:http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.layouttransform.aspx

+2

完璧に、よかった! – JMK

5

純粋なスクロールでは、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; 
} 
3

は、あなたが順番にScrollViewer_CanvasMain内部ViewBox_CanvasMain、内部Canvas_Mainを持っていると仮定しましょう。マウスホイールを回してズームインしたい場合、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; 
     } 


    } 
関連する問題