2013-02-06 9 views
14

Ho creato una semplice applicazione WPF per dimostrare il problema che sto riscontrando. Il mio XAML è qui sotto:WPF - Ingrandimento di un'immagine all'interno di un visualizzatore di pergamene e il dover regolare le barre di scorrimento

<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> 

Il code-behind è qui sotto:

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; 
     } 
    } 
} 

Ho aggiunto WriteableBitmapEx utilizzando Nuget. Se si esegue questo, e sostituire myImage.png con la posizione di un'immagine reale sul vostro computer, troverete un'applicazione che sembra qualcosa di simile:

App

È possibile disegnare una scatola sul immagine facendo clic sulla parte in alto a sinistra di dove vuoi che la casella vada e trascinando in basso a destra dove vuoi che la casella vada, ottieni un rettangolo rosso. Puoi anche ingrandire con il middle-mouse e disegnare un rettangolo da vicino per una maggiore precisione, questo funziona come previsto.

Il problema è che, quando si scorre con il mouse centrale, le barre di scorrimento non si regolano nuovamente, il che è un requisito del programma che sto creando. La mia domanda è: come posso forzare le barre di scorrimento sullo scrollviewer per riaggiustare quando l'immagine viene ingrandita?

Sono convinto che abbia qualcosa a che fare con la proprietà RenderTransform di ScrollViewer e che ho bisogno di aggiornarlo mentre aggiorno la proprietà RenderTransform dell'immagine (su UIElement_OnMouseWheel) ma non sono sicuro di come per andare su questo.

risposta

5

Per lo scrolling puro preferirei usare un ScaleTransform, dovrebbe regolare di conseguenza le barre di scorrimento. Puoi provare codice qui sotto se risolve il tuo problema.

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

Si ipotizzi di avere un Canvas_Main all'interno di un ViewBox_CanvasMain, che a sua volta all'interno di uno ScrollViewer_CanvasMain. Si desidera ingrandire ruotando la rotellina del mouse e ScrollViewer regola automaticamente l'offset in modo che la funzione (puntata dal mouse in Canvas_Main) rimanga durante lo zoom in/out. È complesso, ma qui è il codice chiamato dal gestore della rotella del mouse:

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; 
     } 


    } 
Problemi correlati