建议:在PictureBox之间拖放 [英] Suggestion: Drag and Dropping Between PictureBoxes

查看:70
本文介绍了建议:在PictureBox之间拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我提供了2张图片,以便您更轻松地理解我的问题, 由于我是新成员,因此无法在此处直接链接它们,因此我将它们放在了Dropbox的公共文件夹中,

I have included 2 images so you can understand my question easier, I could not link them directly in here as I am a new member, so I have put them in my Dropbox public folder,

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

在这里您可以在左侧看到组面板", 嵌套有6个较小的盒子,它们都是图片框",

Here you can see a Group Panel on the left, With 6 smaller boxes nested they are all "pictureBoxes",

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

Then on the right is a larger picture Box, with a smaller one nested inside,

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

在这里您可以看到左侧加载的图像(请忽略图像的失真,这是我会在之后解决的问题)

Here you can see the images loaded on the left (Please ignore the distortion of the images, this is something I will fix after)

我需要做的是将一些图像(短语)从左侧拖动到右侧的圆圈中的段"中,

What I need to do, is drag some images (the phrases) from the left hand side, into the circle in the right hand side, within the "segments",

然后,我想保存圆圈,并将新图像拖放到圆圈上(我将执行drawToBitmap),我只想知道对我而言最好的方法是什么?

Then I want to save the circle, with the new images that have been dragged on top of it (which I will do a drawToBitmap), I just want to know what is the best way for me to go about this?

请提出一些建议,

我现在可以在左侧移动图像,但是由于当前只能在其图片框内移动而只能移动很小的图像,

I can move the images on the left at the moment, but only a tiny amount as they are currently restricted to only move within their picture Box,

推荐答案

您的问题包括三个任务:

Your problem consists of three tasks:

  • 移动Controls(在这里为PictureBoxes).
  • 检查以查看他们降落的地方
  • 放置它们,使它们加入目标区域
  • Moving Controls (here: PictureBoxes) around.
  • Checking to see where they have landed
  • Placing them in a way that makes them join in the target area

以下是有关每个任务的一些提示:

Here are a few hints about each task:

  • 要移动Controls,最好使用MouseDown存储起点,并使用MouseMove事件更新移动控件的Location.在MouseUp事件中,您可以完成操作:也许处理命中,重置控件,输出用户消息等.
  • To move the Controls it is best to use the MouseDown to store a starting point and the MouseMove event to update the Location of the moving control. And in the MouseUp event you can finalize the action: Maybe process the hit, reset the control, output user messages, etc..

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

Note that the events belong to each control you to move, but if you map them to the same three events for all controls you can use the sender parameter to move the right Control. Much better than repeating the same code n times..

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

(One can even write a reusable function makeMoveable(Control ctl) to make any Control moveable; this could involve three lambda expressions for the three events..)

还要注意,如果您的控件最初位于某个容器内,则说一个Panel,您将需要将其Parent更改为最好的Form;在这里,您还需要根据原始父对象的偏移量来调整位置,并且需要使用BringtoFront()使它们移到窗体上所有其他控件的上方.

Also note that if your controls originally sit inside some container, say a Panel you will need to change their Parent to be, probably best, the Form; here you also will need to adapt the location by the offset of the original parent and you need to use BringtoFront() to make them move above all other controls on the Form..

  • 对于命中测试,您需要检查新位置是否在圆弧段内.段的形状比Rectangle更复杂.复杂的形状可以通过在GraphicsPath中添加简单的内容来构造.
  • For hit testing you need to check if the new location is inside a segment of a circle. A segment is a more complicated shape than, say a Rectangle. Complicated shapes can be constructed by adding simple things to a GraphicsPath.

Rectangles还具有Rectangle.Contains(Point)功能,因此似乎更易于命中测试.出于特殊原因,GraphicsPaths的相同功能被命名为GraphicsPath.IsVisible(Point).

Rectangles also seem easier for hit testing since they have a Rectangle.Contains(Point) function. For no special reason the same function for GraphicsPaths goes by the name GraphicsPath.IsVisible(Point).

  • 如果您有组成整个圆圈的GraphicsPaths列表,则可以使用它来限制绘图,并在使用Graphics.SetClip(segment)后直接将正确的图像绘制到圆圈上.
  • If you have a list of GraphicsPaths that make up the full circle you can use it to restrict the drawing and draw the right image directly onto the circle after using Graphics.SetClip(segment).

为了让您开始使用细分,这里是一个创建细分并将其绘制在Paint事件中的PictureBox pb_target上的函数.请注意,两个Arcs的绘制方向相反,因此Closing Path不会创建交叉连接!

To get you going with segments here is a function that creates a segment and paints it onto a PictureBox pb_target in its Paint event. Note that the two Arcs are drawn in opposite directions so that Closing the Path will not create crossing connections!

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例程中的中心和尺寸.

You don't need the painting code above in the final version but it will help you to fine tune the coordinates, i.e. the center and the sizes in the getSegment routine..

这里严格测试的是目标PB的MouseMove事件:

Strictly for testing here is a MouseMove event for the target 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";

    }
}

请注意,片段是从左开始顺时针计数的..

Note the the segments count clockwise from the left..

这篇关于建议:在PictureBox之间拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆