[英]Drawing a moving line in a transparent panel in C#
There seems to be a million questions out there on this, yet I can't find one that will work. 关于这一点似乎有一百万个问题,但我找不到一个可行的问题。 So, I guess it's time for question 1,000,001.
因此,我想是时候提出问题1,000,001了。
I have a custom control with a PictureBox
and a Panel
. 我有一个带有
PictureBox
和Panel
的自定义控件。 The Panel
is the child of PictureBox
with a transparent background. Panel
是具有透明背景的PictureBox
的子级。 This allows me tp draw on top of whatever image is loaded in the PictureBox
. 这使我可以在
PictureBox
加载的任何图像之上进行tp绘制。
The drawing part works, but the erasing part does not. 绘图部分有效,但擦除部分无效。 And if I use
Invalidate()
I just get a bunch of flickering, and the line never even shows. 而且,如果我使用
Invalidate()
我只会出现一堆闪烁,而且该行甚至不会显示。
If the end goal isn't obvious, it should work like any decent drawing application, where you click in one spot, drag around, and the line moves with the mouse until you let go. 如果最终目标不明显,则它应像任何体面的绘图应用程序一样工作,在其中单击一个点,然后四处拖动,然后用鼠标移动线条,直到松开为止。
Code: 码:
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
is defined as new Pen(Color.FromArgb(0, 0, 0, 0));
m_transPen
被定义为new Pen(Color.FromArgb(0, 0, 0, 0));
m_transPen
new Pen(Color.FromArgb(0, 0, 0, 0));
And the result: 结果:
Now, if I change it to: 现在,如果我将其更改为:
m_graphics.DrawLine(Pens.White, m_lastPoints[0], m_lastPoints[1]);
I get this, which shows what it should be doing, only instead of with white lines, they should be transparent. 我得到了这个,它显示了它应该做的事情,只应该是透明的,而不是白线。
No need to erase the old line! 无需删除旧行! Just invalidate the
Panel
and draw the fresh one, best in the Paint
event. 只是使
Panel
无效,并在Paint
事件中最好地绘制一个新的Panel
。
But for this to work, the Panel
must not overlay the PictureBox
. 但是 ,要使其正常工作,
Panel
不得覆盖 PictureBox
。 It must be inside it! 它必须在里面 ! Put this in the load or constructor event :
将其放入load或构造函数事件中:
yourPanel.Parent = yourPictureBox;
yourPanel.Size = yourPictureBox.Size;
yourPanel.Location = Point.Empty;
(I know you got that one right already, but maybe the next person only looks at the answer ;-) (我知道您已经正确了,但是也许下一个人只会看答案;-)
To avoid flicker use a double-buffered Panel
..: 为避免闪烁,请使用
double-buffered Panel
..:
class DrawPanel : Panel
{
public DrawPanel()
{
DoubleBuffered = true;
}
}
..or, better yes, a Picturebox
or a Label
(with Autosize=false
); ..或更好的是,是一个
Picturebox
或Label
(具有Autosize=false
); both have the DoubleBuffered
property turned on out of the box and support drawing better than Panels
do. 两者都具有
DoubleBuffered
即用的DoubleBuffered
属性,并且比Panels
更好地支持绘图。
Actually , if you only want to draw something on top of the loaded Image
, you don't even need a separate Panel
. 实际上 ,如果您只想在加载的
Image
之上绘制东西,甚至不需要一个单独的Panel
。 Just draw on the PictureBox
itself! 只需在
PictureBox
本身上绘制即可! It has three independent layers: BackgroundImage
, Image
and the Control surface
.. 它具有三个独立的层:
BackgroundImage
, Image
和Control surface
..
Here is the minimal code to draw a Cursor controlled line: 这是绘制光标控制线的最少代码:
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;
}
The line disappears when you release the mouse button. 释放鼠标键时,该行消失。
To make it permanent you need to store its two points in a list of data needed to draw them and work through that list in the Paint
event. 要使其永久化,您需要将其两个点存储在绘制它们并在
Paint
事件中遍历该列表所需的数据列表中。
That list should probably also include the color, pen width and then some, so designing a class 'drawAction' will help.. 该列表可能还应该包括颜色,笔的宽度,然后再加上一些,因此设计类“ drawAction”将有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.