Reputation: 628
I'm using this example (only with layout transform, and with attached behavior instead of external nuget package) to zoom into my canvas. It seems to work so far, but I also want to limit the applied zoom factor, e.g. the user can't zoom in more than 10x.
For that, I need to find out the actual zoom factor applied to my canvas. Unfortunately, the above code does not use the actual factor, only applies the next ScaleAt operation on the already scaled control.
Question: how can I find out, the already applied scale factor, to be able to decide, whether or not to apply the next scaling?
Extra: how could I expose this factor as a dependency property of my attached property, so I can apply a binding from xaml on it?
Edit - added code sample:
public static class ZoomBehavior
{
//example from https://stackoverflow.com/questions/46424149/wpf-zoom-canvas-center-on-mouse-position
#region ZoomFactor
public static double GetZoomFactor(DependencyObject obj)
{
return (double)obj.GetValue(ZoomFactorProperty);
}
public static void SetZoomFactor(DependencyObject obj, double value)
{
obj.SetValue(ZoomFactorProperty, value);
}
// Using a DependencyProperty as the backing store for ZoomFactor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomFactorProperty =
DependencyProperty.RegisterAttached("ZoomFactor", typeof(double), typeof(ZoomBehavior), new PropertyMetadata(1.05));
#endregion
#region ModifierKey
public static ModifierKeys? GetModifierKey(DependencyObject obj)
{
return (ModifierKeys?)obj.GetValue(ModifierKeyProperty);
}
public static void SetModifierKey(DependencyObject obj, ModifierKeys? value)
{
obj.SetValue(ModifierKeyProperty, value);
}
// Using a DependencyProperty as the backing store for ModifierKey. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ModifierKeyProperty =
DependencyProperty.RegisterAttached("ModifierKey", typeof(ModifierKeys?), typeof(ZoomBehavior), new PropertyMetadata(null));
#endregion
public static TransformMode TranformMode { get; set; } = TransformMode.Layout;
private static Transform _transform;
private static DesignerCanvas _canvas;
#region IsZoomable
public static bool GetIsZoomable(DependencyObject obj)
{
return (bool)obj.GetValue(IsZoomableProperty);
}
public static void SetIsZoomable(DependencyObject obj, bool value)
{
obj.SetValue(IsZoomableProperty, value);
}
// Using a DependencyProperty as the backing store for IsZoomable. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsZoomableProperty =
DependencyProperty.RegisterAttached(
"IsZoomable",
typeof(bool),
typeof(ZoomBehavior),
new UIPropertyMetadata(false, OnIsZoomableChanged));
#endregion
//#region ScaleMax
//#region ScaleMin
private static void OnIsZoomableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
_canvas = d as DesignerCanvas;
if (null == _canvas)
{
System.Diagnostics.Debug.Assert(false, "Wrong dependency object type");
return;
}
if ((e.NewValue is bool) == false)
{
System.Diagnostics.Debug.Assert(false, "Wrong value type assigned to dependency object");
return;
}
if (true == (bool)e.NewValue)
{
_canvas.MouseWheel += Canvas_MouseWheel;
if (TranformMode == TransformMode.Render)
{
_transform = _canvas.RenderTransform = new MatrixTransform();
}
else
{
_transform = _canvas.LayoutTransform = new MatrixTransform();
}
}
else
{
_canvas.MouseWheel -= Canvas_MouseWheel;
}
}
private static void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
ModifierKeys? modifierkey = GetModifierKey(sender as DependencyObject);
if (!modifierkey.HasValue)
{
return;
}
if((Keyboard.Modifiers & (modifierkey.Value)) == ModifierKeys.None)
{
return;
}
if (!(_transform is MatrixTransform transform))
{
return;
}
var pos1 = e.GetPosition(_canvas);
//double max = GetScaleMax(sender as DependencyObject);
//double min = GetScaleMin(sender as DependencyObject);
double zoomfactor = GetZoomFactor(sender as DependencyObject);
double scale = (e.Delta < 0) ? zoomfactor : (1 / zoomfactor);
//scale = (scale > max) ? max : scale;
//scale = (scale < min) ? min : scale;
var mat = transform.Matrix;
mat.ScaleAt(scale, scale, pos1.X, pos1.Y);
transform.Matrix = mat;
e.Handled = true;
}
public enum TransformMode
{
Layout,
Render,
}
}
Upvotes: 1
Views: 377
Reputation: 2654
You can Take the m11 and m22 Elements of Graphics.Transform, to get the x and y scale factors. You can "zoom" different in each dimension, that's why you get two factors.
But you never know, what your Graphics object is created for, they can actually be stacked one on top of the other, better you track any zoom operation you do, yourself, at another variable.
Upvotes: 1