Groups | Blog | Home
all groups > dotnet drawing api > june 2005 >

dotnet drawing api : ClipRectangle


Bob Powell [MVP]
6/22/2005 12:00:00 AM
Hi,
This looks to me as though the window is behaving normally. When a window is
scrolled the existing contents of the window are shifted using the Win32
ScrollWindow API and only the part that needs redrawing is invalidated. Are
you sure that the rectangle is outside of the client area. It looks
right-ish for a window on a 1024*768 monitor or larger.

Remember also that any intersection of a rectangle and the virtual scrolling
area will have to take account of the scroll position too so effectively you
need to offset the clip rectangle by the amount of scroll in order to
compare it with things that are on your virtual page. The clip rectangle is
always in window coordinates regardless of the reported scroll position.


--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.





[quoted text, click to view]

Andrew
6/22/2005 12:41:01 AM
Hi Bob,

Prior to the drawing of any graphical object, I test to determine if that
object 's envelope/bounds intersects with the ClipRectangle (c).

c is retrieved directly from the base classes PaintEventArgs cliprectangle.

I have noticed that when the form is not scrolled, 'c' is OK(sensible
values), however upon scrolling the form, 'c' somehow takes on unexpected
values eg
c is {X=840,Y=0,Width=1,Height=426} which is right off the form's display
rectangle ?

Due to the scrolling, I assume that Windows is invalidating the form's
entire client rectangle, hence setting the PaintEventArgs.ClipRectagle to the
entire client rectangle.

I am translating the graphics object in accordance with the
AutoScrollPosition in order to place draw the graphics objects in the correct
location (allowing for any
scroll position)

Because of the weird values occuring in 'c' , the intersection test is
failing ie
if (c.IntersectsWith(rcDraw))
{
//draw object
}

hence nothing gets drawn when upon scrolling .

I am wondering why the ClipRectangle is getting such strange values when the
form is scrolled ?

Any help would be appreciated .

Thanks

Andrew.
Andrew
6/22/2005 2:42:02 PM
Thanks Bob,

I will need to investigate it further as per your comments and I will soon
reply.

Much of what you describe is already in place.

Thanks

Andrew
[quoted text, click to view]
Andrew
6/22/2005 7:15:01 PM
Bob,

Yes the screen resolution is 1024 * 768.

Because I have a properties panel to the right and another panel situated
below my form, the view/form's client rectangle is {0,0,842,426}.

With no scroll the clip rectangle is the same as the client rectangle.

The building rectangle is initially displayed in the buildingview with no
scrolling required. When I increase the building length, scroll margins are
generated in the horizontal direction and upon scrolling I should be able to
see the right edge of the building rectangle. However what happens is that
upon scrolling, nothing appears to the right of the existing rectangle shape.

I observe from the debug screen that just as the scroll commences (eg scroll
point is -1,0) that the clip rectangle jumps to {840,0,1,426} which puts it
right at the extremity of the display rectangle!

No given graphical shape is going to pass a intersectwith/contains test with
such a clip rectangle, hence it won't be drawn.

As per your advice, I am now translating the location of the clip rectangle
in accordance with the scroll position - thanks. The main point is the
concern regarding the values in the cliprectangle as soon as scrolling begins.

Prior to introducing the clip rectangle test , the graphical objects would
draw correctly upon scrolling using the transformed graphics object ie

In the view forms's base class, I would take the graphics object that was
provided to the base classes OnPaint handler and transform it by the amount
of the scrollposition ie
Graphics g = e.Graphics
Point pt = this.AutoScrollPosition;
g.TranslateTransform(pt.X,pt.Y);

in the derived form/view I then draw the object ie

g.DrawRectangle(object)

Now, in the base classes OnPaint handler I have introduced an offset to the
cliprectangle by the scroll amount, and in the draw code of the respective
graphical objects I move the objects envelope to the scroll position.

The object will only be drawn if its envelope intersects with the clip
rectangle , however in reality no object does not due to the values in the
cliprectangle.

I intend to persist with the clip rectangle test in order to achieve the
most efficient drawing strategy. If the clip rectangle test was to pass (as I
was expecting) then the translated graphics object would be drawn and in the
correct location and in this example I should see the right edge of the
building rectangle.

I cannot say that I am sure of where the clip rectangle should be when the
view/form scrolls - I suspect that when scrolling occurs the entire client
area is invalidated by the system hence setting the clip rectangle to have to
same values ie static ??

Can you understand why the clip rectangle has the reported values ?


Thanks

Andrew

[quoted text, click to view]
Andrew
6/26/2005 8:35:04 PM
Hello ,

Does anyone have a comment regarding the cliprectangle values upon the form
scrolling ?



[quoted text, click to view]
Bob Powell [MVP]
6/27/2005 10:28:30 AM
The clip rectangle reports the amount of screen area that needs to be
updated. If you scroll the window to the left then it exposes an area to the
right of the window that needs to be refreshed.

The code below my signature shows how such a scheme might be created.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

---------------------------------------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace cliprectangles
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{

ArrayList ar=new ArrayList();

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
Random r=new Random();
for(int x=0;x<1024;x+=10)
{
ColorRect cr=new ColorRect();
cr.Rect=new Rectangle(x,(int)(x*0.66f),10,7);
cr.Color=Color.FromArgb(r.Next(255),r.Next(255),r.Next(255));
ar.Add(cr);
}
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.AutoScroll = true;
this.AutoScrollMinSize = new System.Drawing.Size(1024, 768);
this.ClientSize = new System.Drawing.Size(275, 249);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new
System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
//transform the drawing output according to the scroll positions
Matrix mx=new
Matrix(1,0,0,1,this.AutoScrollPosition.X,this.AutoScrollPosition.Y);
e.Graphics.Transform=mx;

//adjust the clip rectangle...
//note the use of the inverse of the scrollposition
Rectangle clip=e.ClipRectangle;
clip.Offset(-this.AutoScrollPosition.X,-this.AutoScrollPosition.Y);
int rectCount=0;
foreach(ColorRect cr in this.ar)
{
if(cr.Rect.IntersectsWith(clip))
{
cr.Draw(e.Graphics);
rectCount++;
}
}
System.Diagnostics.Trace.WriteLine(string.Format("This pass drew {0}
rectangles.",rectCount));
}
}

public class ColorRect
{
Rectangle _rect;
public Rectangle Rect
{
get{return _rect;}
set{_rect=value;}
}

Color _color;
public Color Color
{
get{return _color;}
set{_color=value;}
}

public void Draw(Graphics g)
{
SolidBrush sb=new SolidBrush(this._color);
g.FillRectangle(sb,_rect);
sb.Dispose();
}
}
}

---------------------------------------------------------------------



[quoted text, click to view]
Andrew
6/28/2005 4:29:06 PM
Thanks

The Cliprectangle values are puzzling me.

I will try to interpret the reported values of the ClipRectangle in the
light of your comments/code.

Much appreciated .

Andrew.

[quoted text, click to view]
Andrew
7/6/2005 10:25:03 PM
Hello ,

Now with a proper appreciation of the mechanisms of scrolling, cliprectangle
generation,invalidating... - I have made alerations to the graphics code
that now
to justice to the whole process of drawing on a form for any scroll condition.

It did take me some time to achieve and thanks for the feeback on my
questions.

Bob, I looked at your code after having made my alerations and with no
surprises they are very similar.

The above exercise reflects that coding a graphics application is futile
without a thorough understanding of the processes that are happening behind
the scene.

The 'graphics engine' now works very efficiently.

Regards

Andrew.

[quoted text, click to view]
AddThis Social Bookmark Button