Я пытаюсь реализовать простую функциональность «масштабирования для точки» в WinForms. Когда мышь находится в одной точке и колесико мыши прокручивается в/из, оно отлично работает. Когда положение мыши изменено между свитками, оно перескакивает в эту позицию и очень неудобно. Вот код для элемента управления, который можно добавить к Form
для тестирования:Zoom To Point Не работает как ожидается
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);
}
}
Так важная часть, очевидно, affine transformation. Я знаю, что это в Adobe Flex, но я получил идею Translate
, Scale
, Translate
от this website (отличный пример того, что я пытаюсь сделать). Я не понимал, что MatrixOrder.Append
был ключом в .NET
, пока я не попытался. Но проблема все еще остается. Попробуйте загрузить элемент управления в приложении WinForms, и вы поймете, что я имею в виду. Кто-нибудь знает, в чем проблема?
EDIT: Причина мне нужно вручную вычислить прямоугольник, потому что я собираюсь быть рисунок более, чем просто изображение. Это холст, который работает как Visio. Мне также понадобится метод для преобразования определенного Point
.
EDIT 2: Я понимаю, что я могу использовать Invert()
на Matrix
затем TransformPoints()
, чтобы получить надлежащие преобразованные точки, но это еще не решает проблему шаткого движения мыши. Я думал о вычислении Origin
из местоположения верхнего угла изображения, но он не работал.
Ах bumme Я надеялся решить эту проблему. :) –
@Carter - Да, как только я это увидел, у меня был «D'OH!». момент. – TheCloudlessSky