Skip to content

Instantly share code, notes, and snippets.

@earthengine
Last active September 17, 2016 14:14
Show Gist options
  • Save earthengine/0a6825379204addf0313a010c3d8877c to your computer and use it in GitHub Desktop.
Save earthengine/0a6825379204addf0313a010c3d8877c to your computer and use it in GitHub Desktop.
A WPF control that can zoom in and positioning its content by mouse
<UserControl x:Class="WPFZoomText.ZoomViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFZoomText"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500">
<Grid Background="Black" MouseDown="Grid_MouseDown" MouseUp="Grid_MouseUp" MouseWheel="Grid_MouseWheel"
SizeChanged="Grid_SizeChanged">
<Canvas Name="canvas" Canvas.Left="0" Canvas.Top="0">
<Canvas.RenderTransform>
<MatrixTransform x:Name="scale" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</UserControl>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace WPFZoomText
{
/// <summary>
/// Interaction logic for ZoomViewer.xaml
/// </summary>
public partial class ZoomViewer : UserControl
{
/// <summary>
/// Default constructor.
/// </summary>
public ZoomViewer()
{
InitializeComponent();
}
public Rect Domain { get; set; } = new Rect() { X = 0, Y = 0, Width = 30, Height = 30 };
/// <summary>
/// The set of the inner drawings (scale will affect to those drawings)
/// </summary>
public UIElementCollection Drawings
{
get
{
return canvas.Children;
}
}
/// <summary>
/// Scale the content to show everything.
/// </summary>
public void ZoomFit()
{
var s1 = ActualWidth / Domain.Width;
var s2 = ActualHeight / Domain.Height;
var m = new Matrix();
var sc = s1 > s2 ? s2 : s1;
m.Scale(sc, sc);
var porig = m.Transform(new Point(Domain.Width / 2 + Domain.Left, Domain.Height / 2 + Domain.Top));
var pdest = new Point(ActualWidth / 2, ActualHeight / 2);
m.Translate(pdest.X - porig.X, pdest.Y - porig.Y);
scale.Matrix = m;
}
private Point? draggingPoint = null;
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (e.ChangedButton == MouseButton.Left)
{
if (e.ClickCount == 2)
{
ZoomFit();
} else
{
draggingPoint = e.GetPosition(canvas);
((Grid)sender).CaptureMouse();
}
}
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (e.ChangedButton == MouseButton.Left) {
if (draggingPoint.HasValue)
{
var pos = e.GetPosition(canvas);
var v = draggingPoint.Value - pos;
var m = scale.Matrix;
m.Translate(-v.X, -v.Y);
scale.Matrix = m;
((Grid)sender).ReleaseMouseCapture();
draggingPoint = null;
}
}
}
private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var s = e.Delta > 0 ? 1.04 : 0.96;
var m = scale.Matrix;
var porig = m.Transform(e.GetPosition(canvas));
m.ScaleAt(s, s, porig.X, porig.Y);
scale.Matrix = m;
}
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
ZoomFit();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment