0

Imagine a simple .Net 2.0 Windows-Form with a MultilineTextbox that fills the whole form. I want to (re-)draw a rectangle everytime a key is pressed. In the real application there is fare more logic about the position and stuff of the rectangle - but keep it simple.

I thought: "Lets first invalidate the TextBox and then draw the rectangle." But this doesnt work. The screen flickers shortly - thats it. If I remove the line "invaliate" a rectangle is drawn - but the old ones keep their position..

Whats wrong? And how do I repaint from scratch?

Thank you in advance for your answers!

private void OnKeyDown(object sender, KeyEventArgs e)
{
        textBox1.Invalidate();

        using (Graphics g = this.textBox1.CreateGraphics())
        {
            int startX = 100;
            int startY = 300;
            int height = 200;

            Brush brush = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

            Pen myPen = new Pen(Color.Black, 2);
            myPen.DashStyle = DashStyle.Dash;

            g.DrawRectangle(myPen, startX, startY, this.textBox1.Width, height);

            g.FillRectangle(brush, startX, startY, this.textBox1.Width, height);
        }
}
user799821
  • 218
  • 2
  • 10

3 Answers3

1

Call this.Invalidate(); on keypress, and move your drawing code to the OnPaint event where it is supposed to go. If you want to completely avoid flicker, you need to draw according to the following guide: C#, double buffer in WinForms?.

You should also keep a List<> of all you rects and draw each one OnPaint as your key press is not the only thing that can invalidate the form and cause a redraw.

Community
  • 1
  • 1
bizzehdee
  • 20,289
  • 11
  • 46
  • 76
1

Your approach is flawed. Invalidate() only requests a repaint but it is delayed and happens after you draw the rectangle. So it disappears again immediately.

A short (but wrong) fix would be to replace Invalidate() with Update(), but don't do that.

You'll have to move the drawing logic to the textBox1.Paint event. And your form needs a (boolean) property to decide whether to draw the Rectangle or not.

Your KeyDown should look like:

private void OnKeyDown(object sender, KeyEventArgs e)
{
    this.DrawRect = true;
    textBox1.Invalidate();
}
H H
  • 263,252
  • 30
  • 330
  • 514
  • I like the short (wrong) fix because it seems to work - what's wrong about it? – user799821 Aug 08 '13 at 10:38
  • 1
    Very inefficient, and you'll lose the Rect when something else Invalidates the Form. – H H Aug 08 '13 at 10:40
  • If i press a key nothing happens. If i press the key and move the mouse over the area or out of the area- the rectangle is drawn - strange ... – user799821 Aug 08 '13 at 10:52
-1

I was told to use "textBox1.Refresh()" instead of "textBox1.Invalidate();" and it works!

private void OnKeyDown(object sender, KeyEventArgs e)
{
    //textBox1.Invalidate(); - Dont do that
    textBox1.Refresh(); //Dominik Schelenz, my internet Hero for today!

    using (Graphics g = this.textBox1.CreateGraphics())
    {
        int startX = 100;
        int startY = 300;
        int height = 200;

        Brush brush = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

        Pen myPen = new Pen(Color.Black, 2);
        myPen.DashStyle = DashStyle.Dash;

        g.DrawRectangle(myPen, startX, startY, this.textBox1.Width, height);

        g.FillRectangle(brush, startX, startY, this.textBox1.Width, height);
    }
}
user799821
  • 218
  • 2
  • 10
  • [Refresh() is the same as Update()](http://stackoverflow.com/a/952964/60761). Meaning this is not an efficient way to do this. – H H Aug 12 '13 at 13:52
  • Yes I know - http://blogs.msdn.com/b/subhagpo/archive/2005/02/22/378098.aspx - but Refresh Works and other solutions didnt - so I stick with it. – user799821 Aug 12 '13 at 14:12
  • Did you test it with Invalidate caused by other events? – H H Aug 12 '13 at 14:56