在C#中透明面板中绘制一条移动线

在这方面似乎有一百万个问题,但我找不到一个可行的问题。 所以,我想这是问题1,000,001的时间。

我有一个带有PictureBoxPanel的自定义控件。 PanelPictureBox的孩子,具有透明背景。 这允许我绘制在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_transPen new Pen(Color.FromArgb(0, 0, 0, 0));

结果如下:

现在,如果我将其更改为:

 m_graphics.DrawLine(Pens.White, m_lastPoints[0], m_lastPoints[1]); 

我得到了这个,它显示了它应该做什么,而不是用白线,它们应该是透明的。

无需删除旧行! 只需使Panel无效并绘制新的,最好在Paint事件中。

为了实现这一点, Panel 不得覆盖 PictureBox 。 它必须在里面 ! 把它放在load或constructor事件中:

 yourPanel.Parent = yourPictureBox; yourPanel.Size = yourPictureBox.Size; yourPanel.Location = Point.Empty; 

(我知道你已经有了这个,但也许下一个人只看答案;-)

为避免闪烁,请使用double-buffered Panel

 class DrawPanel : Panel { public DrawPanel() { DoubleBuffered = true; } } 

实际上 ,如果你只想在加载的Image上绘制一些东西,你甚至不需要一个单独的Panel 。 只需画上PictureBox本身! 它有三个独立的层: BackgroundImageImageControl surface ..

以下是绘制Cursor控制线的最小代码:

 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事件中处理该列表。

该列表可能还应该包括颜色,笔宽和一些,所以设计一个类’drawAction’将有助于..