Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法将单击坐标转换为picturebox_C#_Drawing - Fatal编程技术网

C# 无法将单击坐标转换为picturebox

C# 无法将单击坐标转换为picturebox,c#,drawing,C#,Drawing,我有一个带有一些图形的PictureBox,可以通过鼠标滚轮进行缩放。为了使图形保持在(大致)相同的位置,而不必在每次缩放后移动,我在每次缩放后平移图形。这是我的缩放代码: private void pictureBox1_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(pictureBox1.BackColor); float _step = 1.0f; if (todo == "zoom out")

我有一个带有一些图形的
PictureBox
,可以通过鼠标滚轮进行缩放。为了使图形保持在(大致)相同的位置,而不必在每次缩放后移动,我在每次缩放后平移图形。这是我的缩放代码:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(pictureBox1.BackColor);
    float _step = 1.0f;
    if (todo == "zoom out")
    {
        float step = 0;
        if (CurrentRate >= 0.60f) step = 0.05f;
        else if (CurrentRate >= 0.40f && CurrentRate < 0.60f) step = 0.025f;
        else if (CurrentRate >= 0.05f && CurrentRate < 0.40f) step = 0.0125f;
        CurrentRate -= step; // current rate is 1.0 on startup
        _step = step;
        //pictureBox1.Location = new Point((int)(pictureBox1.Location.X + step * 1500), (int)(pictureBox1.Location.Y + step * 1500));
        translateX += step * 10500; //achieved these numbers after few dozens of tries, it actually keeps the graphics at the same position..
        translateY += step * 8500;
        todo = null;
    }
    else if (todo == "zoom in")
    {
        float step = 0;
        if (CurrentRate >= 1.80f && CurrentRate <= 1.95f) step = 0.0125f;
        else if (CurrentRate >= 0.80f && CurrentRate < 1.80f) step = 0.025f;
        else if (CurrentRate >= 0.03f && CurrentRate < 0.80f) step = 0.05f;
        CurrentRate += step;
        _step = step;
        translateX -= step * 10500;
        translateY -= step * 8500;
        //pictureBox1.Location = new Point((int)(pictureBox1.Location.X - step * 1500), (int)(pictureBox1.Location.Y - step * 1500));
        todo = null;
    }

    e.Graphics.TranslateTransform(translateX, translateY); //move it to keep same position
    e.Graphics.ScaleTransform(CurrentRate, CurrentRate); //rescale according to the zoom
   //the drawing itself (of everything, also the things mentioned below)
但这不起作用。在MouseDown事件中,我也尝试过在没有翻译的情况下进行翻译,但仍然使用偏移量绘制。我不太确定如何正确描述这种行为,所以我做了一个简短的视频(大约30秒)来解释偏移量。。

有什么想法吗?先谢谢你

**

编辑 **

现在,根据答案进行编辑后,我的代码如下所示:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (trackDrawing)
        {
            Matrix m = transform.Clone();
            m.Invert();
            Point[] rectanglePos = new Point[1];
            rectanglePos[0] = new Point(e.Location.X - 3, e.Location.Y - 3);
            m.TransformPoints(rectanglePos);
            drawBuffer.Add(rectanglePos);
            drawBuffertype.Add("DRAWTRACKRECTANGLE");
            if (trackDrawingBuffer.Count > 0)
            {
                Point[] linePos = new Point[2];
                linePos[0] = trackDrawingBuffer[trackDrawingBuffer.Count - 1];
                linePos[1] = new Point(e.Location.X, e.Location.Y );
                m.TransformPoints(linePos);
                drawBuffer.Add(linePos);
                drawBuffertype.Add("DRAWTRACKLINE");
            }
            trackDrawingBuffer.Add(rectanglePos[0]);
            pictureBox1.Invalidate();
        }
现在,这里是转换部分,包括获取矩阵偏移量的代码

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.Clear(pictureBox1.BackColor);
        transform.Translate(-translateX, -translateY);
        float _step = 1.0f;
        if (todo == "zoom out")
        {
            float step = 0;
            if (CurrentRate >= 0.60f) step = 0.05f;
            else if (CurrentRate >= 0.40f && CurrentRate < 0.60f) step = 0.025f;
            else if (CurrentRate >= 0.05f && CurrentRate < 0.40f) step = 0.0125f;
            CurrentRate -= step;
            _step = step;
            translateX += step * 10500;
            translateY += step * 8500;
            todo = null;
        }
        else if (todo == "zoom in")
        {
            float step = 0;
            if (CurrentRate >= 1.80f && CurrentRate <= 1.95f) step = 0.0125f;
            else if (CurrentRate >= 0.80f && CurrentRate < 1.80f) step = 0.025f;
            else if (CurrentRate >= 0.03f && CurrentRate < 0.80f) step = 0.05f;
            CurrentRate += step;
            _step = step;
            //pictureBox1.Scale((1f + step), (1f + step));
            translateX -= step * 10500;
            translateY -= step * 8500;
            todo = null;
        }

        transform.Translate(translateX, translateY); // transform is the Matrix

        e.Graphics.Transform = transform;
        e.Graphics.ScaleTransform(CurrentRate, CurrentRate);
private void pictureBox1\u Paint(对象发送方,PaintEventArgs e)
{
e、 图形。清晰(pictureBox1.背景色);
transform.Translate(-translateX,-translateY);
浮动步进=1.0f;
如果(todo==“缩小”)
{
浮动步长=0;
如果(电流率>=0.60f)阶跃=0.05f;
否则,如果(电流率>=0.40f&&CurrentRate<0.60f)阶跃=0.025f;
否则,如果(电流率>=0.05f&&CurrentRate<0.40f)阶跃=0.0125f;
电流率-=步进;
_步骤=步骤;
translateX+=步骤*10500;
translateY+=步骤*8500;
todo=null;
}
else if(todo==“放大”)
{
浮动步长=0;
如果(电流率>=1.80f&&CurrentRate=0.80f&&CurrentRate<1.80f)阶跃=0.025f;
否则,如果(电流率>=0.03f&&CurrentRate<0.80f)阶跃=0.05f;
电流率+=阶跃;
_步骤=步骤;
//图1.刻度((一层+台阶),(一层+台阶));
translateX-=步骤*10500;
translateY-=步骤*8500;
todo=null;
}
transform.Translate(translateX,translateY);//transform是矩阵
e、 图形。变换=变换;
e、 图形.缩放转换(CurrentRate,CurrentRate);
这里是图纸本身:

 for (int i = 0; i < drawBuffer.Count; i++)
        {
        //...
else if (drawBuffertype[i].ToUpper().Contains("DRAWTRACKRECTANGLE"))
                {
                    e.Graphics.FillRectangle(new SolidBrush(Color.Red), drawBuffer[i][0].X, drawBuffer[i][0].Y, 6, 6);
                }
                else if (drawBuffertype[i].ToUpper().Contains("DRAWTRACKLINE"))
                {
                    e.Graphics.DrawLine(new Pen(Color.OrangeRed, 2), drawBuffer[i][0], drawBuffer[i][1]);
                }
for(int i=0;i

仍然像视频的第一部分那样画画。我只是缺少一些非常基本的东西…

也许这段简单的代码可以帮助你。这一切都是在没有任何转换或缩放的情况下完成的。但是如果你对图形应用缩放,效果也一样

this.pictureBox1.Scale(new SizeF(2.5f, 2.5f));
所以

实际上,我将矩形的边定义为15个单位宽

private int RectSideLen = 15;
所以每次我点击图片框时,我假设我点击了要绘制的矩形的中心。这意味着我们的矩形将从点击位置减去半个矩形边开始

int cornerOffset = RectSideLen / 2;
Point newUpLeftCorner = e.Location;
newUpLeftCorner.Offset(-cornerOffset, -cornerOffset);
然后我将它添加到一个矩形列表中,并刷新图片框,用添加的新矩形重新绘制它

pictureBox1.Refresh();
在图片框的绘画事件中,我只画了一个预先计算好的矩形

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    using (Pen pen = new Pen(Color.Red, 1))
    {
        foreach (Rectangle r in DrawBuffer)
        {
            e.Graphics.DrawRectangle(pen, r);
        }
    }
}
这是完整的样本

public partial class Form1 : Form
{
    private int RectSideLen = 15;
    private IList<Rectangle> DrawBuffer = new List<Rectangle>();

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
    {
        int cornerOffset = RectSideLen / 2;

        Point newUpLeftCorner = e.Location;
        newUpLeftCorner.Offset(-cornerOffset, -cornerOffset);

        DrawBuffer.Add(new Rectangle(newUpLeftCorner, new Size(RectSideLen, RectSideLen)));

        pictureBox1.Refresh();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {

        using (Pen pen = new Pen(Color.Red, 1))
        {
            foreach (Rectangle r in DrawBuffer)
            {
                e.Graphics.DrawRectangle(pen, r);
            }
        }
    }
}
公共部分类表单1:表单
{
private int RectSideLen=15;
私有IList DrawBuffer=新列表();
公共表格1()
{
初始化组件();
}
私有无效图片Box1u鼠标单击(对象发送器,MouseEventArgs e)
{
int cornerOffset=矩形边/2;
点newUpLeftCorner=e.位置;
newUpLeftCorner.Offset(-cornerOffset,-cornerOffset);
添加(新矩形(newUpLeftCorner,新大小(RectSideLen,RectSideLen));
pictureBox1.Refresh();
}
私有void pictureBox1_Paint(对象发送方,PaintEventArgs e)
{
使用(钢笔=新钢笔(颜色:红色,1))
{
foreach(DrawBuffer中的矩形r)
{
e、 绘图矩形(钢笔,r);
}
}
}
}

不是我的专业领域

…但您可以保留一个类级矩阵来表示“世界”的当前状态。您可以平移、缩放和/或旋转该矩阵来操纵世界。只需将该矩阵指定给
e.Graphics。在绘制所有内容之前变换

现在,当用户单击时,您可以克隆该矩阵并将其反转(),允许您使用其TransformPoints()方法。这将从屏幕坐标转换为等效的世界坐标。将转换后的世界坐标存储在列表中,以便您可以在Paint()事件中重用它们

玩这个例子。在一个空白表单中添加两个按钮,并将它们的单击事件关联到下面的相应典型方法名称。运行它并单击屏幕上的几个点。现在单击第一个按钮旋转,和/或第二个按钮放大。现在通过单击表单上的更多点尝试添加更多点。单击按钮看看会发生什么。一切都应该保持相对(我希望):

公共部分类表单1:表单
{
私有矩阵MyMatrix=新矩阵();
私有列表点=新列表();
公共表格1()
{
初始化组件();
this.WindowState=FormWindowState.Maximized;
this.show+=新的EventHandler(如图所示为Form1_);
}
所示为void Form1_(对象发送方、事件参数e)
{
点中心=新点(this.ClientRectangle.Width/2,this.ClientRectangle.Height/2);
MyMatrix.Translate(Center.X,Center.Y);
this.MouseDown+=新的MouseEventHandler(Form1\u MouseDown);
this.Paint+=新的PaintEventHandler(Form1_Paint);
public partial class Form1 : Form
{
    private int RectSideLen = 15;
    private IList<Rectangle> DrawBuffer = new List<Rectangle>();

    public Form1()
    {
        InitializeComponent();
    }

    private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
    {
        int cornerOffset = RectSideLen / 2;

        Point newUpLeftCorner = e.Location;
        newUpLeftCorner.Offset(-cornerOffset, -cornerOffset);

        DrawBuffer.Add(new Rectangle(newUpLeftCorner, new Size(RectSideLen, RectSideLen)));

        pictureBox1.Refresh();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {

        using (Pen pen = new Pen(Color.Red, 1))
        {
            foreach (Rectangle r in DrawBuffer)
            {
                e.Graphics.DrawRectangle(pen, r);
            }
        }
    }
}
public partial class Form1 : Form
{

    private Matrix MyMatrix = new Matrix();
    private List<Point> Points = new List<Point>();

    public Form1()
    {
        InitializeComponent();
        this.WindowState = FormWindowState.Maximized;
        this.Shown += new EventHandler(Form1_Shown);
    }

    void Form1_Shown(object sender, EventArgs e)
    {
        Point Center = new Point(this.ClientRectangle.Width / 2, this.ClientRectangle.Height / 2);
        MyMatrix.Translate(Center.X, Center.Y);
        this.MouseDown += new MouseEventHandler(Form1_MouseDown);
        this.Paint += new PaintEventHandler(Form1_Paint);
    }

    void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.Transform = MyMatrix;

        // draw the origin in the center of the form:
        e.Graphics.DrawLine(Pens.Red, new Point(-10, 0), new Point(10, 0));
        e.Graphics.DrawLine(Pens.Red, new Point(0, -10), new Point(0, 10));

        // draw our stored points (that have already been converted to world coords)
        foreach (Point pt in Points)
        {
            Rectangle rc = new Rectangle(pt, new Size(1, 1));
            rc.Inflate(10, 10);
            e.Graphics.DrawRectangle(Pens.Black, rc);
        }
    }

    void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        Matrix m = MyMatrix.Clone();
        m.Invert();
        Point[] pts = new Point[] {new Point(e.X, e.Y)};
        m.TransformPoints(pts);
        Points.Add(pts[0]);
        this.Refresh();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MyMatrix.Rotate(10);
        this.Refresh();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        MyMatrix.Scale(1.1f, 1.1f);
        this.Refresh();
    }

}