Solved

Check the invalidated region on paint event?

Posted on 2011-03-01
15
698 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
  • 6
  • 4
  • 3
  • +1
15 Comments
 
LVL 8

Accepted Solution

by:
SunnyDark earned 167 total points
Comment Utility
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
Comment Utility
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
Comment Utility

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
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 167 total points
Comment Utility
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
Comment Utility

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 85

Expert Comment

by:Mike Tomlinson
Comment Utility
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 166 total points
Comment Utility

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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 25

Expert Comment

by:SStory
Comment Utility
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
Comment Utility
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
Comment Utility
(sorry was responding to idlemind)
0
 

Author Comment

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

Expert Comment

by:Mike Tomlinson
Comment Utility
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
Comment Utility

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
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

771 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now