Category Archives: C#

Notes on C# / .NET

Casting

Casting classes up and down.

B b = new B();
A a = (A)b;
B c = a as B;

if (c != null)
{
//cast succeeded
}
>/pre>
Lastest update in June 2011, inital post in June 2011

Get the MyVideos folder

For the current user

System.Environment.GetFolderPath(Environment.SpecialFolder.MyVideos));

For all users

System.Environment.GetFolderPath(Environment.SpecialFolder.CommonVideos));
Lastest update in June 2011, inital post in June 2011

.NET and painting from an API viewpoint

When .NET is used on the windows platform it’s a layer on top  of the windows API. Understanding how this works will help you to speed up painting.

The windows API  works with messages. These message are processed by the message queue.  Often the message handler is one function with a long switch statement processing the messages required.

Messages related to painting

Messages of importance are the WM_ERASEBKGND and the WM_PAINT.

WM_ERASEBKGND   clears the background and paint it. It is called when a part of the control needs to be repainted. The default handling uses the brush assigned to the background and paints. When an API InvalidateRect is used to invalidate a rectangle the last parameter indicates whether this message is generated.

WM_PAINT paints the contents, it uses a clipping rectangle. The GDI API can clip all contents on this rectangle. Although clipping is not totally free it reduces the time to repaint significantly.

How does this translate to .NET.

.NET supports two events which map directly to the events.

OnPaintBackground

Called from the WM_ERASEBKGND event unless double buffering or SetStyle is used to set the style AllPaintingInWmPaint. In that case this event will be fired from the WM_PAINT message, this may reducing some flicker since there can be some time between the two messages. It is to be assumed that setting the form property DoubleBuffered to true will also set this style implicit .

Paint

Used to paint the contents. It uses a clipping rectangle to prevent unneeded painting. It is important to remember that if you invalidate the form yourself using the Invalidate() method (equivalent to an InvalidateRect API call) using the parameter less version will invalidate the entire client area!

When using invalidate always supply an rectangle or region if needed. Multiple invalidates will be combined in one clipping rectangle. Typically the bounding rectangle.

It is also important to remember that invalidate() will not repaint directly, use the update method to redraw (the equivalent of the UpdateWindow() API call.

Double buffering

When double buffering is used the graphics drawn is first drawn on a bitmap which is then drawn on screen. Although theoretically this would be slower requiring an extra step, drawing on the bitmap (in memory) is often faster then to video memory the net result may be faster.  Since there will be less flicker since the screen buffer is accessed less often and bitmap drawing is a very efficient graphics operation double buffering is almost always a good idea .

It is still very important to use the Invalidate with rectangles even when double buffering.  Admittedly, drawing the entire bitmap is fast but when dragging a lot of bitmaps need to be painted!  Also if possible do not rely on clipping to much. Your paint handler has a parameter with the clipping rectangle. If a lot of objects are to be painted a quick check on this boundary can save precious time creating brushes, pens etc.

Lastest update in June 2011, inital post in June 2011

Remove or insert items in an ‘fixed’ array like int[]

Remove or insert an item in an array.

Use the always useful Array class. It has some static members which are great!

int[] myArray = new int[4];
myArray [0] = 0;
myArray [1] = 1;
myArray [2] = 2;
myArray [3] = 3;

// Remove item 1
Array.Copy(myArray , 2, myArray , 1, 2);
// MyArray contains 0,2,3,3

myArray [0] = 0;
myArray [1] = 1;
myArray [2] = 2;
myArray [3] = 3;

// Insert new item in 1
Array.Copy(myArray , 1, myArray ,2, 2);
// MyArray contains 0,1,1,2

Note: If the bounds of the array are exceeded an exception will be thrown.

The functions below calculate the number of elements to copy.

They use the following arguments:

Array The array to use.
index The offset whereto insert or remove
delta The number of items to add / remove
totCount The number of items currently in the array.

To allow a correct insert the array must be larger than the current numbers (Arrays are not resized). Clearing is optional

void removeFromArray(Array array, int index, int delta, int totCount)
{
   Array.Copy(array, index + delta, array, index, totCount - (index + delta));
   Array.Clear(array, totCount - delta, delta);
}

void insertIntoArray(Array array, int index, int delta, int totCount)
{
   Array.Copy(array, index, array, index + delta, totCount - index);
   Array.Clear(array, index, delta);
}
Lastest update in May 2011, inital post in May 2011

OutputDebugString replacement

To replace OutputDebugString API use the System.Diagnostics.Debug class.

For example:

System.Diagnostics.Debug.WriteLine("Debug message");
Lastest update in May 2011, inital post in May 2011

Get the send to folder

For the current user

System.Environment.GetFolderPath(Environment.SpecialFolder.SendTo));

For the all users

System.Environment.GetFolderPath(Environment.SpecialFolder.CommonSendTo));
Lastest update in May 2011, inital post in May 2011

Get the desktop folder

For the current user

System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));

For the all users

System.Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory));
Lastest update in May 2011, inital post in May 2011

Get the template folder

For the current user

System.Environment.GetFolderPath(Environment.SpecialFolder.Templates));

For the all users

System.Environment.GetFolderPath(Environment.SpecialFolder.CommonTemplates));
Lastest update in May 2011, inital post in May 2011