61

My program draws text on its panel,but if I'd like to remove the text I have to repaint.

How do I call(raise) the paint event by hand?

H H
  • 263,252
  • 30
  • 330
  • 514
Ivan Prodanov
  • 34,634
  • 78
  • 176
  • 248

8 Answers8

107

In a method of your Form or Control, you have 3 choices:

this.Invalidate();  // request a delayed Repaint by the normal MessageLoop system    
this.Update();      // forces Repaint of invalidated area 
this.Refresh();     // Combines Invalidate() and Update()

Normally, you would just call Invalidate() and let the system combine that with other Screen updates. If you're in a hurry you should call Refresh() but then you run the risk that it will be repainted several times consecutively because of other controls (especially the Parent) Invalidating.

The normal way Windows (Win32 and WinForms.Net) handles this is to wait for the MessageQueue to run empty and then process all invalidated screen areas. That is efficient because when something changes that usually cascades into other things (controls) changing as well.

The most common scenario for Update() is when you change a property (say, label1.Text, which will invalidate the Label) in a for-loop and that loop is temporarily blocking the Message-Loop. Whenever you use it, you should ask yourself if you shouldn't be using a Thread instead. But the answer is't always Yes.

H H
  • 263,252
  • 30
  • 330
  • 514
  • 9
    I'd like to clarify. Update() will immediately repaint any part of the control that is already invalidated. You still need to invalidate first. Refresh() will invalidate and immediately repaint the entire control. When I write a control that does it's own drawing, I call Invalidate() with a dirty rectangle, then call Update() for the sake of responsiveness, and stay away from Refresh() for the sake of performance. – snarf Jun 04 '09 at 21:39
  • 2
    Note there can be a huge CPU performance difference depending on which method you use. `this.Invalidate()` requires the least CPU resources since you aren't forcing things outside the standard message loop, and this is especially true if you can call `this.Invalidate(false)` so you are only calling `OnPaint()` on the main control/form and not the child controls. For one of my UserControls, moving from `this.Update()` to `this.Invalidate(false)` reduced CPU load by a factor of 4. – Special Sauce Nov 23 '17 at 04:24
51

The Invalidate() Method will cause a repaint.

MSDN Link

Matthew Vines
  • 27,253
  • 7
  • 76
  • 97
6

I found the Invalidate() creating too much of flickering. Here's my situation. A custom control I am developing draws its whole contents via handling the Paint event.

this.Paint += this.OnPaint;

This handler calls a custom routine that does the actual painting.

private void OnPaint(object sender, PaintEventArgs e)
{
    this.DrawFrame(e.Graphics);
}

To simulate scrolling I want to repaint my control every time the cursor moves while the left mouse button is pressed. My first choice was using the Invalidate() like the following.

private void RedrawFrame()
{
    var r = new Rectangle(
        0, 0, this.Width, this.Height);

    this.Invalidate(r);
    this.Update();
}

The control scrolls OK but flickers far beyond any comfortable level. So I decided, instead of repainting the control, to call my custom DrawFrame() method directly after handling the MouseMove event. That produced a smooth scrolling with no flickering.

private void RedrawFrame()
{
    var g = Graphics.FromHwnd(this.Handle);
    this.DrawFrame(g);
}

This approach may not be applicable to all situations, but so far it suits me well.

user2529145
  • 265
  • 3
  • 5
4

I think you can also call Refresh().

Brian
  • 25,523
  • 18
  • 82
  • 173
2

Maybe this is an old question and that´s the reason why these answers didn't work for me ... using Visual Studio 2019, after some investigating, this is the solution I've found:

this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
halfer
  • 19,824
  • 17
  • 99
  • 186
Izar Urdin
  • 326
  • 1
  • 11
1

Call control.invalidate and the paint event will be raised.

Otávio Décio
  • 73,752
  • 17
  • 161
  • 228
  • 1
    private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { System.Drawing.Graphics graphics = this.CreateGraphics(); System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(0, 0, 50, 50); graphics.DrawEllipse(System.Drawing.Pens.Black, rectangle); graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle); } When is this paint method called to repaint the form. It does repaint the form doesn't it. – Doug Hauf Feb 27 '14 at 20:24
1

Refresh would probably also make for much more readable code, depending on context.

Simon
  • 151
  • 1
  • 7
-2

use Control.InvokePaint you can also use it for manual double buffering

TheNegative
  • 171
  • 3
  • 7