Link to home
Start Free TrialLog in
Avatar of David L. Hansen
David L. HansenFlag for United States of America

asked on

Paint events - determine when a paint event has finished.

I'd like to know if one can determine programmatically when a paint event has just completed.
Avatar of TwynFeyr
TwynFeyr

You can always override the OnPaint kind like:
protected override void OnPaint(PaintEventArgs e) {    
base.OnPaint(e);
//Do your stuff here
} 

Open in new window

base.OnPaint(e) does it's thing and then you do your afterwards

here's a link to MSDN
Control.OnPaint method
Avatar of Kyle Abrahams, PMP
Easiest way that comes to mind is the following:

Inherit a class, say TextBox

then create an After_Paint Event

Override the OnPaint event, raising After_Paint when done.



eg:

Class MyTextBox : TextBox
{
Public Event After_Paint

Protected void Overrides OnPaint(e as System.EventArgs)
{  
   base.OnPaint(e);
   RaiseEvent After_Paint;
}

}

NOTE:  Code was done by hand, may have syntax error but displays general idea.
Avatar of David L. Hansen

ASKER

TwynFeyr: It seems that OnPaint just allows me to force the paint event to fire. But thanks for the suggestion.

Here is some context: I have a datagridview and that flicker bug is becoming a problem (for those of you not aware of the bug...a datagridview placed on a form with a background image will often cause horrible flicker of the screen when the datagridview is painting itself - there is a lot of documentation of this if you search for it - affecting VS 2005 and older).  I have minimized this issue but it is still a problem.  I want to just tell the grid's paint event to set the form's background to nothing (done that), then - when the grid's paint event is finished, reset the form's backgroundimage to what it was (here in is my problem).
Hi again,

overide onpaint is fired everytime a paint event is raised.  If you put it directly in a winform it'll fire for the form's events.  If you do as ger325 suggested it'll fire when paint events are raised for the control class you have inherited (which in this case after the question had further context added) is a better suggestion.

however, I'd be wary as alot of paint events can be raised in a very short amount of time depending on the circumstances.  resizing a form usually forces all the controls to repaint if they are docked or anchored to resize on form resize.  Also when the form becomes smaller and then bigger than the controls on the form there is alot of repainting.  you may end up replacing one flicker, for a different kind.

i look forward to hearing about your progress.

Cheers!
TwynFeyr
Yes, that really is the root of the problem.  I need to know when the grid is beginning to paint itself so I can disable the background, then have an event fire when it is completed with all of its interior paint events.  This may not be possible, but that is what I'm after.

Setting the background = nothing for each descrete paint event is not a big deal.  There is no flicker issue there.  So, if all I can get is the "FinishedPaintingTheWholeGrid" event, I'm in good shape.
I think the grid paint event may be fired again when you change the background color.

Have you tried putting the grid into a panel of same size as grid? This may not solve the problem but worth the try.
Inherit the datagrid:


implement this for your paint:

Boolean _painting = false;
 
Protected void Overrides OnPaint(e as System.EventArgs)
{  
 

  if (!_painting)
   {
    _painting = true;
     //set background image to nothing
    base.OnPaint(e);
    //set background image back.  
   _painting = false;
   }
}


and also turn on double buffering:  (modified from http://bitmatic.com/c/fixing-a-slow-scrolling-datagridview)

new()
{
  Type dgvType = this.GetType();
        PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
            BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(this, true, null);

}
CodeCruiser,
The panel didn't help.  Too bad, it would have been the easiest solution.

ged325,
I really like your idea and am trying to implement it.  I'm in VB, so I've converted the code.  Two things: First, the following code causes constant flicker when the form loads...the flicker never stops (it paints the background as nothing then the image, then nothing, then the image, etc., etc. very very fast).  Secondly, I don't see how I can generically set the background of the form to nothing within the custom datagridview class.  I certainly can force it through "my.Forms.mySpecificFrom.BackgroundImage = Nothing" but then I can't reuse the code without rewriting that line of code each time I drop a grid on a form.  Is there a way I can generically point to the parent form?

Here is the code:
Public NotInheritable Class DatagridViewPlus
    Inherits DataGridView

    Dim _painting As Boolean = False

    Private Sub New()
        Dim dgvType As Type = Me.[GetType]()
        Dim pi As PropertyInfo = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance Or BindingFlags.NonPublic)
        pi.SetValue(Me, True, Nothing)
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        _painting = True
        My.Forms.frmMain.BackgroundImage = Nothing  '<******** Too specific
        MyBase.OnPaint(e)
        Dim resources As System.ComponentModel.ComponentResourceManager = New               System.ComponentModel.ComponentResourceManager(GetType(frmBuyer))
        My.Forms.frmMain.BackgroundImage = CType(resources.GetObject("$this.BackgroundImage"), System.Drawing.Image)
        _painting = False
    End Sub
End Class

Open in new window


To make it really reuasable I think I'll put in a test to see if a background image exists.
SOLUTION
Avatar of Kyle Abrahams, PMP
Kyle Abrahams, PMP
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
There is no "GetForm" method for DatagridViews.  But there is a "Parent" property which I've not tried.  

Also, getting the image is not a problem. The "Dim resources ..." line and the "...$this.BackgroundImage" line work wonderfully.  I've tested those.  I think perhaps the sequencing is funny...not sure, but there is definitely an infinite loop going on.
the infinite loop comes from setting the background to null.  Which is intern triggering the paint event again . . . Hence the mutex like options.



Once it's in the on_paint, it needs to skip it for all other calls.


Regarding the .Parent . . . I've had issues with that where it was nothing even after being loaded.

You may want to create another property and set the property from the control.

As for the resources line . . . that may work for this app but was trying to make it as generic as possible.  If you're okay with it though that's what counts.
Cruiser, Ged, and Twyn,

Truly sorry for the long delay guys (and through the E-E-Derby too)!  I've been trying to duplicate the flicker, in a test project, and fix it with the custom grid.  The problem is, I've been getting inconsistent results.  Without determining all the variables contributing to the problem, I'm reluctant to close this post (and give out an incomplete answer).  I'll continue testing with this and won't neglect this post; it may take some time however (as I do have a band-aid fix, which my boss is happy with).  I will definitely work on it as I have time to do so -- I really do want to pin this down.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'll definitely give your idea a shot and let you know the results :)
>and through the E-E-Derby too

Curious on the use of Derby word as its the city I live in.
I was just referring to the Grand-Prix competition Experts-Exchange was having at the time.
Oh ok.
The Derby in England?
I'm working on this today.  I hope I can finish this off and that it will work...thanks for your help and patients.
I need to just tie this up.  I believe your approach will work TwynFyer; I'm going to award the points without actually testing because I just don't know when I'll be able to.  I was basically told me to forget the "Pretty backgrounds" and finish the job.  Too bad really.
Thank you very very much.