C# GDI+ 以鼠标为中心缩放

ff09304 2016-11-21 05:45:58
现在在实现一个类似CAD的那样以鼠标点为中心的缩放。
然后我现在代码是这样的:

class Canvas{
class GlobalMatrix
{
public PointF m_pan;
public float m_rotation;
public float m_zoom = 1;
public float m_perZoom = 1.2f;
public PointF m_scalePos;

Matrix m_globalMatrix = new Matrix();
public Matrix GetMatrix()
{
m_globalMatrix.Reset();
m_globalMatrix.Translate(m_scalePos.X, m_scalePos.Y);
m_globalMatrix.Scale(m_zoom, m_zoom);
m_globalMatrix.Translate(-m_scalePos.X, -m_scalePos.Y);
//m_globalMatrix.Translate(m_scalePos.X - m_scalePos.X*m_zoom , m_scalePos.Y - m_scalePos.Y*m_zoom);

m_globalMatrix.Translate(m_pan.X, m_pan.Y);
m_globalMatrix.Rotate(m_rotation);
return m_globalMatrix;
}
}
GlobalMatrix m_globalMatrix = new GlobalMatrix();
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
m_globalMatrix.m_scalePos = (PointF)ScreenToCoord(e.Location);

//m_scalePos = CoordTransform(e.Location);
if (e.Delta < 0)
{
m_globalMatrix.m_zoom /= m_globalMatrix.m_perZoom;
}
else
{
m_globalMatrix.m_zoom *= m_globalMatrix.m_perZoom;
}
Invalidate();
}
//测试 绘制
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (m_bmpBuffer == null)
{
ReSize(ClientRectangle.Width, ClientRectangle.Height);
}
m_graphics.FillRectangle(Brushes.Black, this.ClientRectangle);

PointF[] pts = new PointF[]{
new PointF(20,20),
new PointF(80,80),
new PointF(20,80),
new PointF(80,20),
new PointF(0,0)
};
for (int i = 0; i < pts.Length; i++)
{
pts[i] = (PointF)ScreenToCoord(pts[i]);
}
m_graphics.DrawLine(Pens.White, pts[0], pts[1]);
m_graphics.DrawLine(Pens.White, pts[2], pts[3]);

RectangleF rect = new RectangleF(pts[4], Size.Empty);
rect.Inflate(4,4);
m_graphics.FillRectangle(Brushes.White, Rectangle.Round(rect));

e.Graphics.DrawImage(m_bmpBuffer, 0, 0);
//DrawCoord(e.Graphics);
}
public CoordPoint ScreenToCoord(PointF screenPoint)
{
PointF[] points = new PointF[] { screenPoint };
Matrix mx = m_globalMatrix.GetMatrix().Clone();
mx.TransformPoints(points);
return points[0]; //这里进行了隐式转换
/*有一个这样的结构体
public struct CoordPoint{
private float m_x;
private float m_y;
//与PointF隐式转换 允许PointF隐式转化成CoordPoint
public static implicit operator CoordPoint(System.Drawing.PointF p)
{
return new CoordPoint(p.X, p.Y);
}
}
*/
}
}

现在的实现现象是这样的:
在一个点上放大,效果符合预期,但是当放大倍率到10以上时,就会出现不一致的预期,准确来说是scalePos的位置获取不符合预期,然后程序就跑到很奇怪,甚至在绘图过程里抛出overflowException.
还有一点不符合预期的是,你在一个点缩放后,跑去另外一个点缩放(现在画的线有个交汇处),就是在这个交汇处缩放,缩放后,鼠标位置不在交汇点上。会跑偏,而跑偏的位置就是上次缩放的位置。
想了很久都没法解决。。只能来求助了。
...全文
434 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Happy-Tzy 2019-03-28
  • 打赏
  • 举报
回复
您好 在么?https://blog.csdn.net/onlyshi/article/details/78408000 这个贴子你最后是怎么实现的?我的始终不能够弹出软键盘。。。

110,532

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧