用鼠标移动绘制的线

2023-12-03

我试图通过用鼠标抓住一条绘制的线来移动它。

这条线已经画好了Graphics.DrawLine(Pen P, Point A, Point B).

创建线条并将其绘制在表单上绝对没有问题。

我试过了:

  • 将行添加到GraphicsPath- 这甚至没有划清界限OnPaint.

  • 检查是否MouseEventArgs e.Location与一些基本代数有关(到目前为止我已经放弃了计算)

总结一下:我想抓住线路并将其拖动到某个地方,但我什至无法检查 e.Location 是否在线上,我该怎么做?

编辑:这就是我使用 GraphicsPath 时代码的样子。

当我不使用 GraphicsPath 时,我有:

if (s.thisShape == ShapeType.Line) {
  g.DrawLine(pen, s.p1, s.p2);
} else { ... }`

在 DrawingShapes 方法中。

从 drawStuff : Usercontrol 类:

private void drawStuff_MouseDown(object sender, MouseEventArgs e)
{
  pointRegion = e.Location;
  for (int i = 0; i < Shapes.Count; i++)
  {
    if (Shapes[i].Region.IsVisible(pointRegion))
    {
      isDragging = true;
      count = i;
      break;
    }
  }
}

private void drawStuff_MouseMove(object sender, MouseEventArgs e)
{
  if (isDragging)
  {
    Shapes[count].moveWithDiff(pointRegion, e.Location);
    pointRegion = e.Location;
    Refresh();
  }
}

private void drawStuff_MouseUp(object sender, MouseEventArgs e)
{
  isDragging = false;
  Refresh();
}

protected override void OnPaint(PaintEventArgs e)
{
  base.OnPaint(e);
  drawShapes(e.Graphics);
}

private void drawShapes(Graphics g)
{
  temporaryPen = pennaLeft;
  foreach (Shape s in Shapes)
  {
    g.FillRegion(temporaryPen, s.Region);
  }
}

从 Shape : Usercontrol 类:

public void moveWithDiff(Point pr, Point mp)
{
  Point p = new Point();
  if (this.thisShape == ShapeType.Line)
  {
    p.X = mp.X - pr.X;
    p.Y = mp.Y - pr.Y;
    this.p1.X += p.X;
    this.p1.Y += p.Y;
    this.p2.X += p.X;
    this.p2.Y += p.Y;
  }
  RefreshPath();
}

private void RefreshPath()
{
  gPath = new GraphicsPath();
  switch (thisShape)
  {
    case ShapeType.Line:
      gPath.AddLine(this.p1, this.p2);
      break;
  }
  this.Region = new Region(gPath);
}

现在,这甚至没有画线,但是使用 DrawingShapes() 中的 if 语句它可以完美绘制,但我无法将其拖动到其他地方。


让我们从基础知识开始,在屏幕上画一条线。我创建了一个自定义类来处理我希望在此过程中可用的一些功能:

public class MyLine
{
    public Pen pen { get; set; }
    public Point Start { get; set; }
    public Point End { get; set; }

    public MyLine(Pen p, Point p1, Point p2)
    {
        pen = p;
        Start = p1;
        End = p2;
    }

    public float slope
    {
        get
        {
            return (((float)End.Y - (float)Start.Y) / ((float)End.X - (float)Start.X));
        }
    }
    public float YIntercept
    {
        get
        {
            return Start.Y - slope*Start.X;
        }
    }

    public bool IsPointOnLine(Point p, int cushion)
    {
        float temp = (slope * p.X + YIntercept);
        if (temp >= (p.Y-cushion) && temp <=(p.Y+cushion))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

这个类提供了一些帮助函数,可以让我们的生活更轻松。我们有返回斜率和 Y 截距的属性,因此我们可以确定某个点是否在线上。然后,我们提供一个辅助函数 IsPointOnLine(),它接受一个点和一个缓冲。缓冲垫用于简单地允许用户在距离线足够近的地方单击以使其返回 true。

接下来我将实例化这条线并在窗体的绘制事件中绘制它:

MyLine m;

private void Form1_Load(object sender, EventArgs e)
{
    m= new MyLine(Pens.Black, new Point(20, 20), new Point(40, 40));
}



private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawLine(m.pen, m.Start, m.End);     
}

现在您应该能够运行您的应用程序并在屏幕上看到一条从 20,20 到 40,40 的行。

现在我想处理鼠标与线的交互,因此在 MouseDown 上,我们将查看单击点是否与线相交,以及是否设置了标志并保持与端点的增量。在 MouseMove 事件中,我们将查看该线是否已被单击但未释放,并相应地重置坐标。在 MouseUp 事件中,我们简单地重置我们的标志:

Point deltaStart;
Point deltaEnd;
bool dragging = false;

private void Form1_MouseDown(object sender, MouseEventArgs e)
{

    if (e.Button == System.Windows.Forms.MouseButtons.Left && m.IsPointOnLine(e.Location, 5))
    {
        dragging = true;
        deltaStart = new Point(m.Start.X - e.Location.X, m.Start.Y - e.Location.Y);
        deltaEnd = new Point(m.End.X - e.Location.X, m.End.Y - e.Location.Y);
    }
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (dragging && deltaStart != null && deltaEnd != null )
    {
        m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y);
        m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y);
        this.Refresh();
    }
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    dragging = false;
}

现在您应该能够在该线的 5 个像素范围内单击并使其随鼠标移动。

请注意,代码中的某些位置需要额外的错误处理,尤其是处理除 0 错误。

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

用鼠标移动绘制的线 的相关文章

  • Dapper 强类型查询返回默认对象值

    刚刚开始使用 Dapper 并喜欢它 我遇到了问题 它返回正确数量的对象 但它们的属性都有默认值 using var dbConnection Connection await dbConnection OpenAsync const st
  • 在两个 .cpp 文件之间定义全局变量 [重复]

    这个问题在这里已经有答案了 如何在 A cpp 和 B cpp 之间共享 全球化 bool 变量 其中它们都不包含其他 h 文件 他们有其他联合头文件 但彼此没有 我可以在这些共享标头中定义全局变量吗 Thanks 我可以在这些共享标头中定
  • ProtoBuf-net AsReference 需要 Activator.CreateInstance 中的公共构造函数吗?

    在我的两门课程中 看起来像这样 最少 using System using System Collections Generic using System Collections using System ComponentModel us
  • 浏览器收集哪些值作为回发数据?

    当页面被发送回服务器时 浏览器收集每个控件的当前值并将其粘贴到一个字符串中 然后 该回发数据通过 HTTP POST 发送回服务器 Q1 除了控件的 Text 属性和 SelectedIndexchanged 因此除了用户输入数据 之外 控
  • 将占位符文本添加到文本框

    我正在寻找一种将占位符文本添加到文本框的方法 就像在 html5 中使用文本框一样 IE 如果文本框没有文本 则会添加文本Enter some text here 当用户单击它时 占位符文本消失并允许用户输入自己的文本 如果文本框失去焦点并
  • CMake 警告:无法为目标生成安全的链接器搜索路径

    在为 pcl 项目运行 CMake 时 我收到一条警告消息 Configuring done CMake Warning at CMakeLists txt 12 add executable Cannot generate a safe
  • Windows 程序如何临时更改其时区?

    我写了一个函数来返回time t与给定日期的午夜相对应的值 当给定日期没有午夜时 它返回最早可用的时间 例如 当埃及进入夏令时时 这种情况就可能发生 今年 时间更改于 4 月 29 日晚上午夜生效 因此时钟直接从 23 59 转到 01 0
  • 使用正则表达式匹配以“Id”结尾的单词?

    如何组合一个正则表达式来匹配以 Id 结尾的单词并进行区分大小写的匹配 试试这个正则表达式 w Id b w 允许前面的单词字符Id和 b确保Id位于单词末尾 b是字边界断言
  • 基于 C++ 范围的 for 循环

    尝试使用基于范围的 for 循环执行某些操作 可以使用常规的 for 循环来完成 如下所示 vector
  • 使用对象列表构建树

    我有一个带有属性 id 和parent id 的对象列表 我想建造一棵树来连接那些孩子和父母 1 个父对象可以有多个子对象 并且有一个对象将成为所有对象的祖先 实现该功能最快的算法是什么 我使用 C 作为编程语言 但其他语言也可以 像这样的
  • IBM Watson 对话服务错误:无法从“方法组”转换为“conversation.onMessage”

    我正在尝试运行 IBM Watson会话服务团结和下面是代码片段 https github com watson developer cloud unity sdk conversation private Conversation m C
  • 如何使用 C# 代码使用超链接的 onClick 事件?

    我正在尝试为页面中的超链接添加条件 而不是仅仅使用特定的链接 例如 a href help Tutorial html Tutorial a 我想为不同的用户显示不同的页面 例如 如果用户以管理员身份登录 他们将看到与普通用户不同的链接 我
  • 使用 cudamalloc()。为什么是双指针?

    我目前正在浏览有关的教程示例http code google com p stanford cs193g sp2010 http code google com p stanford cs193g sp2010 学习CUDA 演示的代码 g
  • 语义问题 Qt Creator:命名空间“std”中没有名为“cout”的成员

    我开始使用 Qt Creator 编写代码 对于 C 文件 我遇到很多语义问题 99 是 命名空间 yyy 中没有名为 xxx 的成员cpp文件构建 编译和输出没有问题 如果我点击例如cout 我已链接到 iostream 我是否需要在 Q
  • C# - 命名空间内的类型声明

    在命名空间内而不是在类中声明类型的可能用途是什么 For ex namespace Test public delegate void Ispossible 这是有效的并且不会产生任何编译错误 但我无法想象为什么我们会以这种方式声明它而不是
  • 使 C# 编译器相信执行将在成员返回后停止

    我认为目前这是不可能的 或者这是否是一个好主意 但这是我刚才正在考虑的事情 我使用 MSTest 对我的 C 项目进行单元测试 在我的一项测试中 我执行以下操作 MyClass instance try instance getValue
  • printf 参数不足

    我的问题是关于缺少参数的 printf 之后的行为 printf s blah blah d int integer was given as argument and not int written 我已经知道 如果格式参数不足 则行为是
  • 无效的模板相关成员函数模板推导 - 认为我正在尝试使用 std::set

    我有一个继承自基类模板的类模板 基类模板有一个数据成员和一个成员函数模板 我想从我的超类中调用它 我知道为了消除对成员函数模板的调用的歧义 我必须使用template关键字 我必须明确引用this在超级班里 this gt base mem
  • Visual Studio 2015默认附加库

    当我在 VS 2015 中创建一个空项目时 它会自动将这些库放入 附加依赖项 中 kernel32 lib user32 lib gdi32 lib winspool lib comdlg32 lib advapi32 lib shell3
  • 如何获取通过网络驱动器访问的文件的 UNC 路径?

    我正在 VC 中开发一个应用程序 其中网络驱动器用于访问文件 驱动器由用户手动分配 然后在应用程序中选择驱动器 这会导致驱动器并不总是映射到相同的服务器 我该如何获取此类文件的 UNC 路径 这主要是为了识别目的 这是我用来将普通路径转换为

随机推荐

  • 使用回调将 C 库 (GSL) 包装在 cython 代码中

    我是新手cython and c 我想使用 cython 来加快代码的性能 我想用gsl integration我的代码中的库用于集成 更新 test gsl pyx cdef extern from math h double log d
  • 如何在Android中每分钟获取gps坐标?

    我想每分钟获取我的坐标 即使用户没有移动 所以我使用 requestLocationUpdates 和以下参数 locMgr requestLocationUpdates LocationManager GPS PROVIDER 60000
  • NSMutableArray 内的块泄漏 (ARC)

    我有一些在块内的操作 此操作 仅更新一个UIImage像这样 UIImage image self myImage image 我的图像是通过访问互联网来计算的NSURLConnection 当我从互联网上收到图像时 我称该块为NSMuta
  • 如何优化在 postgresql 中查询这些数据?

    我的查询对于特定行来说速度很慢 Postgres 选择做一个Seq Scan而不是使用Index Scan对于某些行 我认为是因为它实际上比使用索引更快 以下是针对正常工作负载使用索引的查询计划 http explain depesz co
  • 高效构建FEM/FVM矩阵

    这是 FEM FVM 方程系统的典型用例 因此可能会引起更广泛的兴趣 从三角形网格 la 我想创建一个scipy sparse csr matrix 矩阵行 列表示网格节点处的值 该矩阵在主对角线上以及两个节点通过边连接的地方都有条目 这是
  • 本地化 MPMoviePlayerViewController 的“完成”按钮

    我正在使用 MPMoviePlayerViewController 来呈现视频 一切都按预期工作 但如果我将设备的语言切换为例如德语 完成 按钮未本地化 我尝试访问该按钮并将其设置为我自己的按钮实现 如下所示 MPMoviePlayerVi
  • 使 openGL 线连接起来

    现在我创建了一个多边形 然后我做了同样的事情 但使用 line loop 来绘制轮廓 我现在的问题是 如果我将线条粗细设置为高 则线条不会连接 它们的末端需要更长 线宽 有没有办法解决这个问题 Thanks glMatrixMode GL
  • Rails 条件验证

    所以我这里有两个模型 class Screen lt ActiveRecord Base belongs to user validates screen size numericality gt less than or equal to
  • 在 c 可执行文件中运行数据 shellcode

    我正在研究这个c 程序 我在 64 位 x64 linux 上用 gcc 编译它 include
  • 新的 React Context API 是否会触发重新渲染?

    我一直在尝试理解新的 React Context API 并正在使用它 我只是想检查一个简单的情况 当提供者的数据更新时 所有内容都会重新呈现 Check Codesandbox 上的这个小例子 所以 在我的例子中 我有一个App组件 具有
  • Paypal 支付 REST API Web 体验配置文件

    我正在使用 PayPal Rest API 并将 PayPal 与付款集成 我设法使用以下代码创建网络体验配置文件 但我无法运行此代码 2 次 它表示该配置文件已存在 这是否意味着我必须创建一个配置文件并将其用于所有客户和所有交易 Web
  • hbase 扫描仪的排序结果

    如何以相同的任何排序顺序检索 hbase 列族 值 like列族 值 列 1 1列 3 2列 4 3列 2 4 HBase 本身不会这样做 相反 您可以使用 Result raw 1 方法检索 KeyValues 列表 将其放入 List
  • F# 匹配两个值

    我对 F 相当陌生 我想使用 match with 语法比较两个值 当我尝试比较两个值时 问题就出现了 如下所示 let value1 19 let isValue1 y match y with value1 gt y 1 gt y 我收
  • 如果存在可能的未定义行为,为什么编译器不会警告您?

    我正在读著名的未定义的行为可能导致时间旅行发帖并注意到这部分 首先 您可能会注意到循环中的逐一错误 控制 结果是该函数读取了超过末尾的一位 放弃之前的表数组 经典编译器不会 特别关心 它只会生成代码来读取 越界数组元素 尽管事实上这样做是
  • C#:如何将组合框等项目列表保存到 .NET 设置文件中?

    C 如何将组合框等项目列表保存到 NET 设置文件中 设置设计器允许您使用的唯一集合类型是 System Collections ArrayList 如果您确实使用 ArrayList 则其所有元素的类型都必须是可序列化的 具有 Seria
  • 遗留 C/C++ 项目中的死代码检测 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 您将如何进行 C C 代码中的死代码检测 我有一个相当大的代码库可供使用 并且至少 10 15 是死代码 有没有基于 Unix 的工具来识别这个区域
  • mongodb 和 mongomapper

    我有一个 Rails 应用程序 当前使用 activerecord 来存储和查询产品 每个产品都有一个类别和子类别 每个子类别由我可以在应用程序中创建的多个字段定义 由此 当用户想要输入特定产品时 他们会被按下相关的表单字段 这已经变得非常
  • 贝宝集成问题

    我无法弄清楚我的代码做错了什么 我收到错误 我们检测到该购物车存在问题 如果问题仍然存在 请联系商家 这是我正在提交的表格
  • python内部类的用途是什么?

    Python 的内部 嵌套类让我很困惑 有什么事情是没有他们就无法完成的吗 如果有的话 那是什么东西 引自http www geekinterview com question details 64739 内部类的优点 类的逻辑分组 如果一
  • 用鼠标移动绘制的线

    我试图通过用鼠标抓住一条绘制的线来移动它 这条线已经画好了Graphics DrawLine Pen P Point A Point B 创建线条并将其绘制在表单上绝对没有问题 我试过了 将行添加到GraphicsPath 这甚至没有划清界