This way quite tricky :cool:
Sorry for waiting so long - I working on new version of Reader3ds.
So here is the solution:
The XAML part is the same as before:
Code:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:zoomPanel="clr-namespace:Ab2d.Controls;assembly=Ab2d.Controls.ZoomPanel"
Title="Window1" Height="300" Width="300"
MouseWheel="Window_MouseWheel">
<Grid>
<zoomPanel:ZoomPanel Name="ZoomPanel1" IsMouseWheelZoomEnabled="False" ZoomMode="Move">
<TextBlock Text="12345"/>
</zoomPanel:ZoomPanel>
</Grid>
</Window>
The tricky part is in the code:
Code:
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point mousePosition;
double zoomFactor;
if (e.Delta > 0)
zoomFactor = 1.3;
else
zoomFactor = 1 / 1.3;
mousePosition = e.GetPosition(ZoomPanel1);
ZoomPanel1.Viewbox = GetNewViewbox(zoomFactor, mousePosition);
e.Handled = true;
}
private Rect GetNewViewbox(double zoomFactor, Point mousePosition)
{
UIElement content;
double zoomPanelAspectRatio, contentAspectRatio;
double aspect;
Rect newViewbox;
Point relativeMousePosition;
Point relativeViewboxPosition;
Point relativeViewboxPosition2;
Rect actualViewbox1, actualViewbox2;
content = ZoomPanel1.Content as UIElement;
if (content == null)
return ZoomPanel1.Viewbox;
zoomPanelAspectRatio = ZoomPanel1.ActualWidth / ZoomPanel1.ActualHeight;
contentAspectRatio = content.DesiredSize.Width / content.DesiredSize.Height;
// Apsect ration between ZoomPanel and its content
aspect = contentAspectRatio / zoomPanelAspectRatio;
relativeMousePosition = new Point(mousePosition.X / ZoomPanel1.ActualWidth,
mousePosition.Y / ZoomPanel1.ActualHeight);
// Calculate actual viewbox
actualViewbox1 = AdjustRectForAspectRatio(ZoomPanel1.Viewbox, aspect);
// mouse position on the original actual viewbox
relativeViewboxPosition = new Point(actualViewbox1.X + actualViewbox1.Width * relativeMousePosition.X,
actualViewbox1.Y + actualViewbox1.Height * relativeMousePosition.Y);
// Do the normal zoom to the current center point for the zoomFactor
double viewboxDx, viewboxDy;
// viewboxDx and viewboxDy are the actual viewbox changes
viewboxDx = ZoomPanel1.Viewbox.Width - (ZoomPanel1.Viewbox.Width / zoomFactor);
viewboxDy = ZoomPanel1.Viewbox.Height - (ZoomPanel1.Viewbox.Height / zoomFactor);
newViewbox = new Rect(ZoomPanel1.Viewbox.X + viewboxDx / 2,
ZoomPanel1.Viewbox.Y + viewboxDy / 2,
ZoomPanel1.Viewbox.Width - viewboxDx,
ZoomPanel1.Viewbox.Height - viewboxDy);
// Now get where the mouse position would be in the newViewbox
actualViewbox2 = AdjustRectForAspectRatio(newViewbox, aspect);
relativeViewboxPosition2 = new Point(actualViewbox2.X + actualViewbox2.Width * relativeMousePosition.X,
actualViewbox2.Y + actualViewbox2.Height * relativeMousePosition.Y);
// Adjust the newViewbox so the objects under the mouse position stay on the same place
newViewbox.X -= relativeViewboxPosition2.X - relativeViewboxPosition.X;
newViewbox.Y -= relativeViewboxPosition2.Y - relativeViewboxPosition.Y;
return newViewbox;
}
private Rect AdjustRectForAspectRatio(Rect originalRect, double aspect)
{
Rect adjustedRect;
adjustedRect = originalRect;
if (aspect > 1) // content wider than ZoomPanel
{
//actualViewbox2.Y = actualViewbox1.Y * aspect - (actualViewbox1.Height * (aspect - 1) / 2);
adjustedRect.Y *= aspect;
adjustedRect.Height *= aspect;
}
else
{
adjustedRect.X /= aspect;
adjustedRect.Width /= aspect;
}
return adjustedRect;
}
This should work.
The code will be probably included into next version of ZoomPanel (cannot say when it will be published).
Thank you for your recommendation.