从 Visual Studio 2013 的面板中复制手绘图

2024-01-27

我想在 Visual Studio 上以表单(图片框)徒手绘制,并在另一个面板/图片框上复制相同的图形(我绘制的)。 而且它们不应该是形成一条线的点,而是一条连续的线。请帮忙。

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 object.

存储a(几乎)总是错误的Graphics object!

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

注意Graphics 不包含任何图形,它是一个用于绘制到关联的工具Bitmap或控件的表面。

  • 接下来要做的就是了解手绘线条。通常人们可以看到您拥有的代码;但这是无用的,只是你在介绍中发现了多少愚蠢的事情的一个例子。忘了它。它总是看起来像垃圾,因为圆圈看起来永远不会平滑,一旦你更快地移动鼠标,伪线就会完全崩溃。

有一个不错的方法DrawCurve这将画出平滑的线条。你喂它一个Pen和一个数组Points.

这就是我们将要使用的。

让我们回到基础知识:如何创建图形?现在我们知道您需要致电DrawCurve in the Paint event:

e.Graphics.DrawCurve(somePen, somePointsArray);

这就提出了接下来的问题:

  • 什么是笔
  • 什么是 somePointsArray

还有一个隐藏的第三个问题:

  • 画更多线条怎么样?

第一个很简单;你创建一个Pen笔划宽度为 5.5 像素

Pen somePen = new Pen(Color.Blue, 5.5f); 

如果你愿意,你也可以给它一个线条样式(破折号)。

现在来说说数组:以最简单的形式,这也很容易。

In the MouseMove您存储当前的事件Location在点列表中。首先,我们在类级别声明它:

List<Point> currentLine = new List<Point>();

然后我们只要按下左键就开始填充:

private void panel1_MouseMove_1(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        currentLine.Add(e.Location);
        panel1.Invalidate();
    }  
}

注意最后一行:调用Invalidate在控件上触发system调用Paint事件。它可能看起来很复杂,但这是唯一正确的方法,因为它保证当某些情况下也会发生完全相同的绘图other理性使得它成为必要。

We需要绘制,因为我们更改了应该绘制的数据。但也有很多outside原因,最出名的是Minimize/maximize序列将清除绘图并触发Paint事件,也。所以我们需要合作随路windows绘制其控件!只有这样图形才会persist.

另外,请注意,我们不使用数组,因为我们不知道有多少Points我们会需要。相反,我们使用List然后将其投射到Array.

让我们编写代码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());
}

请注意,我已经创建了Pen in a using条款。这是一种廉价且安全的方法,可确保Pen已妥善处置。

另请注意我们如何投射List to an Array!

仅上面的代码就可以工作并允许您徒手画一条线。

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

所以我们不仅需要one点列表但是more除此之外,事实上,需要一个点列表的列表:

List<List<Point>> curves = new List<List<Point>>();

每当释放鼠标时,我们都会将当前曲线添加到其中:

private void panel1_MouseUp(object sender, MouseEventArgs e)
{
    if (currentLine.Count > 1) curves.Add(currentLine.ToList());  // copy!!
    currentLine.Clear();
    panel1.Invalidate();
}

请注意我如何使用来自List to List强制执行副本,否则仅分配引用,然后在下一行中清除..

我们再次触发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());
    }
}

现在我们的手绘部分已经基本完成了。

所以我们回到你原来的问题:如何将绘图复制到second Panel?

好吧,你已经将所有内容存储在curves数据结构。

所以你有两个选择:要么简单地使用相同的数据panel2_Paint事件或者如果您需要复制和更改数据,也许会适应不同的大小。

以下是仍然缺少的东西:

  • 保存数据,保存绘图(Serialize, DrawToBitMap)
  • 用不同的笔和颜色绘图(创建一个drawAction类来存储您需要的所有内容)
  • 使用其他工具,如直线或矩形(创建一个drawAction class)
  • 清除绘图(见下文)
  • 撤消和重做(查看Stacks an Queues)
  • 当有大量行时进行缓存(将第一部分绘制到BackgroundImage Bitmap)

这是一个清除代码:

curves.Clear(); currentLine .Clear(); panel1.Invalidate();

我注意到您的原始代码允许您使用左右按钮以两种不同的笔画宽度进行绘制。仅此一点就说明这段代码不是很好。谁会a)想到这一点并且b)只满足于两个笔划宽度。

请阅读这个帖子 https://stackoverflow.com/questions/28714411/update-a-drawing-without-deleting-the-previous-one/28716887?s=5%7C0.1873#28716887我在其中解释了一些关于创建一个可以存储笔宽度、颜色等的类,以便您可以在绘制的线条之间进行更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Visual Studio 2013 的面板中复制手绘图 的相关文章

  • 无法使用c#更改视频捕获分辨率

    我正在尝试使用 C 中的 DirectShowNet 更改默认网络摄像头分辨率 据我所知 我需要通过调用 windows win32 api dll 中内置的 VideoInfoHeader 类来更改它以进行 avi 捕获 我有来自 Dir
  • 如何使用 Entity Framework 和 Identity 解决对象处置异常 ASP.NET Core

    我正在尝试编写一个控制器 该控制器接收来自 AJAX 调用的请求并通过 DBContext 对数据库执行一些调用 但是 当我发出命令时var user await GetCurrentUserAsynch 在对 DBContext 的任何调
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 头文件中实现的函数的静态与内联

    我想到的方式inline在 C 中用于链接 作用域 我把它放在同一个篮子里extern and static对于全局对象 通常 对于在头文件中实现的函数 我的首选解决方案是将其设为静态 In Foo h static void foo Do
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • 如何通过 libwebsocket 发送异步数据?

    我正在将 Warmcat 的 libwebsocket C 库用于小型 Websocket 服务器 我已经启动并运行了这些示例 并且可以发送数据以响应从 websocket 接收数据 例如回显发送的反向字节 但是 我无法弄清楚如何在不使用
  • 无法将参数从 `const char *` 转换为 `char *`

    鉴于此代码 void group build int size std string ips Build the LL after receiving the member list from bootstrap head new memb
  • 原子存储抛出错误

    我最近升级到了 C 11 兼容编译器 并且尝试将一些代码从 boost 更新到 c 11 标准 我在使用atomic store转换一些代码时遇到了问题 这是一些简单的测试代码 似乎会引发编译器错误 int main std shared
  • 检测反射 DLL 注入

    在过去的几年中 恶意软件 以及一些渗透测试工具 如 Metasploit 的 meterpreter 负载 已经开始使用反射 DLL 注入 PDF http www harmonysecurity com files HS P005 Ref
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • 模板与非模板类,跨编译器的不同行为

    我在一些应用程序中使用编译时计数器 它确实很有用 昨天我想用 gcc 编译一个程序 我之前使用的是 msvc 并且计数器的行为在模板类中发生了变化 它在模板类中不再工作 过于简化的代码 Maximum value the counter c
  • 列表到优先队列

    我有一个 C 大学编程项目 分为两个部分 在开始第二部分时应该使用priority queues hash tables and BST s 我 至少 在优先级队列方面遇到了麻烦 因为它迫使我自己重做第一部分中已经实现的许多代码 该项目是关
  • ASP.net WebForms - 在标记中使用 GetRouteUrl

    我一直在尝试弄清楚如何将路由功能与 ASP net 4 0 WebForms 一起使用 我将一条路线添加到我的路线集合中 void Application Start RegisterRoutes RouteTable Routes voi
  • 表单上的 KeyEvents 只能与 CTRL 结合使用

    Code Private Sub KeyHandling ByVal sender As Object ByVal e As System Windows Forms KeyEventArgs Handles Me KeyDown Sele
  • Windows 上本机 C++ 应用程序中的自动死代码检测?

    背景 我有一个用原生 C 编写的应用程序 花了几年的时间 大约有 60 KLOC 有很多函数和类已经死了 可能有 10 15 就像下面提出的类似的基于 Unix 的问题 我们最近开始对所有新代码进行单元测试 并尽可能将其应用于修改后的代码
  • 如何禁用基于 ValidationRule 类的按钮?

    如何禁用基于 ValidationRule 类的 WPF 按钮 下面的代码可以很好地突出显示 TextBox
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 基础设施 - 同步和异步接口和实现? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在实现库 基础设施时 并且该 API 的用户希望同步和异步使用代码 我读到混合同步和异步并不是一个好主意 例如 同步实现包括等待异步实现 显然
  • 使用C标准数学库精确计算标准正态分布的CDF

    标准 C 数学库不提供计算标准正态分布 CDF 的函数 normcdf 然而 它确实提供了密切相关的函数 误差函数 erf 和互补误差函数 erfc 计算 CDF 的最快方法通常是通过误差函数 使用预定义常量 M SQRT1 2 来表示 d
  • C# PasswordDeriveBytes:似乎 Salt 并不重要

    可能我误解了什么 以下代码通过 CryptDeriveKey 使用两种不同的盐生成两个相等的密钥 这是控制台结果 盐1 21 3e 18 a3 9a 8b 5f gt 键 da 89 ea 3d 91 08 20 98 20 e9 dc 4

随机推荐