Archive for July, 2006

A simple but handy new control called KryptonBorderEdge has been added to the Toolkit. Although not much to look at it does enable some useful scenarios to be created.

Here is a picture showing the new control in the two possible orientations. On the left is the default Horizontal orientation and the right side is the Vertical.

The KryptonBorderEdge is best used by setting the AutoSize property to be True. That way the height or width, depending on the orientation, will be automatically set to the width of the border the control has been styled to.

We can use the control in combination with the new DrawBorders property to create a stack of controls with the appropriate appearance.

In the following example we have a KryptonHeaderGroup control. At the bottom of the control we add a KyptonCheckButton with a docking style of Bottom. We modify the check button so it does not draw any of its borders. Then we place a KryptonBorderEdge also with a docking style of Bottom. We just repeat this for the number of options we want to expose and then hook all the check buttons into a KryptonCheckSet instance to get the exclusive checking functionality.

Viola, a simple replica of the Outlook navigator. It lacks many features such as the overflow area at the bottom and a separator bar for resizing the option buttons area but in many cases you may not need that capability.

Of course, you do not have to use check buttons, you could create a stack of controls of any type that are separated using the KryptonBorderEdge.

You can now specify which of the four border edges you would like to be used for any of the Krypton controls that support drawing a border.

The new property is called DrawBorders and is an enumeration so you can specify any combination of the four border edges. Here is a picture with all the different options applied for a KryptonButton.

As the new property is exposed as an appearance value inside the existing states if means you can define a different value per state. So you might have no borders showing until the user hot tracks over the button and then decide to show just the Top and Left borders. This opens up more variations for your custom palettes.

It is not just the button control that has a border. Here are some quick, and not very exciting, examples of customing the border for KryptonHeader, KryptonHeaderGroup and KryptonNavigator controls.

How do you track down a memory leak in .NET? Well here is a simple and effective technique that should work for you most of the time.

Just because you have a garbage collector does not prevent you from having a memory leak. In this context a memory leak is where you are not releasing all references to an object; so that object is never garbage collected.

So how do you work out where that rogue reference is that prevents it from being cleaned up?

Use the following steps inside Visual Studio 2005.

Step 1
You need to set your managed project to allow unmanaged code debugging. To do this you right click the project and select Properties. The project properties will be shown and from there you select the Debug page of settings. Then ensure the Enable unmanaged code debugging option is ticked. Just like below.

Step 2
Run your application in Debug and set a breakpoint at the place where you know the problem will have already occured. Use your application until you hit your breakpoint.

Step 3
Show the Immediate window so you can begin entering some debugging commands. If the window is not present then use the View -> Other Windows -> Command Window menu option to bring up the Command window. Inside the command window you use the Immed command and then the Immediate window will be displayed.

Step 4
Use the !load sos command in the Immediate window to load the Son Of Strike debugging extensions that allow us to examine managed memory.

Step 5
Use the !dumpheap -stat command. This will then list out all the different types of object that are on the heap.

Each line gives the number of instances of that type, the total amount of memory those instances occupy, the name of the type and a MT address. The MT (Method Table) address is the address of the type and not of any particular instance of the type.

You can see below an abbreviated example of the output.

You need to search this list for the type of the object that you think should have already been garbage collected and so should not actually be present.

We will use System.Drawing.Color[] as the example type from this point onwards. Looking at the above output you can see it has four instances.

Step 6
Use the !dumpheap -mt 7ae7bde4 command to list out the four individual instances of the type. Obviously you need to substitute the address from the MT column of the type you are actually interested in.

In our debugging session the four instances are listed as.

Step 7
Use !dumpobj 013070f8 to list out information about the specific object instance we are interested in from step 6. Again, you need to substitute the actual address with the relevant value found in the previous step. Here is the actual output for the Color[] instance.

Step 8
Now that we have found the rogue instance we believe should not exist we need to find the reference that points to it. Use !gcroot 013070f8 in order to search for all the references to the instance and also display the call stack for each reference.

In our example there is a single reference to the Color[] and the call stack of the object that references it is displayed in the output.

The first object in the stack is the windows form which references the next object down; which itself referencs the one below it and so forth.

In summary, the set of commands are as follows…

List all types of objects
!dumpheap -stat

List instances of a type
!dumpheap -mt {addr}

Examine an instance
!dumpobj {addr}

Find references to instance
!gcroot {addr}

For the first time I have looked at the memory usage of a typical Krypton application. I managed to find some low hanging fruit that was ripe for the picking.

Using the commands described in the Find .NET Memory Leaks article I checked the memory usage for the Palette Designer application.

The above picture shows the end of a list showing all the different types present in the application along with how many instances and how much memory they are consuming. As the list is ordered, the ones at the end of the list are consuming the most memory.

Most of the types listed are of no surprise, the PaletteBack, PaletteBorder and PaletteContent types were to be expected. After all, there are many Krypton controls in the palette designer and therefore many state objects. Multiply the number of state instances by the number of properties that need storage and it works out to be a pretty chunky number.

Although I expected a biggish number I was still surprised that they constitute around 200k, 219k and 369k respectively. Given that the vast majority of these instances will only ever contain defaulted values there was definitely room for improvement.

Instead of PaletteBack having a long list of instance fields that are defined with a default value, I created a helper class that contains the actual storage for the background values. This storage is only created when one of the background values is set to be a non default value. This means that if non of the properties is ever altered then the storage instance is never created. In that case we only have a single reference that is defined as null as the entire footprint for the property storage. I applied this technique to the PaletteBorder and PaletteContent types as well.

The big surprise from the investigation was the event handler type that is shown second to last in the above listing. It has 14k instances consuming 465k of memory. All these instances are actually just event handlers used to notify when an object has been changed in a way that requires a repaint. I was amazed there were quite so many being created and therefore taking up so much room.

In retrospect it should have been obvious. Each Krypton control has multiple states and each state has one or more palette objects for storage of appearance values. Each object exposes an event which is fired when a change occurs to the object that would require a repaint. Once you start hooking up all the objects in the palette hierarchy so that all the children are hooked up to notify the parent it leads to the numbers we see.

The solution turns out to be simple but tedious to refactor the code. I have removed all the events that were exposed and instead store just a single delegate that is fired when the repaint is needed. I create a delegate at the top level of the hierarchy and just pass it down the levels so that all the different palettes objects are using the same delegate to perform notifications.

The end result of the changes gives the following listing when running the palette designer a second time.

So the change in footprint are approx…
PaletteBack 200k -> 67k
PaletteBorder 219 -> 66k
PaletteContent 369k -> 85k
EventHandler 465k -> 2k

Although these changes will not make the application any faster they certainly help reduce memory usage which is useful when using a large number of Krypton controls in a single application.

Until now you could not use padding values with a negative value. Anything under 0 was treated as being defaulted. Now negative values are actually applied and are surprisingly useful.

This change is in response to a question on the forum. A user wants to create a rounded button. The problem is that the rounding causes the size of the button is increase dramatically in size making it impossible to actually use.

The following picture shows three button instances.

Left most is a default button with an image as the content and a square border. In the middle is the same button but with the border rounding defined as 20 pixels. At the end is the same 20 pixel border button with with a content padding value of -4 for all edges.

Here is the property window showing how to set the content padding property.

The middle button is doing the correct thing by getting bigger as the rounding increases. It is ensuring that the entire contents are placed within the border edges and so as the rounding gets bigger it needs to move the content further inwards to avoid overlapping any part of the rounding.

In order to offset this insetting from the rounding you can use the content padding to reduce the padding around the content. As the default padding for the Office 2003 palette is around 3 pixels you can therefore set this to something less. But once the rounding gets large your stuck becaues you cannot set a negative padding value, anything less than 0 is treated as meaning a default value and so it just tries to inherit the value instead.

The code is now changed so that only the value of -1 for a padding edge is treated as meaning a defaulted value that causes inheritance. More negative numbers are just used and applied as can be seen with the right most button in the first picture.

The change always works when use with KryptonHeader.

Or any other control such as a KryptonHeaderGroup.