2013-02-06 37 views
14

Tôi đã kết hợp một ứng dụng WPF đơn giản để minh họa sự cố tôi đang gặp phải. XAML của tôi là dưới đây:WPF - Phóng to hình ảnh bên trong trình xem cuộn và có các thanh cuộn điều chỉnh cho phù hợp

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

code-behind là dưới đây:

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

Tôi đã thêm WriteableBitmapEx sử dụng NuGet. Nếu bạn chạy này, và thay thế myImage.png với vị trí của một hình ảnh thực tế trên máy tính của bạn, bạn sẽ tìm thấy một ứng dụng mà trông giống như sau:

App

Bạn có thể vẽ một hộp trên hình ảnh bằng cách nhấp vào trên cùng bên trái của nơi bạn muốn hộp để đi và kéo xuống phía dưới bên phải của nơi bạn muốn hộp để đi, bạn sẽ có được một hình chữ nhật màu đỏ. Bạn thậm chí có thể phóng to bằng chuột giữa và vẽ hình chữ nhật gần hơn để chính xác hơn, điều này hoạt động như mong đợi.

Vấn đề là khi bạn cuộn chuột giữa, thanh cuộn không điều chỉnh lại, đó là yêu cầu của chương trình tôi đang tạo. Câu hỏi của tôi là làm cách nào để buộc thanh cuộn trên scrollviewer điều chỉnh lại khi hình ảnh được phóng to?

Tôi tin rằng nó có liên quan đến thuộc tính RenderTransform của ScrollViewer và tôi cần cập nhật nó cùng lúc tôi cập nhật thuộc tính RenderTransform của hình ảnh (trên UIElement_OnMouseWheel) nhưng tôi không chắc chắn về cách chính xác để đi về điều này.

Trả lời

18

Bạn nên sử dụng LayoutTransform thay vì RenderTransform trên hình ảnh của mình.

RenderTransform xảy ra sau khi bố cục hoàn tất và chỉ hiển thị. LayoutTransform được thực hiện trước khi vượt qua bố cục và do đó có thể thông báo cho ScrollViewer về kích thước mới.

Xem ở đây để biết thêm: http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.layouttransform.aspx

+2

Hoạt động hoàn hảo, cảm ơn! – JMK

5

Để cuộn tinh khiết, tôi muốn sử dụng ScaleTransform hơn, nó sẽ điều chỉnh thanh cuộn cho phù hợp. Bạn có thể thử mã dưới đây nếu nó sửa lỗi của bạn.

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

Giả sử bạn có một Canvas_Main bên trong một ViewBox_CanvasMain, do đó bên trong một ScrollViewer_CanvasMain. Bạn muốn phóng to bằng cách xoay bánh xe chuột và ScrollViewer sẽ tự động điều chỉnh độ lệch sao cho tính năng (được chỉ bằng chuột trong Canvas_Main) ở lại trong khi phóng to/thu nhỏ. Nó phức tạp nhưng đây là mã được gọi bởi tổ chức sự kiện bánh xe chuột:

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


    } 
Các vấn đề liên quan