2013-02-06 9 views
14

के अनुसार समायोजित करना मैंने अपने मुद्दे को प्रदर्शित करने के लिए एक सरल 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 जोड़ लिया है।

App

आप पर एक बॉक्स आकर्षित कर सकते हैं: यदि आप इस चलाते हैं, और myImage.png की जगह अपने कंप्यूटर पर एक वास्तविक छवि के स्थान के साथ हैं, तो आप एक आवेदन है कि कुछ इस तरह दिखता मिलेगा जहां आप बॉक्स को जाना चाहते हैं, उस शीर्ष-बाईं ओर क्लिक करके छवि जहां आप बॉक्स को जाना चाहते हैं, नीचे दाईं ओर खींचकर, आपको एक लाल आयताकार मिलता है। आप मध्य-माउस के साथ भी ज़ूम इन कर सकते हैं, और अधिक परिशुद्धता के लिए एक आयत खींच सकते हैं, यह अपेक्षा के अनुसार काम करता है।

समस्या यह है कि, जब आप मध्य माउस के साथ स्क्रॉल करते हैं, तो स्क्रॉल बार फिर से समायोजित नहीं होते हैं, जो कि मैं बना रहा प्रोग्राम की आवश्यकता है। मेरा सवाल यह है कि जब मैं ज़ूम इन करता हूं तो स्क्रोलवॉयर पर स्क्रॉलबार को फिर से समायोजित करने के लिए कैसे मजबूर करता हूं?

मुझे विश्वास है कि स्क्रॉल व्यूअर की रेंडरट्रांसफॉर्म प्रॉपर्टी के साथ इसका कुछ संबंध है, और मुझे इसे अपडेट करने की आवश्यकता है, उसी समय मैं छवि की रेंडरट्रांसफॉर्म प्रॉपर्टी अपडेट करता हूं (UIElement_OnMouseWheel पर) लेकिन मुझे बिल्कुल ठीक नहीं है इसके बारे में जाने के लिए।

उत्तर

18

आप अपनी छवि पर LayoutTransform बजाय RenderTransform का उपयोग करना चाहिए।

RenderTransform लेआउट पूर्ण होने के बाद होता है और केवल दृश्य है। LayoutTransform लेआउट पास से पहले किया जाता है और इसलिए नए आकार के ScrollViewer को सूचित कर सकता है।

अधिक जानकारी के लिए यहाँ देखें: http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.layouttransform.aspx

+2

पूरी तरह से काम करता है, धन्यवाद! – JMK

5

शुद्ध स्क्रॉलिंग के लिए मैं स्केलट्रांसफॉर्म का उपयोग करना चाहता हूं, इसके अनुसार स्क्रॉलबार को समायोजित करना चाहिए। यदि आप अपनी समस्या को हल करते हैं तो आप कोड से नीचे आज़मा सकते हैं।

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

चलो तुम एक ViewBox_CanvasMain, अंदर एक Canvas_Main है मान लेते हैं जो एक ScrollViewer_CanvasMain अंदर बदले में। आप माउस व्हील को चालू करके ज़ूम इन करना चाहते हैं, और स्क्रॉलव्यूयर ऑफसेट को स्वचालित रूप से समायोजित करेगा ताकि सुविधा (कैनवास_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; 
     } 


    } 
संबंधित मुद्दे