How to draw shapes in WinForms

2020-01-24 13:58发布

I'm trying to code paint-like programme. You can draw filled shapes by selecting which shape you want, click picturebox and drag mouse to get which size you want. But THIS can happens when I drag. When I use refresh();, shapes -which previously drawn- deletes itself. What should I do to draw filled shapes?

private void CizimPicture_MouseDown(object sender, MouseEventArgs e)
    {
        Cursor = Cursors.Cross;
        if (e.Button == MouseButtons.Left)
        {
            cizim = true;
        }
        X1 = e.X;
        Y1 = e.Y;
    }

    private void CizimPicture_MouseUp(object sender, MouseEventArgs e)
    {
        Cursor = Cursors.Default;
        cizim = false;
    }

    private void CizimPicture_MouseMove(object sender, MouseEventArgs e)
    {
        if (!cizim) return;

        if (cizim == true)
        {
            X = e.X;
            Y = e.Y;
            X2 = (e.X - X1);
            Y2 = (Y1 - e.Y);

            if (dikdörtgen == true)
            {
                resmim.FillRectangle(renk.Brush, X1, Y1, X2, -Y2);
            }
            if (elips == true)
            {
                resmim.FillEllipse(renk.Brush, X1, Y1, X2, -Y2);
            }
        }

    }

标签: c# winforms
1条回答
▲ chillily
2楼-- · 2020-01-24 14:37

I looked for sample code that was both simple and worked and did not find anything. You do not need offscreen bitmaps or CreateGraphics for this, but you will need to handle tracking the mouse position, drawing to the screen, and adding drawn shapes to a list of shapes as Eric suggests. To handle interactive drawing you need to store the mouse state, initial click position, and current rectangle in your form handler:

bool mouseDown;
Point clickPos;
Rectangle rect;

Then when the user clicks, remember the initial position:

private void MouseDown(object sender, MouseEventArgs e)
{
    mouseDown = true;
    clickPos = e.Location;
    rect = new Rectangle(clickPos, new Size(0, 0));
}

While the user drags with the mouse down, create a rectangle encompassing the start and current location:

private void MouseMove(object sender, MouseEventArgs e)
{
    if (mouseDown)
    {
        this.Invalidate(rect);
        if (e.Location.X > clickPos.X && e.Location.Y > clickPos.Y)
        {
            rect = new Rectangle(clickPos.X, clickPos.Y, e.Location.X - clickPos.X, e.Location.Y - clickPos.Y);
        }
        else if (e.Location.X > clickPos.X && e.Location.Y < clickPos.Y)
        {
            rect = new Rectangle(clickPos.X, e.Location.Y, e.Location.X - clickPos.X, clickPos.Y - e.Location.Y);
        }
        else if (e.Location.X < clickPos.X && e.Location.Y < clickPos.Y)
        {
            rect = new Rectangle(e.Location.X, e.Location.Y, clickPos.X - e.Location.X, clickPos.Y - e.Location.Y);
        }
        else if (e.Location.X < clickPos.X && e.Location.Y > clickPos.Y)
        {
            rect = new Rectangle(e.Location.X, clickPos.Y, clickPos.X - e.Location.X, e.Location.Y - clickPos.Y);
        }

        this.Invalidate(rect);
    }
}

When the user releases the mouse, stop drawing:

private void MouseUp(object sender, MouseEventArgs e)
{
    mouseDown = false;
}

The #1 most important rule in Windows Forms is: only draw to the screen in the Paint event. Never never draw in the MouseMoved event:

private void Paint(object sender, PaintEventArgs e)
{
    e.Graphics.FillRectangle(Brushes.DarkGray, rect);
}

Once you get this working, create a form List<Rectangle> and add the current rectangle in the MouseUp event and draw all rectangles in the Paint event. You might also want to clip your drawing to the panel or window you are drawing in. You can also do some optimizations in MouseMoved to only invalidate the changed screen region, not both the old and new rectangles.

查看更多
登录 后发表回答