Tuesday 22 February 2011

.net WaitCursor: how hard can it be to show an hourglass?


I've seen a couple of different ways of using the 'Wait' cursor (aka the 'Hourglass') and several forum posts discuss the problems people have when they haven't been able to work out how to use it properly. Hopefully this is a comprehensive discussion of this small but seemingly complicated topic.

When your program is doing something which stops users from accessing the UI, you should display a 'Wait' cursor. There are three different things you can do to get this (and usually none of them work the way you'd want on their own):
// Method #1
Control.Cursor = Cursors.WaitCursor

// Method #2
Cursor.Current = Cursors.WaitCursor

// Method #3
Control.UseWaitCursor = true;
For the first two, Cursors.Default can be used to return to the expected arrow after the operation has finished; UseWaitCursor should simply be set to false again.

Controls all have a Cursor property and this sets the cursor shape when the mouse pointer is over a control. This property is examined and acted upon only when a Windows message (WM_SETCURSOR) is sent to a window. This means that until the next time this message is sent (perhaps when the pointer is moved away from and back over the control in question), updating this property won't have any effect. To exacerbate the problem, if the UI thread is blocked by whatever operation the WaitCursor would be displayed for, any WM_SETCURSOR messages that are generated won't be processed until the operation has finished.

The other problem with using this alone is that it is a per-control setting: set it for a form and all the child controls on the form will still display the default cursor unless you update all of their Cursor properties as well.

The solution for this problem (and the suggested 'proper' way of displaying the WaitCursor) is to set the Form's UseWaitCursor property. This has the advantage of working for any given control and all its child controls, so set it for a Form and the whole UI for the form will display the WaitCursor when the pointer is over it, regardless of the control under the mouse. There is also an Application.UseWaitCursor which has the same effect across all the windows of a running application. However, this still suffers from the problem of needing a WM_SETCURSOR message before the cursor shape will change.

So what about the other option? Cursor.Current is a static member of the Cursor class and accesses the OS to change the current cursor immediately. This is great… until the next WM_SETCURSOR message is processed and it goes back to whatever the control underneath is supposed to display.

Problems with all these approaches are made less predictable with UI thread blocking too: Cursor.Current will affect a change for some time if UI messages aren't being processed, for example, and then might suddenly change back for no reason that is obvious as a message gets handled.

So the best approach looks like it is to set MyForm.UseWaitCursor to true and then set Cursor.Current. As well as putting any long-running activities in a separate thread, of course. Well, that does solve the problem, unless you want the relatively common ability to cancel a long-running activity and you want the default cursor shape (i.e. an arrow) over your cancel button.

If you look into the Control.UseWaitCursor setter in Reflector, you'll see that it sets its flag (a bit in the private 'state' field in Control) and then recurses into the UseWaitCursor setters in each of its child controls. You might think (i.e. I thought) that all that's then needed is to reverse the setting of this flag in the button in which you want to display a normal arrow and all would be well. Unfortunately, this doesn't work – you still get WaitCursor everywhere. So how can you do it?

Well, it turns out that if you use all of:

MyForm.UseWaitCursor = true;
CancelButton.UseWaitCursor = false;
CancelButton.Cursor = Cursors.Default;

Then you can get the desired behaviour. And of course, a Cursor.Current call would also be in order if you find the cursor shape isn't changing until the mouse is moved.

I don't know how this works: I would have thought that if Control.UseWaitCursor = true sets Control.Cursor to the WaitCursor (which appears to be the case) then setting it to false would have the opposite effect, but I found that CancelButton.Cursor was still set to WaitCursor even after the UseWaitCursor flag in the control (not the form) had been reset.

This solves the problem and is not overly arduous but if you can explain the behaviour, leave a comment and I'll update the article accordingly!

Friday 18 February 2011

.net Graphics in Windows Forms – Part 1: ControlStyles

One of the areas of .net development that doesn't get the attention I think it deserves is graphics. At the UI level, a lot of software is effectively just a bolting together of existing components that all draw themselves and so this topic is often considered a sideline. Maybe it is beyond the scope of a lot of programs, but occasionally it's very useful to know about the default drawing behaviour and how it can be altered.

Although it isn't hard to draw to a control's surface in Forms applications, the default configuration for the GDI+ system can limit the quality of the result – mainly for reasons of safety (speed, making sure something gets drawn and previously painted stuff gets erased, etc.). This is the first of three posts on graphics in Windows Forms applications. In this post, I'll discuss the ControlStyles flags held internally in objects derived from Control and how they can be set to help controls that draw themselves by overriding OnPaint(). In the next post I'll talk about painting lines and shapes (and in particular about smoothing) and in the last one, the discussion will move on to drawing text directly to the screen. On to the first topic…


System.Windows.Forms.Control has a private enum variable called controlSyle, which is of type System.Windows.Forms.ControlStyles. Amongst other things, the flags contained in this enum can alter the way the control is painted in several respects. In particular, you can use it to:
  • Inform the Window Manager that you want to be in charge of drawing a control if you don't need it to do anything (which removes pointless and potentially time-consuming calls during painting)
  • Use Double-buffering for complicated (i.e. time-consuming) drawing
  • Ask for painting to be redone any time the control is resized
The really good news about these settings (even the relatively complicated double-buffering) is that all you need to know is what the settings are for: any heavy lifting is done for you by the framework and you just have to ask.


As I said, ControlStyles is a flag-style enum (i.e. the possible values are independent of one another and several can be set at once). The variable itself is private, but it's exposed using the getter / setter methods GetStyle() and SetStyle(). However, these are protected, so deriving from an object in the Control hierarchy is the only way to access them. This isn't a problem because deriving a new control from an existing one (or simply from Control itself) is really what you want to do any time you're changing behaviour like painting.


Don't forget when you're dealing with a derived control that the recommended way to access events is not to subscribe to them, but override the OnEvent() methods of the base class (OnPaint(), OnClick(), etc.). Whether you then call the base method is up to you, but as the base method actually raises the event, make sure there are no subscribers if you want to miss this out.
 

The flags that are of interest to this discussion are detailed in the table below:

Flag
Description
UserPaint
Cause the Paint event to be raised when repainting is necessary
AllPaintingInWmPaint
Prevent the control from being erased by the OS before Paint is raised
OptimizedDoubleBuffer
Construct control in buffer before outputting to screen
ResizeRedraw
Repaint the control automatically if resized

UserPaint causes the Paint event to be raised when redraw is necessary. This flag will be set to false on controls the OS draws without input from the program. See the note below about this flag in combination with some of the others, but in general, if you're painting, you'll need this set to true.
 

AllPaintingInWmPaint simply says that the control wants to be responsible for the entire painting operation. What this means in practice is that the PaintBackground event is not raised when a WM_ERASEBKGND message is received from the Windows message pump. Running the (potentially lengthy) implementation of OnPaintBackground in Control is pointless if you are just going to replace the entire area with something else (a picture or some other graphic that fills the control). This flag can greatly reduce flickering on controls where OnPaint() always redraws every pixel of the invalidated region (or can easily be made to).
 

In fact, MSDN suggests that when this flag is true, PaintBackground is raised instead from the WM_PAINT Windows event, and you sometimes see a recommendation to override OnPaintBackground with an empty method specifically so the base method is never called. When I experimented with this, I found OnPaintBackground was never called if AllPaintingInWmPaint was set to true. Your mileage may vary, of course, and I'd be interested to hear any counter-examples. However, I can't see the point of making it possible to not call it from one Windows message just to call it from a subsequent one instead.
 

OptimizedDoubleBuffer means the PaintEventArgs passed to OnPaint() references the Graphics object of an off-screen surface and swaps that onto the display only when painting has been completed. This is another flicker-reducer and works especially well if the painting takes any length of time and / or is made up of layers (which the user can often see being constructed). Obviously, it does introduce an extra step into each Paint event and may not be necessary so should be experimented with rather than simply used all the time.
 

There is another member of the enum, "DoubleBuffer" which you may come across (previous to .net 2.0, it was all that existed). In current versions of the framework, it is hidden from Intellisense so you won't see it in the IDE. Despite this, there is a (presumably erroneous) note on the MSDN ControlStyles entry saying it is preferred over OptimizedDoubleBuffer.
 

MSDN says that UserPaint must be true for either of AllPaintingInWmPaint and OptimizedDoubleBuffer to work and that in order for OptimizedDoubleBuffer to work fully, AllPaintingInWmPaint should also be set to true when double buffering is desired.
 

ResizeRedraw is not really a way of improving display, but does provide a handy method for forcing the Paint event to be raised whenever a control's size has been changed. I've mentioned it here because you would normally set it together with the other flags if it is useful for your control.
 

I've seen a few contradicting examples and explanations in this area and the problems are exacerbated by the current (as of Feb 2011) MSDN literature. As well as contradiction of my findings with the PaintBackground event and the surprising recommendation of DoubleBuffer (i.e. the older flag, currently hidden from Intellisense in the IDE) over OptimizedDoubleBuffer, the ControlStyles page is ambiguous about UserPaint and DoubleBuffer (there is a statement that it should be set for the DoubleBuffer flag to work and another that says it is implied by the DoubleBuffer flag).
 

I thought it would be interesting to see which flags are set by default on some of the familiar controls. Here is the full set of flags, the numeric value of each within the enum and those set by default ('*' in the 'T' column) for a control derived from Panel:

Hex      Binary                            T Name
=========================================================================
00000001 00000000000000000000000000000001: * ContainerControl
00000002 00000000000000000000000000000010: * UserPaint
00000004 00000000000000000000000000000100:   Opaque
00000010 00000000000000000000000000010000:   ResizeRedraw
00000020 00000000000000000000000000100000:   FixedWidth
00000040 00000000000000000000000001000000:   FixedHeight
00000100 00000000000000000000000100000000: * StandardClick
00000200 00000000000000000000001000000000:   Selectable
00000400 00000000000000000000010000000000:   UserMouse
00000800 00000000000000000000100000000000: * SupportsTransparentBackColor
00001000 00000000000000000001000000000000: * StandardDoubleClick
00002000 00000000000000000010000000000000:   AllPaintingInWmPaint
00004000 00000000000000000100000000000000:   CacheText
00008000 00000000000000001000000000000000:   EnableNotifyMessage
00010000 00000000000000010000000000000000:   DoubleBuffer
00020000 00000000000000100000000000000000:   OptimizedDoubleBuffer
00040000 00000000000001000000000000000000: * UseTextForAccessibility
 

I looked at the default flags for several different types of control and found varying results:

                        Name Panel Form Button TextBox Control
==============================================================
            ContainerControl   *     *                        
                   UserPaint   *     *    *               *   
                      Opaque              *                   
                ResizeRedraw              *                   
                  FixedWidth                                  
                 FixedHeight                      *           
               StandardClick   *     *                    *   
                  Selectable         *    *       *       *   
                   UserMouse              *                   
SupportsTransparentBackColor   *          *                   
         StandardDoubleClick   *     *                    *   
        AllPaintingInWmPaint              *       *       *   
                   CacheText              *                   
         EnableNotifyMessage                                  
                DoubleBuffer                                  
       OptimizedDoubleBuffer              *                   
     UseTextForAccessibility   *     *    *               *   

Lastly, it's worth just making a note about the best way of calling SetStyle(). The method declaration is:


protected void SetStyle(ControlStyles flag, bool value)

which at first glance might lead you to suspect that only a single flag can be set at once and you may see discussions of setting these flags which list several calls to this method. However, because of the way the SetStyle method is implemented, you can combine flag values as you normally would (i.e. with the '|' OR operator) and set several at once, providing you need to set each to the same Boolean value:

SetStyle (ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer,
true);

Clearly, a single call is the more efficient way to change several flags at once.

Thursday 10 February 2011

Visual Studio Tools for Office Notes

Recently, I've been writing a Visual Studio Tools for Office (or VSTO) application; specifically an addin for Outlook 2007. The relevant versions are Visual C# 2008 and VSTO 3.0. It's been an interesting process and I've discovered a few things about the library that I wanted to make a note of. Specifically, it's worth noting two limitations that anyone needs to be aware of when doing this kind of thing.

Firstly, presumably to aid end users with a more pleasant experience, exceptions are not handled the way you might expect… in most cases they are handled silently by the host application. This is definitely true for the Outlook 2007 plugin I've been building, but from Internet searches it looks like it also happens in at least some (i.e. document-level) Word plugins too. I'm not sure about other types of addin.

Visual Studio creates a class and default method,
ThisAddIn.ThisAddIn_Startup()
and this is the equivalent of Main() for addins as it gets called automatically when the addin is initialised (which usually happens when the host application is loaded). Interestingly, exceptions in the call to this method (and obviously, any nested calls within the addin at this point) operate as you would expect and are reported, but other entry points to your dll through other events do not result in an exception if / when a problem is hit.

Significantly for the developer, this means that whether or not you run the code in debug mode from the VS debugger, you don't get notified of exceptions – instead, the code just silently stops running and control is taken back by the host application (i.e. Outlook) instead of passed to the debugger. Obviously this is a major pain if you're not sure whether something's completed successfully or not, although it's worth pointing out that breakpoints and stepping through the code do still work fine (until you hit an exception, anyway).

The second problem I've had is Outlook specific. I was surprised to find that I cannot easily hook into the Send & Receive functionality. My original idea was to create an account within the standard Outlook account structure and allow users to add it to send / receive groups along with the standard email accounts (it's not actually an email account, but syncs note items). However, it seems that this part of the Outlook 2007 object model is not exposed in the VSTO .net interface: I can't add an account and there is no event when a send & receive takes place, let alone a notification that some specific account should undergo that process.

Now, VSTO is a .net wrapper for a more complex COM API, so it might well be possible using either a pure COM addin or manually accessing the underlying COM interface from a .net language (which I might look into), but it seemed to me to be a surprising omission for a relatively mature API. If anyone can offer any insights (particularly if I've missed anything obvious!), I'd love to know.

Wednesday 9 February 2011

Computer Clocks and VMWare ESXi

I recently noticed that my home Linux server, which now runs on VMWare ESXi was losing time when it was suspended by the ESXi server. Every time the guest was suspended, the clock just stopped and started again, possibly several days later, still using the time when the virtual machine was halted.

I checked the hardware clock (/sbin/hwclock – I needed to be root to do so on my Ubuntu distribution) and it was correct – like other VMWare products, ESXi mimics the CMOS clock of a real platform and uses the hardware clock to do so (and it can update this regularly using an NTP server) but the response from the date command was still stuck to the time a few days ago when the machine was switched off. Several of the “clocks” in our house show the time from this server, so it needs to be accurate. I waited half an hour to see if the time would sort itself out and so it would cross an hour boundary to see if that would help. It didn’t – all my clocks were still wrong.

I learned several things in my subsequent investigation which may prove useful or interesting to other people:
  • OSes only read the time from the hardware clock when they are booted up (or only every hour or so). After that, they count several times a second and derive the time and date from this counter. The CMOS clock only reports time to the nearest second and it is presumably quite slow to access so the OS sorts out the time after bootup itself. The ticker is often a hardware device (and several different ones can be used, depending on OS and available hardware), but will generally cause an interrupt that needs to be serviced on each tick.
  • Windows (NT derivatives only) updates the ticker once an hour from the system CMOS clock (correcting only if it is more than 60 seconds different). Linux generally does not do this.
  • Linux systems can cause resource-hogging problems depending on the kernel used. Earlier Linux systems used to tick at 100Hz, but newer (2.6 kernels) use a 1000Hz timer by default. In a virtual environment, this imposes a more significant resource drain since the whole VM must be switched into context on the host, rather than just whichever CPU mode is required to service the timer interrupts on a physical system. Kernel directives can force the timer to use 100Hz on a virtualised installation which can often be a good idea, especially if the number of guests running simultaneously is relatively high. Kernels newer than 2.6.28-7.18 are more VM friendly and perform timing operations in a different manner
  • As you might expect, if VMTools is installed and running correctly (which I thought it was, but for some reason I still haven’t been able to replicate, it wasn’t running when my machine came out of suspend) this is all taken care of automatically.

MS Word: Automatic date fields


This is a post detailing the way I managed to get Word to create a date automatically with ordinal suffixes and superscript and is written in something of a tutorial style. If you already know about / aren’t interested in the details of Word fields, skip to the highlighted block about 2/3 of the way down and you’ll find the field codes necessary to achieve the result.

I recently decided to write myself a letter template. Even these days, everyone writes letters from time to time and so it seemed a good idea to have a .dotx file that would generate a suitable blank whenever I wanted to start a new one. I like to have the numbers in a date be followed by “st”, “nd” etc., and for these postscripts to be in superscript. This doesn’t seem difficult; after all, word adds the suffix automatically if you type the date in manually and you can insert a field that will fill the date in automatically. Unfortunately, these two techniques do not work together.

The first problem is getting the right date. Inserting a date using the ribbon (I’m using Word 2007 – I expect earlier versions are similar but I haven’t tried, nor have I experimented with 2010 yet) gives you the current date. That means that the date will never change, or if you tick the box that says “Update Automatically” will change every time the field is updated – not much good if you go back to the letter later for reference purposes and cannot tell when you wrote it because it has today’s date on it.

The second is that the list of formats you can choose from does not include a format which produces the “st”, “nd”, etc. suffixes. A number followed by these letters is said to be in ordinal format in Word-speak, incidentally. Perhaps elsewhere too, but I’m not sure it’s universal nomenclature.

Both these problems can be solved rather easily by amending the field directly. If you don’t know, the contents of Word’s fields are represented internally in a slightly cryptic written language. You can view this by right-clicking a field and selecting “Toggle Field Codes”. Alt-F9 will toggle code viewing for the entire document and is quite useful for fields within fields (nested fields) as they don’t all expand at once if you go down the right-click the path.

If you insert an automatically updating date and view the field code, you will see that it is created like this:
{ DATE \@ "dd MMMM yyyy" }
What’s between the inverted commas will be different unless you’ve picked the same date format as me. You can now directly change the code that generates this field.

The first problem (constantly updated date) is solved by changing the word “DATE” to “CREATEDATE”. This keyword determines what the field code does (and you will see one at the start of most fields if you look at the code). In this case, CREATEDATE generates a date based on the time the document was first created. Be aware that this is determined by the “Save As” dialog being used, so if you save an existing document with another name from within Word, this date will change in the newly named document at that point.

The “\@” merely tells Word that what comes next is a template for the date. Word calls this template a picture and the “\@” is the “picture switch”. In more general terms, a switch is a modifier to a command and is indicated here by the backslash. The picture template for this and other date fields has many components to do with date and time and this is beyond our scope here.

We can also use a switch to use the ordinal format for numbers:
{CREATEDATE \@ "d" \* ordinal}
This switch, however, modifies any numeric field to use the ordinal suffix, not just dates. As such, it does not understand the special needs of a date field and produces rubbish if you include it in a full date (with months and years in it). This is why the example above includes a directive only to show the day of the month.
To show a complete date, two adjacent fields must be employed:
{CREATEDATE \@ "d" \* ordinal}{CREATEDATE \@ " MMMM yyyy"}
Note the space before the “MMMM” inside the quotes – this gives us the space we need between the ordinal suffix and month name.

In order to form this into a single field you can use a “QUOTE” type field to encapsulate the other two. QUOTE fields simply repeat what is in them, but they can include embedded fields and so you end up with a single field that can be moved and formatted as a single object in your text:
{ QUOTE{CREATEDATE \@ "d" \* ORDINAL }{CREATEDATE \@ " MMMM yyyy" } }
So this is almost what we want. What we have now is something like this:
9th February 2010
The last problem is the superscript we want for the ordinal day suffix. Relatively simple? I’m afraid not. The \* ORDINAL switch must apply to a number, which is also printed. There is no way to make it print the suffix on its own, which means that we cannot simply create a separate field for the suffix and superscript it. There is no switch to make the suffix superscript on its own and so we cannot separate the two to allow us to format the digits and the suffix separately.

The only way to do it is to write some relatively complicated code to produce the suffixes (suffices?) based on the number from scratch and then formatting (i.e. superscript) can be applied to these letters within the field and when they are printed they will be as we want. Here is the code (and note the use of superscript within it):
{ QUOTE { CREATEDATE \@ “D” }{ IF { =MOD( { CREATEDATE \@ “d” },20) } = 1 “st” “{ IF { = MOD( { CREATEDATE \@ “d” } ,20) } = 2 “nd” “{ IF { =MOD( { CREATEDATE \@ “d” } ,20) } = 3 “rd” “{ IF { CREATEDATE \@ “d” } = 31 “st” “th” }” }“ }“ }{ CREATEDATE \@ “ MMMM yyyy” } }

Finally, we have the format I was originally after:
9th February 2010
I’ve seen some more complicated versions of this in other places, but this is my take on it. Do note, however, that the suffix creation algorithm is only suitable for dates – it will fail as soon as you count above 31! In a more easily read form it looks like this (and there’s no reason not to put it like this into your documents – it won’t spoil the layout once the field codes are hidden):
{ QUOTE
{ CREATEDATE \@ "D" }
{ IF { =MOD( { CREATEDATE \@ "d" },20) } = 1
"st"
"{ IF { = MOD( { CREATEDATE \@ "d" } ,20) } = 2
"nd"
"{ IF { =MOD( { CREATEDATE \@ "d" } ,20) } = 3
"rd"
"{ IF { CREATEDATE \@ "d" } = 31 "st" "th" }"
}"
}"
}
{ CREATEDATE \@ " MMMM yyyy" }
}
The new things introduced here are IF and MOD, as well as the “=” just before the MOD operator.

MOD is not a type of field, so we cannot put it at the start of a field as a type identifier. Instead it is a function – something we might choose to use in a mathematical expression. So, we need to know how to make a field produce the result of a mathematical expression and it will come as no surprise from the usage above that “=” is the field type identifier that does that: whatever is displayed from an “=” field is the result of a mathematical expression.

Those of you familiar with the MOD function will know that it simply divides one number (in this case the first number in brackets after the word) by another (the second number in the brackets) and keeps only the remainder. You will see that the first number (or argument) to the MOD operation is generated by a nested field (the CREATEDATE field just after the opening bracket. In this case we are using MOD to ensure that 21, 22 and 23 but not 11, 12 and 13 are treated the same as 1, 2 and 3, which is what we want (so we don't need separate tests for 1 and 21). There is also a special test right at the end for 31, which is an exception to the rule we have created (which generalised is that numbers in the 0s, 20s, 40s etc. receive special treatment and 10s, 30s, 50s etc. do not).

The IF field type prints one of two things depending on a comparison:
{ IF a = b "True Text" "False Text" }
Although I have written it as an equality test here, the comparison can be one of the other mathematical operations, such as greater than, less than or equal to, etc. The result is whatever is in the first set of quotes if the comparison is true and whatever is in the second if it is false. And you can nest other fields in these quotes which is how the composite field above is created. In the spaced out version, each new line starts further indented if the field is nested inside the previous one. As each field closes, the indentation is also reduced.

Just as a reminder, you cannot simply type (or copy and paste), unfortunately – each field must be created as a field in word. There is a quick way and that is to write the contents of the field (don’t include the outer curly brackets – these are displayed by word only to tell you that you are looking at field codes and are not part of the field), select the text that will form the field and press Ctrl-F9. You can also copy and paste fields, of course, which makes the plethora of identical CREATEDATE fields easier to deal with. Also, watch your spaces - you may end up quoting some you don't want as you construct the fields.

As a final note, when you are experimenting, don’t forget to update the field if you make changes to the field code or your changes may not be processed (F9 does this). If you are working with more than one field, the contents of all of them might not be updated together.

Drawing in (C#) .net programs: Dispose()

It is common to see warnings that dispose() should always be called on certain System.Drawing objects (Graphics, Brush, Pen, etc.) when you have finished with them. The reason for this is that these objects use (non-managed) GDI handles. If they are not collected by the GC in a timely fashion, the OS might run out of these handles, which are apparently in limited supply. I’ve never seen anyone explain what would happen in this case, or seen any problems that have been traced to this. Presumably in the vast majority of cases, the GC kicks in way before this scarce resource is used up.

However, that is not to say that it is a fruitless exercise; on the contrary, I’m sure that it would not be commented on in MSDN literature if it were not a problem, but it’s not always made clear (especially in brief articles) when one shouldn’t call dispose(). The rule is really quite obvious: if you didn't call new on it, you shouldn't call dispose() on it.

First of all, a lot of drawing is naturally done in the OnPaint() method of controls. Helpfully, you are passed a Graphics object as part of the PaintEventArgs object that accompanies the Paint event. Don’t dispose() of this! It is passed along the chain of subscribers to the Paint event, so disposal can obviously only be done at the end of this process, not in any of the OnPaint overrides or other event subscribers.

As a side note, it is usually suggested that override OnPaint() should call base.OnPaint(). There is a note on one of the MSDN pages, however, that explains that if the current class is able to take responsibility for the whole of the painting process, this is not necessary. The context is that of a class derived directly from Control, so do be careful – someone may have done something in a base class other than Control which affects the object’s state outside the drawing domain.

Dispose() should also be called on objects of type Pen and Brush. Again, this only applies to objects that you create. In particular, Brushes.DarkGreen, for example (and the similar set of other brushes and pens in the Pens static class) should not “normally” be disposed (quote from MSDN). You can use these to instantiate new objects. In this case, of course, the new object will need to be disposed when you have finished with it.

Finally, it is worth noting that the best way to call dispose() is to use the using() statement instead. Any exceptions before the dispose() call is made (either in the main code or in a finally{…} block, if the call is there) will cause the dispose() call to be missed. Using() creates a finally{…} block behind the scenes but because it is hidden, no potentially erroneous code can be introduced into it.

Incidentally, remember that using() can look after more than one object. Two objects of the same type can be declared in the same using() statement separated by commas:
using (Brush a, b)
{
    …
}

Nested using()s will work for objects of differing types (you may think they don't look nested, but the second is effectively the code block for the first):
using (Brush a)
using (Pen b)
{
   …
}