Image Control provide zoom in and out of images using scroll wheel
When mouse hovering over the Image control, scroll the mouse wheel to zoom in and out of the image
With the latest commit, you can do this outside of Image (or SvgImage) control, something like this:
var img = new Image();
Children.Add(img);
var accumulatedZoom = 0;
const float zoomStepPercent = 0.01f;
img.MouseWheel += (s, e) =>
{
accumulatedZoom += e.Delta;
if (accumulatedZoom != 0)
{
var destRc = img.GetDestinationRectangle();
var scale = 1 + zoomStepPercent * accumulatedZoom;
var offsetX = destRc.Width * zoomStepPercent * accumulatedZoom / 2;
var offsetY = destRc.Height * zoomStepPercent * accumulatedZoom / 2;
img.RenderTransformMatrix = Matrix4x4.CreateScale(scale) * Matrix4x4.CreateTranslation(new Vector3(-offsetX, -offsetY, 0));
}
else
{
img.RenderTransformMatrix = null;
}
};
img.Source = Application.CurrentResourceManager.GetWicBitmapSource(@"resources\rainier.jpg")
In https://github.com/aelyo-softworks/Wice/blob/main/WiceAot.Tests/TestWindow.cs#L69
Thank you for your prompt reply.
Can the Image control support zooming and moving by default ?
public void ZoomableMovableImage()
{
var img = new Image();
img.InterpolationMode = D2D1_INTERPOLATION_MODE.D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC;
Children.Add(img);
var accumulatedZoom = 0;
const float zoomStepPercent = 0.05f;
float scale = 1;
float offsetX = 0;
float offsetY = 0;
bool ismoving = false;
POINT startpoint = new POINT(0, 0);
POINT endpoint = new POINT(0, 0);
float lastoffsetX = 0;
float lastoffsetY = 0;
Vector3 LastMovePoint = new Vector3(0, 0, 0);
img.MouseWheel += (s, e) =>
{
accumulatedZoom += e.Delta;
if (accumulatedZoom != 0)
{
var destRc = img.GetDestinationRectangle();
scale = 1 + zoomStepPercent * accumulatedZoom;
offsetX = destRc.Width * zoomStepPercent * accumulatedZoom / 2;
offsetY = destRc.Height * zoomStepPercent * accumulatedZoom / 2;
Vector3 target = new Vector3(LastMovePoint.X - offsetX + lastoffsetX, LastMovePoint.Y - offsetY + lastoffsetY, 0);
img.RenderTransformMatrix = Matrix4x4.CreateScale(scale) * Matrix4x4.CreateTranslation(target);
}
else
{
img.RenderTransformMatrix = null;
}
};
img.MouseButtonDown += (s, e) =>
{
startpoint = e.Point;
ismoving = true;
LastMovePoint = new Vector3(0, 0, 0);
if (img.RenderTransformMatrix.HasValue) LastMovePoint = img.RenderTransformMatrix.Value.Translation;
};
img.MouseMove += (s, e) =>
{
if (!ismoving) return;
endpoint = e.Point;
float moveX = LastMovePoint.X + endpoint.x - startpoint.x;
float moveY = LastMovePoint.Y + endpoint.y - startpoint.y;
Vector3 target = new Vector3(moveX, moveY, 0);
img.RenderTransformMatrix = Matrix4x4.CreateScale(scale) * Matrix4x4.CreateTranslation(target);
};
img.MouseButtonUp += (s, e) =>
{
ismoving = false;
LastMovePoint = new Vector3(0, 0, 0);
if (img.RenderTransformMatrix.HasValue) LastMovePoint = img.RenderTransformMatrix.Value.Translation;
lastoffsetX = offsetX;
lastoffsetY = offsetY;
};
img.Source = Application.CurrentResourceManager.GetWicBitmapSource(@"resources\rainier.jpg");
}
It's not the objective of Wice to do everything. The objective is to be able to build many things with it programmatically while keeping it as simple as possible. Typically, all classes (Visuals, etc.) are designed to derivable for this reason.
So no, this won't be by default since it can be done in various ways depending on various contexts
After add ScrollViewer control, the visible area of zooming is limited by the visible area of ScrollViewer .
Use ZoomableImageWithSV() function and 42.jpg
it is TestWindow.cs and 42.jpg. Press crtl + mouse wheel to zoom image ZoomWithSV.zip
This is a different question, you want to resize a visual in the layout system, not an image.
Typically, w/o changing Wice, you could do it like this with a custom derived class:
private class ZoomableImage : Image
{
// a Zoom change will cause invalidation of ZoomableImage (Measure => Arrange => Render)
public static VisualProperty ZoomProperty { get; } = VisualProperty.Add(typeof(ZoomableImage), nameof(Zoom), VisualPropertyInvalidateModes.Measure, 1f);
public float Zoom { get => (float)GetPropertyValue(ZoomProperty)!; set => SetPropertyValue(ZoomProperty, value); }
protected override D2D_SIZE_F MeasureCore(D2D_SIZE_F constraint)
{
var size = base.MeasureCore(constraint);
size.width *= Zoom;
size.height *= Zoom;
return size;
}
}
....
var sv = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto };
sv.Viewer.IsWidthUnconstrained = false;
sv.Margin = D2D_RECT_F.Thickness(10);
Dock.SetDockType(sv, DockType.Top);
var img = new ZoomableImage { VerticalAlignment = Alignment.Near, HorizontalAlignment = Alignment.Center };
sv.Viewer.Children.Add(img);
Children.Add(sv);
img.MouseWheel += (s, e) =>
{
if (!NativeWindow.IsKeyPressed(VIRTUAL_KEY.VK_CONTROL))
return;
const float zoomStepPercent = 0.05f;
img.Zoom += e.Delta * zoomStepPercent;
};
img.Source = Application.CurrentResourceManager.GetWicBitmapSource(@"resources\rainier.jpg");
Since the Zoom property as it is can be useful (it does nothing else but change desired size, like in this ZoomableImage class), I've added it to all the base Visual class, so, with the latest commit, you can use the code Above with Image instead of ZoomableImage.
I have added image movement function. When the image is zoomed in, it limit the capture of mouse events. The capture area is limited to the range before movement.
I know where the problem lies now What I need is image scaling and translation, not image control scaling and translation