- Stick a Note on Your Desktop
- NoteWhen: Download It Here
I wanted to include the ability to edit note text directly in the note window. I knew an edit control would work well if I could make the control blend in with the rest of the note. Unless you specify otherwise, edit controls always base their background and text colors on the window and text colors the user sets in the Control Panel. This wasn't acceptable for my note windows. I wanted the edit control to use the font, background, and text colors the user would select in NoteWhen's Font dialog.
Windows provides an easy way to customize the appearance of its built-in control types. This is done through various WM_CTLCOLORxx messages. These messages are sent to the parent window that contains the control. The messages let you specify the various attributes that Windows will use to draw the control. MFC provides the OnCtlColor() method for handling WM_CTLCOLOR messages. For an example of how to set the colors and font for an edit control, take a look at my note window's OnCtlColor() method (see Note.cpp). The handler first determines whether there is an active background brush for the window. If not, the handler creates a new brush object and saves it in the member variable m_hbrBackground. Next, the handler sets the appropriate background and text color for the note. Finally, the handler returns the handle from the previously created brush object.
Although color handlers are a basic part of Windows programming, they have one odd quirk that is easy to forget if you don't write these types of handlers frequently. Many Windows operations require that handles be passed as parameters. For example, to copy items to the clipboard, you must allocate a block of memory and pass its handle to Windows, which takes ownership of the memory. In this case, Windows manages the memory and releases it when the clipboard no longer needs it. The region handle passed to SetWindowsRgn() works in this way, too. Once you pass that handle to Windows, it's no longer yours, and you'd better not try to delete it!
You might assume color handlers work the same way, because they allocate a background brush and pass the handle back to Windows. Unfortunately, the assumption is incorrect. I created my brush on the stack and passed its handle back to Windows. This worked as expected, changing the edit control's background to the appropriate color. But opening a large number of notes caused some serious problems, reducing the amount of free system resources to around 10 percent.
Clearly, NoteWhen had a resource leak, but I had no idea where. Merely leaving notes on the screen for extended periods seemed to trigger the leak. I searched through my code to find the culprit. After commenting out portions of code, I eventually isolated the leak, which was in the edit control used by note windows. Commenting out the code to create the edit control stopped the leak. I pondered how a normal edit control could cause a resource leak, completely forgetting about my specialized WM_CTLCOLOR handler. When I remembered the handler, I thought about the background brush it was creating. I changed my background-brush creation code to create the brush as a class member rather than on the stack, and voila! No more leak!