Business Computing with Windows Mobile!

Onkar Singh

Subscribe to Onkar Singh: eMailAlertsEmail Alerts
Get Onkar Singh: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: Microsoft Developer

Blog Feed Post

Getting Rid of Flickering in .NET CF Forms. . .

. . . with custom drawn controls

.NET Compact Framework doesnt provide builtin double buffering for forms. In case you have multiple custom drawn user controls on a form, loading will mostly show flickr. Overriding OnPaint and drawing the form and its child controls to an offscreen bitmap before putting it out to actual display is expected to solve this. But, once a child control is added to another container control, overriding OnPaint of the parent container control doesnt allow you to paint the child as the child's client rect is clipped out from the graphics object passed to parent's OnPaint.
The solution to this problem is to avoid adding the custom user control to the forms. Instead, maintain your own list of such controls. Form's constructor should make these changes.

//this.Controls.Add(customControl); //don't do this
control_list.Add(customControl); //control_list is Forms own custom list for it's child controls.

When we do that, GWES doesn't know of these controls as child to our form and hence allows us to paint anywhere we like. We can now paint all child controls (by calling their respective OnPaint) to an offscreen bitmap before blting it to actual display. Heres a sample code which does something like this.

protected override void OnPaint(PaintEventArgs e)
{
using (Bitmap doubleBuffer = new Bitmap(this.Width, this.Height))
{
using (Graphics gxOff = Graphics.FromImage(doubleBuffer))
{
using (Brush backBrush = new SolidBrush(this.BackColor))
{
gxOff.FillRectangle(backBrush, this.ClientRectangle);
}

foreach (CustomControl ctl in control_list) //control_list is list of child controls maintained by Form
{
Rectangle rc = new Rectangle(ctl.Left, ctl.Top, ctl.Width, ctl.Height);
if (e.ClipRectangle.IntersectsWith(rc)) //update only those child control which fall within the invalidated region
{
ctl.OnPaint(new PaintEventArgs(gxOff, ctl.ClientRectangle), ctl.Left, ctl.Top);
}
}

e.Graphics.DrawImage(doubleBuffer, 0, 0);
}
}
}

This scheme, however, also requires the form to manage and delegate other GWES events (keypress, clicks, etc) to respective child control. Following code snippet shows that for MouseDown

protected override void OnMouseDown(MouseEventArgs e)
{
foreach (CustomControl ctl in control_list)
{
Rectangle rc = new Rectangle(ctl.Left, ctl.Top, ctl.Width, ctl.Height);
if (rc.Contains(new Point(e.X, e.Y)))
{
ctl.OnMouseDown(e);
this.Invalidate(rc);
break;
}
}
}

I know its a bit of pain but in case you have simple custom controls like buttons, picturebox, very few events need to be overridden and its worth for the flickr free smooth rendering of your forms.

SureMDM: Mobile Device Management for Starters and Experts

Read the original blog entry...

More Stories By Onkar Singh

The author is the founder of 42Gears, developer of affordable Mobile Device Management tools.