• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 560
  • Last Modified:

Invalidate() only part of the form in managed Visual C++ .NET

How can only part of the form be invalidated?
0
judico
Asked:
judico
  • 8
  • 6
1 Solution
 
drichardsCommented:
Check out the various overloads of Invalidate:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformscontrolclassinvalidatetopic.asp

You can specify a region or rectangle to invalidate.  The PaintEventArgs contains a ClipRectangle member that indicates the invalidated rectangle that can be painted on.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformspainteventargsclasscliprectangletopic.asp
0
 
judicoAuthor Commented:
Thanks for the links. I looked at them but still can't figure out how to do this. Well, it appears that a function such as this has to be written:

public: void Invalidate(
   
       Rectangle rc
);

but how are the dimensions of the rectangle declared? I took a look at some solutions here in ee as well as some other web pages but cannot understand how this is done. The main idea is to avoid the flicker of the part of the screen (due to unnecessary redrawing)   where the x- and y-axes, tick-marks etc. are and have only the part where the curve builds up redrawn.
0
 
drichardsCommented:
You don't have to write an Invalidate function, you call Invalidate with a Reectangle or Region as a parameter rather than with no parameters as you are now.  If you inspect the PaintEventArgs parameter in the paint method now, the ClipRectangle will be the full size of the form.  The rectangle is specified as Rectangle(x, y, width, height) or Rectangle(Point, Size) where x,y or Point is the upper left corner and width, height or Size is the size of the rectangle.

The catch is that you need to be able to calculate the portion of the form that will need to be painted.  In your case, you can calculate the coord of the new point to be added and invalidate a small rectangle around that point.  Then when you are drawing, don't draw points that are outside the rectangle as they will not be cleared.  Check the ClipRectangle of the PaintEventArgs to see what region has been invalidated.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
judicoAuthor Commented:
I need to invalidate the whole portion of the form where the curve bulds point by point and avoid the constant repainting of the area (where the x an y-axis values are) outside that portion. I don't understand how I should call Invalidate with a Rectangle as a parameter. Tried various ways but nothing helps.
0
 
judicoAuthor Commented:
Can't figure out how to do that. As far as I understand from the help the rectangle should be created by something like this:

HDC hdc;
BOOL Rectangle(
hdc, // handle to DC
75, // x-coord of upper-left corner of rectangle
20, // y-coord of upper-left corner of rectangle
462, // x-coord of lower-right corner of rectangle
270 // y-coord of lower-right corner of rectangle
);

This, however, gives me

error C2078: too many initializers
error C2078: too many initializers

Also, how do you pass it as an argument to Invalidate -- is it something like:

Invalidate( Rectangle );

0
 
drichardsCommented:
You are looking at the Win32 Rectangle, not the .NET rectangle.  You want this one:

   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdrawingrectangleclasstopic.asp
0
 
judicoAuthor Commented:
The only way it compiles is by writing:

public __value struct ClipRectangle
Invalidate( ClipRectangle );      

However, this doesn't do any good because ClipRectangle seems to encompass the entire form. I don't know how to declare ClipRectangle to be a specific portion of the form.

I tried many different ways also, say:

public __value struct updateRect
updateRect.X = 75;
updateRect.Y = 20;
updateRect.Width = 462;
updateRect.Height = 270;

this->Invalidate(updateRect);

or

public: void Invalidate(
Rectangle rc
);

etc.

Nothing seems to work.
0
 
judicoAuthor Commented:
This also compiles well but with no apparent result:

System::Drawing::Rectangle *r = __nogc new System::Drawing::Rectangle(75,20,462,270);
public __value struct r;
this->Invalidate( r );
0
 
drichardsCommented:
>> This also compiles well but with no apparent result:
First of all, the syntax doesn't seem quite right.  Secondly you are invalidating nearly the whole area, and third, did you remove the call to __super::OnPaint( paintEvent ) in the OnPaint method?  This last is what erases all the previous drawing.

So, suppose your most current point is going to be at the point (10,15).  If you are drawing circles 5 wide, you would only have to invalidate a rectangle (10,15,5,5).  You may have to adjust the number slightly as I don't know if the ellipse is measured the same way from the upper left corner.

You call Invalidate like this:

    Invalidate(System::Drawing::Rectangle(10,15,5,5);

In your pain method, only things you draw in this area will appear.  As a test, leave the __super::OnPaint( paintEvent ); in there and invalidate a region:

   Invalidate(System::Drawing::Rectangle(5, 0, 10,200);

You should see points only in a narrow vertical band close to the beginning.

0
 
judicoAuthor Commented:
Now, this works perfectly. I need the first screen painted in full so I write:

if ( evtCounter < 2 )
{
      Invalidate();
}
else
{
         Invalidate(System::Drawing::Rectangle(75, 20, 1000, 250));
}

In this way I have the numbers of the axes steady (not flickering) and only the curve that builds is being repainted.

Thank you very much for your indispensable help.
0
 
drichardsCommented:
If you wantr to get really fancy, you can inalidate only the small area around the newest point and only that small area gets repainted.
0
 
judicoAuthor Commented:
This is a very cool suggestion, indeed. I'm not sure it will work in my present case, though. Remember that I need to have the trace of the curve on the screen. I understand that according to you last idea every new point appearing on the graph after repaint will leave the previous point unaffected and in this way constant replotting of the ever growing array of points will become unnecessary. I wonder, however, if it will be worth the effort since as it is now it appears to work very well. Thanks anyway.
0
 
drichardsCommented:
>> I wonder, however, if it will be worth the effort since as it is now it appears to work very well
Nope, not worth the effort if it is working to your satisfaction.  Just remember you can do it - you never know what you might need for future work.
0
 
judicoAuthor Commented:
Thanks and all the best.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now