Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Check the invalidated region on paint event?

Posted on 2011-03-01
15
Medium Priority
?
740 Views
Last Modified: 2012-05-11
Hello, in VB.NET forms I occasionally call the Form.Invalidate function and I send in a rectangle.  Sometimes I call several of these for the various parts of the form I want refreshed, and -- I think I see -- through windows magic these are sometimes combined into a single paint event.

But this is kind of a black box -- is there a way, in the .NET forms paint event, to check to see if a particular point on my form is *about* to be repainted?  (Because if not I don't want to bother to run a lot of code to recalculate its appearance.)

Thanks.
0
Comment
Question by:riceman0
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +1
15 Comments
 
LVL 8

Accepted Solution

by:
SunnyDark earned 668 total points
ID: 35008237
The OnPaint's event PaintEventArgs contains "ClipRectange" which could be checked to see if your graphics object is outside it...
0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35008308
Since PaintEventArgs.ClipRectange doesn't work on all windows versions the same, another approach would be to keep track of the invalidated region yourself... Just save it as a variable in your form class whne calling invalidate, and reinitialize when painting...
0
 

Author Comment

by:riceman0
ID: 35009756

I had trouble keeping track of the invalidated region myself, as follows:

What I have is a complex drawing that I don't want to re-render unless I have to, because it can slow other things down.  So I'm trying *not* to run that rendering code except when necessary.

So at first when I wanted to refresh this area I set a flag to allow the area to redraw itself, as below.  The problem is that I'm not the only source of Repaints -- it also repaints when you resize the form or move a window in front of my window, etc.  This would refresh the entire form, my rendering code would not run, and the area would go blank.

But I tried ClipRectangle and it seems to work well -- what windows versions does it not work on?  Do you have more info on this?

***

sub InvalidateBusyArea
repaintflag = true
Invalidate (bounds of area)
end sub

sub OnPaint
   if repaintflag
       repaintflag = false
       perform busy calculations and render
   endif
end sub
0
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!

 
LVL 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 668 total points
ID: 35009810
How static or dynamic is the rendered portion?  If possible, you can render it to a Bitmap and assign that as the BackgroundImage of the Form (or Panel or PictureBox if appropriate).  This way it gets repainted properly whenever necessary without calculations and YOU only re-create the Bitmap when the data within has changed.  Can you give more details about what is rendered?
0
 

Author Comment

by:riceman0
ID: 35009898

Very dynamic, it draws itself based on some shared data that can be modified from several other places.  In this case it is a graph which could have thousands of points.  I'd be recreating it a lot, in some cases faster than I'd want to refresh the screen.

I like your idea, but ultimately if I can control the invalidates, the form is sort of like the bitmap in your example, isn't it?  




0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 35009954
Can you break out the Form into distinct different areas that Paint themselves?  You could use UserControls, Panels, or PictureBoxes.  (It could still look seamless by not using borders on the controls.)  Then you can invalidate only the controls that need repainting and the rest will stay the same.
0
 
LVL 25

Assisted Solution

by:SStory
SStory earned 664 total points
ID: 35011113

See the attached vb.net code snippet.

The e.Cliprectangle is apparently what gets set when something is Invalidated on a form or control.
** If Update is called after invalidate, the whole control is invalidated

You can run the code and see it in action, complete with points tests.

I would have been the first poster, but as the mods can see, I posted to the wrong message apparently...or the system did for me. Somehow it wound up on an Exchange message.
For that reason I am reposting what I had written here.
Public Class Form1

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Console.Write(e.ClipRectangle.ToString())
        Console.Write(" Contains (150,150): {0}", e.ClipRectangle.Contains(150, 150))
        Console.WriteLine(" Contains (0,0): {0}", e.ClipRectangle.Contains(0, 0))
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.Invalidate(New Rectangle(100, 100, 100, 100))
    End Sub
End Class

Open in new window

0
 
LVL 25

Expert Comment

by:SStory
ID: 35011133
I suppose you could draw to a bitmap, then copy that to the form or picturebox or whatever so that on each refresh, it would grab that quickly instead of having to go through your draw routine.  Then when you changed something, you'd redraw the bitmap.

Would that help?
0
 

Author Comment

by:riceman0
ID: 35011150
Wow, that's actually close to what I'm doing... I have created my own "cObject" and "cFrame" classes that represent an area of the screen, handles the paint to draw itself, handles the mouse events, etc.  By deriving from this class I can create my own pseudo-controls that are lighter than the .NET controls and infinitely customizable (e.g., I can animate or alpha them if I want to).  So far it's been pretty easy -- a button is just a rectangle, doesn't need to be a window.

What I'm trying to avoid is repainting "frame" A when I only want to repaint "frame" B... frame A could be very complex and slow down frame B.  I know that .NET controls handle this themselves, but I'm trying not to use their controls:  they also do a lot more than I want to do a lot of the time, and can be sluggish in those cases.  I'm trying to create some alternate lightweight objects for some specific graphics-intensive things.
0
 

Author Comment

by:riceman0
ID: 35011165
(sorry was responding to idlemind)
0
 

Author Comment

by:riceman0
ID: 35011186
S Story, SunnyDark says ClipRectangle is dangerous to use because doens't work consistently -- do you see that too?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 35011192
So do you have an internal rectangle field that describes where each class renders itself?  This way you can check to see if the ClipRectangle() intersects each area and should be redrawn.
0
 

Author Comment

by:riceman0
ID: 35011260

Yep, ClipRectangle seems to be working pretty well exactly like that (thanks to this thread).  Just wondering if it will work on all versions of windows...
0
 
LVL 25

Expert Comment

by:SStory
ID: 35012016
riceman0,

I honestly haven't tried it to know if it fails or not. It seems from researching that, that is what it is for.
Used to be that apps caught the WM_PAINT message (http://msdn.microsoft.com/en-us/library/dd145213%28v=vs.85%29.aspx) for the window and used
GetUpdateRect (http://msdn.microsoft.com/en-us/library/dd144943%28v=vs.85%29.aspx)
to find out the update rectangle.

I don't know if DotNet does away with this or not, but I would have assumed that the cliprectangle should be doing the same thing.

If you dump my code to a vb win form app, you will see that it appears to do what I was saying.

0
 
LVL 25

Expert Comment

by:SStory
ID: 35012025
I'd never know without checking a lot of windows versions.
It worked on Win 7 Pro--so there's one for you. ;)
0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question