Я пытаюсь реализовать в WinForms простую функцию «масштабирования до точки». Когда мышь находится в одной и той же точке, а колесо мыши прокручивается внутрь / наружу, она прекрасно работает. Когда позиция мыши изменяется между прокрутками, она переходит в эту позицию и очень шаткая. Вот код для элемента управления, который вы можете добавить к Form
для тестирования:
public class Canvas : Control
{
private Bitmap Image;
private TextureBrush ImageBrush;
private Point Origin;
private Matrix TransformMatrix;
public float ZoomScale
{
get;
set;
}
public Canvas()
{
this.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
this.Image = // Load your picture here.
this.ImageBrush = new TextureBrush(this.Image, WrapMode.Clamp);
this.ZoomScale = 1.0f;
this.TransformMatrix = new Matrix();
}
protected override void OnPaint(PaintEventArgs e)
{
float zs = this.ZoomScale;
var matrix = this.TransformMatrix.Clone();
e.Graphics.Transform = matrix;
var c = e.ClipRectangle;
// Transform the clip rectangle, is this even right?
var x = (int)Math.Round(c.X / zs - matrix.OffsetX / zs);
var y = (int)Math.Round(c.Y / zs - matrix.OffsetY / zs);
var w = (int)Math.Round(c.Width / zs);
var h = (int)Math.Round(c.Height / zs);
// Draw the image scaled and translated.
e.Graphics.FillRectangle(this.ImageBrush, x, y, w - 1, h - 1);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (e.Delta > 0)
{
this.ZoomScale += 0.1f;
}
else
{
this.ZoomScale -= 0.1f;
}
this.ZoomToPoint(e.Location);
this.Refresh();
}
private void ZoomToPoint(Point origin)
{
this.Origin = origin;
float zoomScale = this.ZoomScale;
// The important part.
var matrix = new Matrix(1, 0, 0, 1, 0, 0);
matrix.Reset();
matrix.Translate(-origin.X, -origin.Y, MatrixOrder.Append);
matrix.Scale(zoomScale, zoomScale, MatrixOrder.Append);
matrix.Translate(origin.X, origin.Y, MatrixOrder.Append);
this.TransformMatrix = matrix;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.ZoomToPoint(this.Origin);
}
}
Таким образом, важной частью является, очевидно, аффинное преобразование . Я знаю, что это в Adobe Flex, но у меня появилась идея Translate
, Scale
, Translate
с этого сайта (отличный пример того, что я пытаюсь сделать). Я не осознавал, что MatrixOrder.Append
был ключом в .NET
, пока не попробовал. Но проблема все еще остается. Попробуйте загрузить элемент управления в приложение WinForms, и вы поймете, что я имею в виду. Кто-нибудь знает, в чем проблема с этим?
РЕДАКТИРОВАТЬ : причина, по которой мне нужно вручную вычислить прямоугольник, заключается в том, что я собираюсь нарисовать больше , чем просто изображение. Это холст, который работает как Visio. Мне также понадобится метод для преобразования определенного Point
.
РЕДАКТИРОВАТЬ 2 : Я понимаю, что могу использовать Invert()
на Matrix
, а затем TransformPoints()
, чтобы получить правильную трансформированную точку, но это все еще не решает проблему шаткого движения мышью , Я думал о вычислении Origin
из местоположения верхнего угла изображения, но это не сработало.