建议:在图片框之间拖放
Suggestion: Drag and Dropping Between PictureBoxes
我包含了 2 张图片,以便您更容易理解我的问题,
由于我是新会员,我不能直接 link 它们在这里,所以我把它们放在我的 Dropbox public 文件夹中,
图 1:设计视图
https://www.dropbox.com/s/wca5gstd8kdsie7/designView.png?dl=0
在这里你可以看到左边有一个群组面板,
嵌套了 6 个较小的盒子,它们都是 "pictureBoxes",
然后右边是一个大一点的图片Box,里面嵌套了一个小一点的,
图2应用运行
https://www.dropbox.com/s/u5bknooks17of1r/appView.png?dl=0
在这里你可以看到左边加载的图片(请忽略图片的失真,这是我稍后会修复的)
我需要做的是,将一些图像(短语)从左侧拖到右侧的圆圈中,在 "segments"、
内
然后我想保存这个圆圈,将新图像拖到它上面(我会做一个 drawToBitmap),我只是想知道什么是我做这个的最好方法?
请提出一些建议,
我现在可以移动左边的图片,但只能移动很小的一部分,因为它们目前仅限于在图片框内移动,
您的问题包括三个任务:
- 移动
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
pb_target 事件中的 PictureBox
pb_target 上。请注意,两个 Arcs
的绘制方向相反,因此 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
例程中的中心和大小..
此处严格用于测试的是目标 PB 的 MouseMove
事件:
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";
}
}
注意段从左边顺时针计数..
我包含了 2 张图片,以便您更容易理解我的问题, 由于我是新会员,我不能直接 link 它们在这里,所以我把它们放在我的 Dropbox public 文件夹中,
图 1:设计视图 https://www.dropbox.com/s/wca5gstd8kdsie7/designView.png?dl=0
在这里你可以看到左边有一个群组面板, 嵌套了 6 个较小的盒子,它们都是 "pictureBoxes",
然后右边是一个大一点的图片Box,里面嵌套了一个小一点的,
图2应用运行 https://www.dropbox.com/s/u5bknooks17of1r/appView.png?dl=0
在这里你可以看到左边加载的图片(请忽略图片的失真,这是我稍后会修复的)
我需要做的是,将一些图像(短语)从左侧拖到右侧的圆圈中,在 "segments"、
内然后我想保存这个圆圈,将新图像拖到它上面(我会做一个 drawToBitmap),我只是想知道什么是我做这个的最好方法?
请提出一些建议,
我现在可以移动左边的图片,但只能移动很小的一部分,因为它们目前仅限于在图片框内移动,
您的问题包括三个任务:
- 移动
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
pb_target 事件中的 PictureBox
pb_target 上。请注意,两个 Arcs
的绘制方向相反,因此 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
例程中的中心和大小..
此处严格用于测试的是目标 PB 的 MouseMove
事件:
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";
}
}
注意段从左边顺时针计数..