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# 在visual studio 2013中从面板复制徒手绘制_C#_Winforms_Panel_Picturebox - Fatal编程技术网

C# 在visual studio 2013中从面板复制徒手绘制

C# 在visual studio 2013中从面板复制徒手绘制,c#,winforms,panel,picturebox,C#,Winforms,Panel,Picturebox,我想在VisualStudio上徒手画一个表单(图片框),然后在另一个面板/图片框上复制相同的图形(我画的)。 它们也不应该是形成一条线的点,而是一条连续的线。请帮忙 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using Syst

我想在VisualStudio上徒手画一个表单(图片框),然后在另一个面板/图片框上复制相同的图形(我画的)。 它们也不应该是形成一条线的点,而是一条连续的线。请帮忙

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Pen p_white;

        bool draw = true;

        private Graphics objgraphics;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Pen p_black = new Pen(new SolidBrush(Color.Black));

            if (draw)
            {
                objgraphics = panel1.CreateGraphics();

            }

        }

        /*private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            bool draw = true;
        }*/

        private void panel1_MouseMove_1(object sender, MouseEventArgs e)
        {
                      Rectangle rEllipse = new Rectangle();


            switch (e.Button)
            {

                case MouseButtons.Left:

                    rEllipse.X = e.X;
                    rEllipse.Y = e.Y;
                    rEllipse.Width = 5;
                    rEllipse.Height = 5;
                    objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
                    break;

                case MouseButtons.Right:

                    rEllipse.X = e.X;
                    rEllipse.Y = e.Y;
                    rEllipse.Width = 3;
                    rEllipse.Height = 3;
                    objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
                    break;

                default:
                    return;
           } 

        }

        /*private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            bool draw = false;
        } */

        private void form_Paint(object sender, EventArgs e)
        {

        }

        private void panel2_Paint(object sender, PaintEventArgs e)
        {

            Pen p_black = new Pen(new SolidBrush(Color.Black));

            if (draw)
            {                objgraphics = panel1.CreateGraphics();

            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}

看着你的代码,我恐怕不得不说:这是完全错误的

很抱歉这么直截了当,但您决不能使用control.CreateGraphics

  • 首先要做的是扔掉
    Graphics objgraphics
    对象
存储
图形
对象(几乎)总是错误的

相反,您必须使用从控件的
Paint
事件中的
e.Graphics
参数获得的参数

请注意,
Graphics
不包含任何图形,它是一种用于在关联的
位图
或控件表面上绘制的工具

  • 接下来要做的是了解如何画手绘线。通常你可以看到你的代码;但它是无用的,只是一个例子,说明你在介绍中发现了多少愚蠢的事情。算了吧。它总是看起来像垃圾,因为圆圈从来都不光滑,一旦你把鼠标移动得更快,伪线就会完全散开
有一种很好的方法
DrawCurve
可以画出平滑的线条。你给它一支
笔和一组

这就是我们将要使用的

让我们回到基础:如何创建图形?现在我们知道,您需要在
Paint
事件中调用
DrawCurve

e.Graphics.DrawCurve(somePen, somePointsArray);
这就引出了下一个问题:

  • 什么是钢笔
  • 有什么事吗,雷
还有一个隐藏的第三个问题:

  • 画更多的线怎么样
第一个是简单的;创建一支笔划宽度为5.5像素的
,如下所示:

Pen somePen = new Pen(Color.Blue, 5.5f); 
如果需要,也可以给它一个线条样式(破折号)

现在来看数组:在最简单的形式中,这也很容易

MouseMove
事件中,您将当前
位置存储在点列表中。首先,我们在类级别声明它:

List<Point> currentLine = new List<Point>();
注意最后一行:在控件上调用
Invalidate
会触发系统来调用
Paint
事件。它可能看起来很复杂,但这是唯一正确的方法,因为它保证了当某些其他原因需要时,同样的绘图也会发生

我们需要绘制,因为我们更改了应该绘制的数据。但是有许多外部原因,最著名的是
最小化/最大化
序列,它将清除图形并触发
绘制
事件。因此,我们需要配合windows绘制控件的方式!只有这样,图形才会持续显示

还要注意,我们不使用数组,因为我们不知道需要多少
点。相反,我们使用
列表
,然后将其强制转换为
数组

让我们为我们的简单案例编写
Paint
事件:

private void panel1_Paint(object sender, PaintEventArgs e)
{
   using (Pen somePen = new Pen(Color.Blue, 5.5f) )
     if (currentLine.Count > 1) e.Graphics.DrawCurve(yourPen , currentLine.ToArray());
}
请注意,我已经使用
子句在
中创建了
。这是一种既便宜又安全的方法,可确保正确处置

还要注意我们如何将
列表
转换为
数组

仅上述代码就可以工作,并允许您自由地画一条线

但是下一行呢?它不应该连接到第一个,所以我们不能只添加更多的点

因此,我们不仅需要一个点列表,还需要更多的,事实上,需要一个点列表:

List<List<Point>> curves = new List<List<Point>>();
请注意,我如何使用从
列表
列表
的强制转换来强制执行副本,否则将只分配引用,然后在下一行中清除

我们再次触发
Paint
事件作为最后一件事

现在,我们应该更改
Paint
事件以显示所有线条,包括当前正在绘制的线条和所有早期线条..:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    using (Pen somePen = new Pen(Color.Blue, 5.5f) )
    {
       if (currentLine.Count > 1) e.Graphics.DrawCurve(somePen, currentLine.ToArray());
       foreach (List<Point> lp in curves)
          if (lp.Count > 1) e.Graphics.DrawCurve(somePen, lp.ToArray());
    }
}
我注意到,您的原始代码允许您使用左键和右键使用两种不同的笔划宽度进行绘制。仅此一点就表明此代码不是很好。a)谁会想到这一点,b)只满足于两个笔划宽度


请阅读我在其中介绍的创建一个类,该类可以存储笔宽、颜色等,以便您可以在绘制的线条之间进行更改。

这非常简单,只要您首先正确绘制。(即:将鼠标点存储在类级
列表
((或可能是
列表
)的mousemove中,并在面板绘制事件中绘制鼠标点。要复制鼠标点,您只需对面板2的绘制事件进行编码即可绘制相同的鼠标点。)-但由于您是新手,可能做得不对。你有代码给我们看吗?谢谢你。我愿意。这就是我用C#画画的方式。请现在检查代码。检查我写的答案。我有很多要学习和学习的东西,但它是值得的。谢谢TaW,我成功地完成了任务,你在详细的解释中帮了我很大的忙。现在我需要将这些图形保存在word文件中。我怎么能做到呢?不幸的是,我不做办公室自动化。你可以简单地使用创建包含图形的位图,但如何将其插入word文档我不知道。不过,应该有很多例子。。祝你好运
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
    if (currentLine.Count > 1) curves.Add(currentLine.ToList());  // copy!!
    currentLine.Clear();
    panel1.Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
    using (Pen somePen = new Pen(Color.Blue, 5.5f) )
    {
       if (currentLine.Count > 1) e.Graphics.DrawCurve(somePen, currentLine.ToArray());
       foreach (List<Point> lp in curves)
          if (lp.Count > 1) e.Graphics.DrawCurve(somePen, lp.ToArray());
    }
}
curves.Clear(); currentLine .Clear(); panel1.Invalidate();