Suggestion: Drag and Dropping Between PictureBoxes

戏子无情 提交于 2019-12-12 06:17:02

问题


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,

Image 1: Design View https://www.dropbox.com/s/wca5gstd8kdsie7/designView.png?dl=0

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,

Image 2 Application Running 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",

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?

Some suggestion please would be appreciated,

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,


回答1:


Your problem consists of three tasks:

  • 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:

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

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

(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..)

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

  • 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 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).

  • 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).

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);
    }

}

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

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



来源:https://stackoverflow.com/questions/28533983/suggestion-drag-and-dropping-between-pictureboxes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!