建议:在PictureBoxes之间拖放

时间:2015-02-16 03:06:15

标签: c# visual-studio-2013 drag-and-drop picturebox

我已经包含了2张图片,因此您可以更轻松地理解我的问题, 我不能直接在这里链接它们,因为我是新成员,所以我把它们放在我的Dropbox公共文件夹中,

图片1:设计视图 https://www.dropbox.com/s/wca5gstd8kdsie7/designView.png?dl=0

在这里你可以看到左边的一个组面板, 嵌套了6个较小的盒子,它们都是" pictureBoxes",

然后在右边是一个较大的图片框,其中一个较小的嵌套在里面,

图片2应用程序正在运行 https://www.dropbox.com/s/u5bknooks17of1r/appView.png?dl=0

在这里你可以看到左边加载的图像(请忽略图像的失真,这是我将要修复的内容)

我需要做的是将一些图像(短语)从左侧拖入右侧的圆圈,在"段内#34;

然后我想要保存圆圈,将新图像拖到它上面(我会做一个drawToBitmap),我只是想知道对我来说最好的方法是什么?< / p>

一些建议请不胜感激,

我现在可以移动左边的图像,但只有很少量,因为它们目前仅限于在图片框内移动,

1 个答案:

答案 0 :(得分:0)

您的问题包含三个任务:

  • 移动Controls(此处:PictureBoxes)。
  • 检查他们降落的位置
  • 以使其加入目标区域的方式放置它们

以下是关于每项任务的一些提示:

  • 要移动Controls,最好使用MouseDown存储起点和MouseMove事件来更新移动控件的Location。在MouseUp事件中,您可以完成操作:可能处理命中,重置控件,输出用户消息等。

请注意,事件属于您要移动的每个控件,但如果您将它们映射到所有控件的相同三个事件,则可以使用sender参数移动右Control。比重复相同的代码n次要好得多..

(甚至可以编写一个可重用的函数makeMoveable(Control ctl)来使任何Control可移动;这可能涉及三个事件的三个​​lambda表达式。)

另请注意,如果您的控件最初位于某个容器内,比如Panel,则需要将Parent更改为Form,最好是BringtoFront();在这里,您还需要根据原始父项的偏移量调整位置,并且需要使用Rectangle使它们移动到表单上的所有其他控件之上。

  • 对于点击测试,您需要检查新位置是否在圆圈段内。段是比GraphicsPath更复杂的形状。可以通过向Rectangles添加简单的内容来构造复杂的形状。

Rectangle.Contains(Point) 似乎更容易进行点击测试,因为它们具有GraphicsPaths功能。没有特殊原因,GraphicsPath.IsVisible(Point)的相同功能名为GraphicsPaths

  • 如果您有一个构成整个圆圈的Graphics.SetClip(segment)列表,您可以使用它来限制绘图,并在使用PictureBox后将正确的图像直接绘制到圆圈上。

为了让您使用细分,这里有一个函数可以创建一个细分并将其绘制到Paint事件中的Arcs pb_target中。请注意,两个Closing的绘制方向相反,因此Path List<GraphicsPath> segments = new List<GraphicsPath>(); private void Form4_Load(object sender, EventArgs e) { PointF center = new PointF(pb_target.Width / 2f, pb_target.Height / 2f); float angle = 60f; for (int i = 0; i < 360 / angle; i++) { segments.Add(getSegment(center, pb_target.Width / 2.5f, pb_target.Width / 4f, i * angle, angle)); } } GraphicsPath getSegment(PointF center, float radius, float width, float startAngle, float angle) { GraphicsPath gp = new GraphicsPath(); float radI = radius - width; RectangleF OunterBounds = new RectangleF(center.X - radius, center.Y - radius, 2 * radius, 2 * radius); RectangleF InnerBounds = new RectangleF(center.X - radI, center.Y - radI, 2 * radI, 2 * radI); gp.AddArc(OunterBounds, startAngle, angle); gp.AddArc(InnerBounds, startAngle + angle, -angle); gp.CloseFigure(); return gp; } private void pb_target_Paint(object sender, PaintEventArgs e) { for (int i = 0; i < segments.Count; i++) { GraphicsPath gp = segments[i]; e.Graphics.FillPath(Brushes.Gainsboro, gp); e.Graphics.DrawPath(Pens.SlateBlue, gp); } } 不会创建交叉连接!

getSegment

您在最终版本中不需要上面的绘画代码,但它可以帮助您微调坐标,即MouseMove例程中的中心和大小。

此处严格测试是针对目标PB的private void pb_target_MouseMove(object sender, MouseEventArgs e) { for (int i = 0; i < segments.Count; i++) { GraphicsPath gp = segments[i]; if (gp.IsVisible(e.Location)) { Text = "Inside segment #" + i; break; } else Text = "Outside of the Circle"; } } 事件:

{{1}}

请注意,这些段从左侧顺时针计数..