views:

591

answers:

5

Can I draw a rectangle with mouseClick?My code is not working so far.Can you help me?

    private void panel1_MouseClick(object sender, MouseEventArgs e)
    {
            Graphics g = this.CreateGraphics();
            Pen pen = new Pen(Color.Black, 2);

            g.DrawRectangle(pen, 100,100, 100, 200);
    }
A: 

You should draw it in "Paint" event of the control (panel1 in this case).

TcKs
+1  A: 

Try this code with a PictureBox instead (just to get you started - there are many different ways of doing this):

private void pictureBox1_Click(object sender, EventArgs e)
{
    if (pictureBox1.Image == null)
    {
            pictureBox1.Image = new Bitmap(pictureBox1.width, 
                    pictureBox1.height);
    }
    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
    {
        // draw black background
        g.Clear(Color.Black);
        Rectangle rect = new Rectangle(100, 100, 200, 200);
        g.DrawRectangle(Pens.Red, rect);
    }
    pictureBox1.Invalidate();
}

This technique will automatically "persist" your drawing, meaning that it won't disappear if another windows gets dragged across it. When you draw to a control directly (what you're trying to do with the CreateGraphics() call) you usually run into the problem of non-persistency.

Update: here's another answer with a more detailed example of drawing something in response to where the mouse is clicked:

http://stackoverflow.com/questions/1537090/how-to-draw-drawings-in-picture-box/1537208#1537208

MusiGenesis
A: 

Can I draw a rectangle with mouseClick?

If you mean "When the mouse is clicked on my panel I want to display a rectangle" then you can do that like this:

        private bool displayRectangle = false;

        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            displayRectangle = true;
            panel1.Invalidate(false);
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            if (displayRectangle)
            {
                using (Pen p = new Pen(Color.Black, 2))
                {
                    e.Graphics.DrawRectangle(p, 100, 100, 100, 200);
                }
            }
        }

If you mean "I want to drag the mouse on my panel to create rectangles" then you have a little more work to do.

You need to handle the mouse up, move and down events tracking the delta between the mouse down point and the current position. Finally, on mouse up, you would draw your rectangle. It gets more complicated because you need to use double buffering or an 'xor' rectangle to draw the "drag" rectangle.

These two threads may help:

http://stackoverflow.com/questions/1086989/dragging-picturebox-inside-winform-on-runtime

http://stackoverflow.com/questions/359229/snap-to-grid-mouse-locking-up/359922#359922

As I see it, the main problem with rendering custom graphics inside a control's Paint event like this is that the code gets called every time the control is repainted. With just a simple rectangle, it's not really a problem, but with complex graphics it can easily become one. Better to render once to a separate surface and then copy from that surface to the control in its Paint event (which is essentially what my example is doing).
MusiGenesis
@MusiGenesis - Hence my point about using double buffering.
So you down-voted my perfectly valid answer?
MusiGenesis
+1  A: 

Edited version:

Without much assumpition of what you trying to do:

private void panel1_Click(object sender, EventArgs e) {
    using (Graphics g = this.panel1.CreateGraphics()) {
        Pen pen = new Pen(Color.Black, 2);
        Brush brush = new SolidBrush(this.panel1.BackgroundColor);

        g.DrawRectangle(pen, 100,100, 100, 200);

        pen.Dispose();
    }
}

Your code did not work as it is drawing the rectangle on the window (this) and the drawn rectangle is then hidden by your panel.

Generally overriding Paint for such a simple case is just too much effort for just drawing a rectangle on a panel. However, drawing the rectangle in this way works, but the rectangle will disapear when the form is redrawn (e.g. by minimizing and subsequently showing the form again. If the rectangle has to be persistent you will have to use the paint method and for this you will have to (e.g.) create the rectangle in the click event and then draw it in the paint event. (See roygbiv's solution for such an approach). Note: If you go along with the paint method, you should keep it as efficient as possible, as the paint method gets called verry frequently.

Edit 2

You do not need to clear the background as your rectangle will be drawn always at the same place. In order to draw the rectangle at the point where the user cliced (it is an assumption that this is what you want) you should move the code to the mouse down event, e.g.:

private void panel1_MouseDown(object sender, MouseEventArgs e) {
    using (Graphics g = this.panel1.CreateGraphics()) {
        Pen pen = new Pen(Color.Black, 2);
        Brush brush = new SolidBrush(this.panel1.BackColor);

        g.FillRectangle(brush, this.panel1.Bounds);  // redraws background
        g.DrawRectangle(pen, e.X, e.Y, 20, 20);

        pen.Dispose();
        brush.Dispose();
    }
}
Obalix
@Obalix - Your solution is incorrect. `1.)` You do not dispose of either the pen or the graphics objects which you create. `2.)` When the form is repainted the rectangle is lost.
@roygbiv: The solution is not incorrect following the OP (see my first line). Is the solution optimal ... well it depends on the requirements the original author has. For 1.) you are right, the objects should be disposed. For 2.) you are right too ... but is it a requirement that the rectanlge stays present? Cant see that in the OP.
Obalix
Thank you.Yes your answer is working for me.Further I want to disappear the previous rectangle which has drawn after mouse click when I clicked again.How can I do that?
C. Karunarathne
@Obalix - You are simply leading the OP down the wrong path.
@C. Karunarathne - You can do that by demonstrating to us what you have done so far to implement that feature.
If I say in details there I have drawn grids in my panel and there have placed labels on it.There are remaining spaces also which are not filled labels.What I want is to click a cell in a space of grid and place a label in that space which lie on another panel.So far I can do the placement and what I am looking for is to when I click on the cell display it highlighted for recognition.If I click on another cell the previous highlight must be disappear.
C. Karunarathne
@C. Karunarathne: See new edit.
Obalix
@roygbiv: Never assume too much ... ;-) ... Your, solution is valid too though !
Obalix
nop! mouse down event doesn't work.It deletes the grid that drawn on the panel.I want to delete the old rectangle and draw a new rectangle.
C. Karunarathne
A: 

Try the below link. it will draw the rectangle on the picture box image where user like.

http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=87153

Nivas