简体   繁体   English

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

[英]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 . 我有一个带有PictureBoxPanel的自定义控件。 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 ); ..或更好的是,是一个PictureboxLabel (具有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 .. 它具有三个独立的层: BackgroundImageImageControl 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM