C# 在透明面板中绘制移动线
Drawing a moving line in a transparent panel in C#
似乎有一百万个问题,但我找不到一个可行的。所以,我想现在是问题 1,000,001 的时候了。
我有一个带有 PictureBox
和 Panel
的自定义控件。 Panel
是具有透明背景的 PictureBox
的子项。这允许我在 PictureBox
中加载的任何图像之上绘制。
绘图部分有效,但擦除部分无效。如果我使用 Invalidate()
,我只会出现一堆闪烁,而且这条线甚至都不会显示。
如果最终目标不明显,它应该像任何体面的绘图应用程序一样工作,您可以在其中单击一个点,四处拖动,然后线会随着鼠标移动,直到您松开为止。
代码:
private void drawLine(Point pt) {
// Erase the last line
if (m_lastPoints != null) {
m_graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
m_graphics.DrawLine(m_transPen, m_lastPoints[0], m_lastPoints[1]);
}
// Set the last points
m_lastPoints = new Point[] { m_mouseStartPoint, pt };
m_graphics.DrawLine(new Pen(m_color), m_mouseStartPoint, pt);
}
m_transPen
定义为 new Pen(Color.FromArgb(0, 0, 0, 0));
结果:
现在,如果我将其更改为:
m_graphics.DrawLine(Pens.White, m_lastPoints[0], m_lastPoints[1]);
我明白了,它显示了它应该做什么,只是白线应该是透明的,而不是白线。
无需删除旧行!只需使 Panel
无效并绘制新的,最好在 Paint
事件中。
但是要使它起作用,Panel
不能覆盖PictureBox
。一定是里面的啦!将其放入加载或构造函数事件中:
yourPanel.Parent = yourPictureBox;
yourPanel.Size = yourPictureBox.Size;
yourPanel.Location = Point.Empty;
(我知道你已经答对了,但也许下一个人只会看答案;-)
为避免闪烁 使用double-buffered Panel
..:[=30=]
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}
..或者,更好的是,一个 Picturebox
或一个 Label
(与 Autosize=false
);两者都开箱即用 DoubleBuffered
属性 并且比 Panels
更好地支持绘图。
实际上,如果你只想在加载的 Image
之上绘制一些东西,你甚至不需要单独的 Panel
。只需利用 PictureBox
本身!它具有三个独立层:BackgroundImage
、Image
和 Control surface
..
这是绘制光标控制线的最少代码:
pictureBox1.MouseDown += pictureBox1_MouseDown;
pictureBox1.MouseMove += pictureBox1_MouseMove;
pictureBox1.MouseUp += pictureBox1_MouseUp;
pictureBox1.Paint += pictureBox1_Paint;
// class level
Point mDown = Point.Empty;
Point mCurrent = Point.Empty;
void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (mDown != Point.Empty) e.Graphics.DrawLine(Pens.White, mDown, mCurrent);
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
mDown = Point.Empty;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
mCurrent = e.Location;
pictureBox1.Invalidate();
}
}
void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
松开鼠标按钮时,线条消失。
要使其永久化,您需要将其两个点存储在绘制它们所需的数据列表中,并在 Paint
事件中处理该列表。
该列表可能还应该包括颜色、笔宽等等,因此设计 class 'drawAction' 会有所帮助..
似乎有一百万个问题,但我找不到一个可行的。所以,我想现在是问题 1,000,001 的时候了。
我有一个带有 PictureBox
和 Panel
的自定义控件。 Panel
是具有透明背景的 PictureBox
的子项。这允许我在 PictureBox
中加载的任何图像之上绘制。
绘图部分有效,但擦除部分无效。如果我使用 Invalidate()
,我只会出现一堆闪烁,而且这条线甚至都不会显示。
如果最终目标不明显,它应该像任何体面的绘图应用程序一样工作,您可以在其中单击一个点,四处拖动,然后线会随着鼠标移动,直到您松开为止。
代码:
private void drawLine(Point pt) {
// Erase the last line
if (m_lastPoints != null) {
m_graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
m_graphics.DrawLine(m_transPen, m_lastPoints[0], m_lastPoints[1]);
}
// Set the last points
m_lastPoints = new Point[] { m_mouseStartPoint, pt };
m_graphics.DrawLine(new Pen(m_color), m_mouseStartPoint, pt);
}
m_transPen
定义为 new Pen(Color.FromArgb(0, 0, 0, 0));
结果:
现在,如果我将其更改为:
m_graphics.DrawLine(Pens.White, m_lastPoints[0], m_lastPoints[1]);
我明白了,它显示了它应该做什么,只是白线应该是透明的,而不是白线。
无需删除旧行!只需使 Panel
无效并绘制新的,最好在 Paint
事件中。
但是要使它起作用,Panel
不能覆盖PictureBox
。一定是里面的啦!将其放入加载或构造函数事件中:
yourPanel.Parent = yourPictureBox;
yourPanel.Size = yourPictureBox.Size;
yourPanel.Location = Point.Empty;
(我知道你已经答对了,但也许下一个人只会看答案;-)
为避免闪烁 使用double-buffered Panel
..:[=30=]
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}
..或者,更好的是,一个 Picturebox
或一个 Label
(与 Autosize=false
);两者都开箱即用 DoubleBuffered
属性 并且比 Panels
更好地支持绘图。
实际上,如果你只想在加载的 Image
之上绘制一些东西,你甚至不需要单独的 Panel
。只需利用 PictureBox
本身!它具有三个独立层:BackgroundImage
、Image
和 Control surface
..
这是绘制光标控制线的最少代码:
pictureBox1.MouseDown += pictureBox1_MouseDown;
pictureBox1.MouseMove += pictureBox1_MouseMove;
pictureBox1.MouseUp += pictureBox1_MouseUp;
pictureBox1.Paint += pictureBox1_Paint;
// class level
Point mDown = Point.Empty;
Point mCurrent = Point.Empty;
void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (mDown != Point.Empty) e.Graphics.DrawLine(Pens.White, mDown, mCurrent);
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
mDown = Point.Empty;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
mCurrent = e.Location;
pictureBox1.Invalidate();
}
}
void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
松开鼠标按钮时,线条消失。
要使其永久化,您需要将其两个点存储在绘制它们所需的数据列表中,并在 Paint
事件中处理该列表。
该列表可能还应该包括颜色、笔宽等等,因此设计 class 'drawAction' 会有所帮助..