现在在实现一个类似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.
还有一点不符合预期的是,你在一个点缩放后,跑去另外一个点缩放(现在画的线有个交汇处),就是在这个交汇处缩放,缩放后,鼠标位置不在交汇点上。会跑偏,而跑偏的位置就是上次缩放的位置。
        想了很久都没法解决。。只能来求助了。