且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 C# windows 窗体中绘制可缩放图像

更新时间:2023-10-27 23:50:40

这是一个 PictureBox 子类,它不仅支持将缩放应用于 Image到您在其表面绘制的图形.

Here is a PictureBox subclass that supports the ability to apply zooming not only to the Image but also to graphics you draw onto its surface.

它包括一个 SetZoom 函数,通过缩放自身和矩阵来放大.

It includes a SetZoom function to zoom in by scaling both itself and a Matrix.

它还有一个 ScalePoint 函数,您可以使用它从鼠标事件中接收到的像素坐标计算未缩放的坐标.

It also has a ScalePoint function you can use to calculate the unscaled coordinates from the pixel coordinates you receive in the mouse events.

这个想法是使用 Transformation Matrix 来缩放 Graphics 对象将在 Paint 事件中绘制的任何像素.

The idea is to use a Transformation Matrix to scale any pixels the Graphics object will draw in the Paint event.

我包含了一些用于测试表单的代码.

I include a little code for the form for testing.

public partial class ScaledPictureBox : PictureBox
{
    public Matrix ScaleM { get; set; }

    float Zoom { get; set; }
    Size ImgSize { get; set; }

    public ScaledPictureBox()
    {
        InitializeComponent();
        ScaleM = new Matrix();
        SizeMode = PictureBoxSizeMode.Zoom;
    }

    public void InitImage()
    {
        if (Image != null)
        {
            ImgSize = Image.Size;
            Size = ImgSize;
            SetZoom(100);
        }
    }

    public void SetZoom(float zoomfactor)
    {
        if (zoomfactor <= 0) throw new Exception("Zoom must be positive");
        float oldZoom = Zoom;
        Zoom = zoomfactor / 100f;
        ScaleM.Reset();
        ScaleM.Scale(Zoom , Zoom );
        if (ImgSize != Size.Empty) Size = new Size((int)(ImgSize.Width * Zoom), 
                                                   (int)(ImgSize.Height * Zoom));

    }

    public PointF ScalePoint(PointF pt)
    {   return new PointF(pt.X / Zoom , pt.Y / Zoom );     }

}

这是表单中进行测试的代码:

Here is the code in the Form that does the testing:

public List<PointF> somePoints = new List<PointF>();

private void scaledPictureBox1_MouseClick(object sender, MouseEventArgs e)
{
    somePoints.Add(scaledPictureBox1.ScalePoint(e.Location) );
    scaledPictureBox1.Invalidate();
}

private void scaledPictureBox1_Paint(object sender, PaintEventArgs e)
{
    // here we apply the scaling matrix to the graphics object:
    e.Graphics.MultiplyTransform(scaledPictureBox1.ScaleM);
    using (Pen pen = new Pen(Color.Red, 10f))
    {
        PointF center = new PointF(scaledPictureBox1.Width / 2f, 
                                   scaledPictureBox1.Height / 2f);
        center = scaledPictureBox1.ScalePoint(center);
        foreach (PointF pt in somePoints)
        {
            DrawPoint(e.Graphics, pt, pen);
            e.Graphics.DrawLine(Pens.Yellow, center, pt);
        }
    }
}

public void DrawPoint(Graphics G, PointF pt, Pen pen)
{
    using (SolidBrush brush = new SolidBrush(pen.Color))
    {
        float pw = pen.Width;
        float pr = pw / 2f;
        G.FillEllipse(brush, new RectangleF(pt.X - pr, pt.Y - pr, pw, pw));
    }
}

以下是绘制几个点后的结果,显示了在四种不同缩放设置下的相同点;ScaledPictureBox 显然放在 AutoScroll-Panel 中.线条显示如何使用常规绘图命令..

Here are the results after drawing a few points showing the same points in four different zoom settings; the ScaledPictureBox is obviously placed in an AutoScroll-Panel. The lines show how to use the regular drawing commands..