Introduction

WTL contains many wrappers and utility classes that haven't gotten full coverage yet in this series, such as
CString and CDC. WTL has a nice system for wrapping GDI objects, some useful functions
for loading resources, and classes that make it easier to use some of the Win32 common dialogs. Here in Part IX,
I'll cover some of the most commonly-used utility classes.

This article discusses four categories of features:

GDI wrapper classes

Resource-loading functions

Using the file-open and choose-folder common dialogs

Other useful classes and global functions

GDI Wrapper Classes

WTL takes a rather different approach to its GDI wrappers than MFC. WTL's approach is to have one template class
for each type of GDI object, each template having one bool parameter called t_bManaged.
This parameter controls whether an instance of that class "manages" (or owns) the wrapped GDI object.
If t_bManaged is false, the C++ object does not manage the lifetime of the GDI object;
the C++ object is a simple wrapper around the GDI object handle. If t_bManaged is true,
two things change:

The destructor calls DeleteObject() on the wrapped handle, if it is not NULL.

Attach() calls DeleteObject() on the wrapped handle, if it is not NULL, before attaching
the C++ object to the new handle.

This design is in line with the ATL window classes, where CWindow is a plain wrapper around an
HWND, and CWindowImpl manages the lifetime of a window.

The GDI wrapper classes are defined in atlgdi.h, with the exception of CMenuT, which is
in atluser.h. You don't have to include these headers yourself, because atlapp.h always includes
them for you. Each class also has typedefs with easier-to-remember names:

Wrapped GDI object

Template class

Typedef for managed object

Typedef for plain wrapper

Pen

CPenT

CPen

CPenHandle

Brush

CBrushT

CBrush

CBrushHandle

Font

CFontT

CFont

CFontHandle

Bitmap

CBitmapT

CBitmap

CBitmapHandle

Palette

CPaletteT

CPalette

CPaletteHandle

Region

CRgnT

CRgn

CRgnHandle

Device context

CDCT

CDC

CDCHandle

Menu

CMenuT

CMenu

CMenuHandle

I like this approach, compared to MFC which passes around pointers to objects. You never have to worry about
getting a NULL pointer (the wrapped handle might be NULL, but that's another matter), nor do you have any special
cases where you get a temporary object that you can't hang on to for more than one function call. It is also very
cheap to create an instance of any of these classes since they only have one member variable, the handle being
wrapped. As is the case with CWindow, there is no problem passing a wrapper class object between threads,
since WTL keeps no thread-specific maps like MFC.

There are additional device context wrapper classes for use in special drawing scenarios:

CClientDC: Wraps calls to GetDC() and ReleaseDC(), used to draw in a
window's client area

CWindowDC: Wraps calls to GetWindowDC() and ReleaseDC(), used to draw
anywhere in a window.

CPaintDC: Wraps calls to BeginPaint() and EndPaint(), used in a WM_PAINT
handler.

Each of these classes takes a HWND in the constructor, and behaves like the MFC classes of the
same name. All three are derived from CDC, so these classes all manage their device contexts.

Common functions in the wrapper classes

The GDI wrapper classes follow the same design. To be concise, I'll cover the methods in CBitmapT
here, but the other classes work similarly.

The wrapped GDI object handle

Each class keeps one public member variable that holds the GDI object handle that the C++ object is associated
with. CBitmapT has an HBITMAP member called m_hBitmap.

Constructor

The constructor has one parameter, an HBITMAP, which defaults to NULL. m_hBitmap
is initialized to this value.

Destructor

If t_bManaged is true, and m_hBitmap is not NULL, then the destructor calls DeleteObject()
to destroy the bitmap.

Attach() and operator =

These methods both take an HBITMAP handle. If t_bManaged is true, and
m_hBitmap is not NULL, these methods call DeleteObject() to destroy the bitmap that the
CBitmapT object is managing. Then they set m_hBitmap to the HBITMAP that
was passed in as the parameter.

Detach()

Detach() sets m_hBitmap to NULL, then returns the value that was in m_hBitmap.
After Detach() returns, the CBitmapT object is no longer associated with a GDI bitmap.

Methods for creating a GDI object

CBitmapT has wrappers for the Win32 APIs that create a bitmap: LoadBitmap(), LoadMappedBitmap(),
CreateBitmap(), CreateBitmapIndirect(), CreateCompatibleBitmap(), CreateDiscardableBitmap(),
CreateDIBitmap(), and CreateDIBSection(). These methods will assert if m_hBitmap
is not NULL; to reuse a CBitmapT object for a different GDI bitmap, call DeleteObject()
or Detach() first.

DeleteObject()

DeleteObject() destroys the GDI bitmap object, then sets m_hBitmap to NULL. This
method should be called only if m_hBitmap is not NULL; it will assert otherwise.

IsNull()

IsNull() returns true if m_hBitmap is NULL, or false otherwise.
Use this method to test whether the CBitmapT object is currently associated with a GDI bitmap.

operator HBITMAP

This converter returns m_hBitmap, and lets you pass a CBitmapT object to a function
or Win32 API that takes an HBITMAP handle. This converter is also called when a CBitmapT
is evaluated in a boolean context, and evaluates to the logical opposite of IsNull(). Therefore, these
two if statements are equivalent:

CBitmapT has a type-safe wrapper for the Win32 API GetObject(): GetBitmap().
There are two overloads: one that takes a LOGBITMAP* and calls straight through to GetObject();
and one that takes a LOGBITMAP& and returns a bool indicating success. The latter
version is the easier one to use. For example:

CBitmapT has wrappers for Win32 APIs that take an HBITMAP parameter: GetBitmapBits(),
SetBitmapBits(), GetBitmapDimension(), SetBitmapDimension(), GetDIBits(),
and SetDIBits(). These methods will assert if m_hBitmap is NULL.

Other utility methods

CBitmapT has two useful methods that operate on m_hBitmap: LoadOEMBitmap()
and GetSize().

Using CDCT

CDCT is a bit different from the other classes, so I'll cover the differences separately.

Differences in methods

The method to destroy a DC is called DeleteDC() instead of DeleteObject().

Selecting objects into a DC

One aspect of MFC's CDC that is prone to errors is selecting objects into a DC. MFC's CDC
has several overloaded SelectObject() functions that each take a pointer to a different kind of GDI
wrapper class (CPen*, CBitmap*, and so on). If you pass a C++ object to SelectObject(),
instead of a pointer to a C++ object, the code ends up calling the undocumented overload that accepts an HGDIOBJ
handle, and this is what causes the problems.

WTL's CDCT takes a better approach, and has several select methods, each of which works with just
one type of GDI object:

In debug builds, each method asserts that m_hDC is not NULL, and that the parameter is a handle
to the correct type of GDI object. They then call the SelectObject() API and cast the SelectObject()
return value to the appropriate type.

There are also helper methods that call GetStockObject() with a given constant, and then select
the object into the DC:

Differences from the MFC wrapper classes

Fewer constructors: The wrappers classes lack constructors that create a new GDI object. For example,
MFC's CBrush has constructors that create a solid or patterned brush. With the WTL classes, you must
use a method to create the GDI object.

Selecting objects into a DC is done better: See the Using CDCT section above.

No m_hAttribDC: WTL's CDCT does not have a m_hAttribDC
member.

Minor parameter differences in some methods: For example, CDC::GetWindowExt() returns a
CSize object in MFC; while in WTL the method returns a bool, and the size is returned
via an output parameter.

Resource-Loading Functions

WTL has several global functions that are helpful shortcuts for loading various types of resources. We'll need
to know about one utility class before getting on to the functions: _U_STRINGorID.

In Win32, most types of resources can be identified by a string (LPCTSTR) or an unsigned integer
(UINT). APIs that take a resource identifier take an LPCTSTR parameter, and if you want
to pass a UINT, you need to use the MAKEINTRESOURCE macro to convert it to an LPCTSTR.
_U_STRINGorID, when used as the type of a resource identifier parameter, hides this distinction so
that the caller can pass either a UINT or LPCTSTR directly. The function can then use
a CString to load the string if necessary:

This works because the CString constructor that takes an LPCTSTR checks whether the
parameter is actually a string ID. If so, the string is loaded from the string table and assigned to the CString.

In VC 6, _U_STRINGorID is provided by WTL in atlwinx.h. In VC 7, _U_STRINGorID
is part of ATL. Either way, the class definition will always be included for you by other ATL/WTL headers.

The functions in this section load a resource from the resource instance handle kept in the _Module
global variable (in VC 6) or the _AtlBaseModule global (in VC 7). Using other modules for resources
is beyond the scope of this article, so I will not be covering it here. Just remember that by default, the functions
look in the EXE or DLL that the code is running in. The functions do nothing more than call through to APIs, their
utility is in the simplified resource identifier handling provided by _U_STRINGorID.

HACCEL AtlLoadAccelerators(_U_STRINGorID table)

Calls through to LoadAccelerators().

HMENU AtlLoadMenu(_U_STRINGorID menu)

Calls through to LoadMenu().

HBITMAP AtlLoadBitmap(_U_STRINGorID bitmap)

Calls through to LoadBitmap().

HCURSOR AtlLoadCursor(_U_STRINGorID cursor)

Calls through to LoadCursor().

HICON AtlLoadIcon(_U_STRINGorID icon)

Calls through to LoadIcon(). Note that this function - like LoadIcon() - can only
load 32x32 icons.

Call through to LoadString(). The string can be returned in either a TCHAR buffer,
or assigned to a BSTR, depending on which overload you use. Note that these functions only accept
a UINT as the resource ID, because string table entries cannot have string identifiers.

This group of functions wrap calls to LoadImage(), and take additional parameters that are passed
on to LoadImage().

Calls LoadImage() with the IMAGE_CURSOR type, passing along the fuLoad
flags. Since one cursor resource can contain several different-sized cursors, you can pass dimensions for the cxDesired
and cyDesired parameters to load a cursor with a particular size.

Calls LoadImage() with the IMAGE_ICON type, passing along the fuLoad
flags. The cxDesired and cyDesired parameters are used as in AtlLoadCursorImage().

This group of functions wrap calls to load system-defined resources (for example, the standard hand cursor).
Some of these resource IDs (mostly the ones for bitmaps) are not included by default; you need to #define
the OEMRESOURCE symbol in your stdafx.h in order to reference them.

HBITMAP AtlLoadSysBitmap(LPCTSTR lpBitmapName)

Calls LoadBitmap() with a NULL resource handle. Use this function to load any of the OBM_*
bitmaps listed in the LoadBitmap() documentation.

HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName)

Calls LoadCursor() with a NULL resource handle. Use this function to load any of the IDC_*
cursors listed in the LoadCursor() documentation.

HICON AtlLoadSysIcon(LPCTSTR lpIconName)

Calls LoadIcon() with a NULL resource handle. Use this function to load any of the IDI_*
icons listed in the LoadIcon() documentation. Note that this function - like LoadIcon()
- can only load 32x32 icons.

Each function checks that you're passing in a sensible value (e.g., AtlGetStockPen() only accepts
WHITE_PEN, BLACK_PEN, and so on), then calls through to GetStockObject().

Using Common Dialogs

WTL has classes that make using the Win32 common dialogs easier. Each class handles messages and callbacks that
the common dialog sends, and in turn calls overridable functions. This is the same design used in property sheets,
where you write handlers for individual property sheet notifications (e.g., OnWizardNext() for handling
PSN_WIZNEXT) that are called by CPropertyPageImpl when necessary.

WTL contains two classes for each common dialog; for example, the Choose Folder dialog is wrapped by CFolderDialogImpl
and CFolderDialog. If you need to change any defaults or write handlers for any messages, you derive
a new class from CFolderDialogImpl and make the changes in that class. If the default behavior of
CFolderDialogImpl is sufficient, you can use CFolderDialog.

The common dialogs and their corresponding WTL classes are:

Common dialog

Corresponding Win32 API

Implementation class

Non-customizable class

File Open and File Save

GetOpenFileName(),GetSaveFileName()

CFileDialogImpl

CFileDialog

Choose Folder

SHBrowseForFolder()

CFolderDialogImpl

CFolderDialog

Choose Font

ChooseFont()

CFontDialogImpl,CRichEditFontDialogImpl

CFontDialog,CRichEditFontDialog

Choose Color

ChooseColor()

CColorDialogImpl

CColorDialog

Printing and Print Setup

PrintDlg()

CPrintDialogImpl

CPrintDialog

Printing (Windows 2000 and later)

PrintDlgEx()

CPrintDialogExImpl

CPrintDialogEx

Page Setup

PageSetupDlg()

CPageSetupDialogImpl

CPageSetupDialog

Text find and replace

FindText(),ReplaceText()

CFindReplaceDialogImpl

CFindReplaceDialog

Since writing about all those classes would make this article far too long, I'll cover just the first two, which
are the ones you'll likely use most often.

CFileDialog

CFileDialog, and its base CFileDialogImpl, are used to show File Open and File Save
dialogs. The two most important data members in CFileDialogImpl are m_ofn and m_szFileName.
m_ofn is an OPENFILENAME that CFileDialogImpl sets up for you with some
meaningful default values; just as in MFC, you can change the data in this struct directly if necessary. m_szFileName
is a TCHAR array that holds the name of the selected file. (Since CFileDialogImpl only
has this one string for holding a filename, you'll need to provide your own buffer when you use a multiple-select
open file dialog.)

The basic steps in using a CFileDialog are:

Construct a CFileDialog object, passing any initial data to the constructor.

bOpenFileDialog should be true to create a File-Open dialog (CFileDialog
will call GetOpenFileName() to show the dialog), or false to create a File-Save dialog
(CFileDialog will call GetSaveFileName()). The remaining parameters are stored directly
in the appropriate members of the m_ofn struct, but they are optional since you can access m_ofn
directly before calling DoModal().

A significant difference between MFC's CFileDialog is that the lpszFilter parameter
must be a null-character-delimited string list (that is, the format documented in the OPENFILENAME
docs), instead of a pipe-separated list.

Here is an example of using a CFileDialog with a filter that selects Word 12 files (*.docx):

CFileDialog isn't very localization-friendly, since the constructor uses LPCTSTR parameters.
That filter string is also a bit hard to read at first glance. There are two solutions, either set up m_ofn
before calling DoModal(), or derive a new class from CFileDialogImpl that has the improvements
we want. We'll take the second approach here, and make a new class that has the following changes:

The string parameters in the constructor are _U_STRINGorID instead of LPCTSTR.

The filter string can use pipes to separate the fields, as in MFC, instead of null characters.

The dialog will be automatically centered relative to its parent window.

We'll start by writing a class whose constructor takes parameters similar to the CFileDialogImpl
constructor:

Note that the string parameters are all NULL in the call to the base class constructor. This is because the
base class constructor is always called before member initializers. To set up the string data in m_ofn,
we add some code that duplicates the initialization steps that the CFileDialogImpl constructor would
do:

PrepFilterString() is a helper method that takes a pipe-delimited filter string, changes the pipes
to null characters, and returns a pointer to the beginning of the string. The result is a string list that's in
the proper format for use in an OPENFILENAME.

Those changes make the string-handling easier. To implement automatic centering, we'll override the OnInitDone()
notification. This requires us to add a message map (so we can chain notification messages to the base class),
and our OnInitDone() handler:

The window attached to the CMyFileDialog object is actually a child of the File Open dialog. Since
we need the top-most window in the stack, we call GetFileDialogWindow() to get that window.

CFolderDialog

CFolderDialog, and its base CFolderDialogImpl, are used to show a Browse For Folder
dialog. While the dialog supports browsing anywhere within the shell namespace, CFolderDialog is only
capable of browsing within the file system. The two most important data members in CFolderDialogImpl
are m_bi and m_szFolderPath. m_bi is an BROWSEINFO that CFolderDialogImpl
manages and passes to the SHBrowseForFolder() API; you can change the data in this struct directly
if necessary. m_szFolderPath is a TCHAR array that holds the name of the selected folder.

The basic steps in using a CFolderDialog are:

Construct a CFolderDialog object, passing any initial data to the constructor.

Call DoModal().

If DoModal() returns IDOK, get the path to the selected folder from m_szFolderPath.

hWndParent is the owner window for the browse dialog. You can either set it here in the constructor,
or in the DoModal() call. lpstrTitle is a string that will be shown above the tree control
in the dialog. uFlags are flags that control the dialog's behavior, and should always include BIF_RETURNONLYFSDIRS
so the tree only shows file system directories. Other values for uFlags that you can use are listed
in the docs for BROWSEINFO, but remember that some flags may not produce good results, such as BIF_BROWSEFORPRINTER.
UI-related flags like BIF_USENEWUI will work fine. Note that the lpstrTitle parameter
has the same usability problems as the strings in the CFileDialog constructor.

To demonstrate customizing CFolderDialog, we'll derive a class from CFolderDialogImpl
and set the initial selection. This dialog's callbacks don't use window messages, so the class doesn't need a message
map. Instead, we override the OnInitialized() method, which gets called when the base class receives
the BFFM_INITIALIZED notification. OnInitialized() calls CFolderDialogImpl::SetSelection()
to change the selection in the dialog.

Other useful classes and global functions

Struct wrappers

WTL has the classes CSize, CPoint, and CRect, that wrap the SIZE,
POINT, and RECT structs respectively. They work like their MFC counterparts.

Classes for handling dual-typed arguments

As mentioned earlier, you can use the _U_STRINGorID type for a function parameter that can be a
numeric or string resource ID. There are two other classes that work similarly:

_U_MENUorID: This type can be constructed from a UINT or HMENU, and
is meant to be used in CreateWindow() wrappers. The hMenu parameter to CreateWindow()
is actually a window ID when the window being created is a child window, so _U_MENUorID hides the
distinction between the two usages. _U_MENUorID has one member m_hMenu, which can be
passed as the hMenu parameter to CreateWindow() or CreateWindowEx().

_U_RECT: This type can be constructed from a LPRECT or RECT&, and
lets the caller pass in a RECT struct, pointer to a RECT, or a wrapper class like CRect
that provides a converter to RECT.

As with _U_STRINGorID, _U_MENUorID and _U_RECT are always included for
you by other headers.

Other utility classes

CString

WTL's CString works just like MFC's CString, so I won't be covering it in detail here.
WTL's CString has many extra methods that are used when you build with _ATL_MIN_CRT defined.
These methods, like _cstrchr(), _cstrstr(), are replacements for the corresponding CRT
functions, which aren't available when _ATL_MIN_CRT is defined.

CFindFile

CFindFile wraps the FindFirstFile() and FindNextFile() APIs, and is a
bit easier to use than MFC's CFileFind. The general pattern of usage goes like this:

If FindFirstFile() returns true, at least one file matched the pattern. Inside the
do loop, you can access the public CFindFile member m_fd, which is a WIN32_FIND_DATA
struct that holds the info about the file that was found. The loop continues until FindNextFile()
returns false, indicating that all files have been enumerated.

CFindFile has methods that return the data from m_fd in easier-to-use forms. These
methods return meaningful values only after a successful call to FindFirstFile() or FindNextFile().

These methods return the ftLastWriteTime, ftLastAccessTime, and ftCreationTime
members from m_fd respectively.

CFindFile also has some helper methods for checking the attributes of the file that was found.

BOOL IsDots()

Returns true if the found file is the "." or ".."
directory.

BOOL MatchesMask(DWORD dwMask)

Compares the bits in dwMask (which should be the FILE_ATTRIBUTE_* constants) with
the attributes of the file that was found. Returns true if all the bits that are on in dwMask
are also on in the file's attributes.

These methods are shortcuts that call MatchesMask() with a particular FILE_ATTRIBUTE_*
bit. For example, IsReadOnly() calls MatchesMask(FILE_ATTRIBUTE_READONLY).

Global functions

WTL has several useful global functions that you can use to do things like DLL version checks and show message
boxes.

bool AtlIsOldWindows()

Returns true if the operating system is Windows 95, 98, NT 3, or NT 4.

HFONT AtlGetDefaultGuiFont()

Returns the value of GetStockObject(DEFAULT_GUI_FONT). In English Windows 2000 and later (and other
single-byte languages that use the Latin alphabet), this font's face name is "MS Shell Dlg". This is
usable as a dialog box font, but not the best choice if you are creating your own fonts for use in your UI. MS
Shell Dlg is an alias for MS Sans Serif, instead of the new UI font, Tahoma. To avoid getting MS Sans Serif, you
can get the font used for message boxes with this code:

These functions look in a given module for an exported function called DllGetVersion(). If the
function is found, it is called. If DllGetVersion() is successful, it returns the version information
in a DLLVERSIONINFO struct.

HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)

Returns the major and minor versions of comctl32.dll.

HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)

Returns the major and minor versions of shell32.dll.

bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)

Truncates a file path so it is less than cchLen characters in length, adding an ellipsis at the
end if the path is too long. This works similarly to the PathCompactPath() and PathSetDlgItemPath()
functions in shlwapi.dll.

Displays a message box, like MessageBox(), but uses _U_STRINGorID parameters so you
can pass string resource IDs. AtlMessageBox() handles loading the strings if necessary.

Macros

There are various preprocessor macros that you'll see referenced in the WTL header files. Most of these macros
can be set in the compiler settings to change behavior in the WTL code.

These macros are predefined or set by build settings, you'll see them referenced throughout the WTL code:

_WTL_VER

Defined as 0x0710 for WTL 7.1.

_ATL_MIN_CRT

If defined, ATL does not link to the C runtime library. Since some WTL classes (notably CString)
normally use CRT functions, special code is compiled that replaces the code that would normally be imported from
the CRT.

_ATL_VER

Predefined as 0x0300 for VC 6, 0x0700 for VC 7, and 0x0800 for VC 8.

_WIN32_WCE

Defined if the current compilation is for a Windows CE binary. Some WTL code is disabled when the corresponding
features are not available in CE.

The following macros are not defined by default. To use a macro, #define it before all #include
statements in stdafx.h.

_ATL_NO_OLD_NAMES

This macro is only useful if you are maintaining WTL 3 code. It adds some compiler directives to recognize
two old class names: CUpdateUIObject becomes CIdleHandler, and DoUpdate()
becomes OnIdle().

_ATL_USE_CSTRING_FLOAT

Define this symbol to enable floating-point support in CString; _ATL_MIN_CRT must
not also be defined. You need to define this symbol if you plan to use the %I64 prefix in a
format string that you pass to CString::Format(). Defining _ATL_USE_CSTRING_FLOAT results
in CString::Format() calling _vstprintf(), which understands the %I64 prefix.

_ATL_USE_DDX_FLOAT

Define this symbol to enable floating-point support in the DDX code; _ATL_MIN_CRT must not
also be defined.

_ATL_NO_MSIMG

Define this symbol to prevent the compiler from seeing a #pragma comment(lib, "msimg32")
line; also disables code in CDCT that uses msimg32 functions: AlphaBlend(), TransparentBlt(),
GradientFill().

_ATL_NO_OPENGL

Define this symbol to prevent the compiler from seeing a #pragma comment(lib, "opengl32")
line; also disables code in CDCT that uses OpenGL.

_WTL_FORWARD_DECLARE_CSTRING

Obsolete, use _WTL_USE_CSTRING instead.

_WTL_USE_CSTRING

Define this symbol to forward-declare CString. This way, code in headers that are normally included
before atlmisc.h will be able to use CString.

_WTL_NO_CSTRING

Define this symbol to prevent usage of WTL::CString.

_WTL_NO_AUTOMATIC_NAMESPACE

Define this symbol to prevent automatic execution of a using namespace WTL directive.

_WTL_NO_AUTO_THEME

Define this symbol to prevent CMDICommandBarCtrlImpl from using XP themes.

_WTL_NEW_PAGE_NOTIFY_HANDLERS

Define this symbol to use newer PSN_* notification handlers in CPropertyPage. Since
the old WTL 3 handlers are obsolete, this symbol should always be defined unless you are maintaining WTL 3 code
that can't be updated.

_WTL_NO_WTYPES

Define this symbol to prevent the WTL versions of CSize, CPoint, and CRect
from being defined.

_WTL_NO_THEME_DELAYLOAD

When building with VC 6, define this symbol to prevent uxtheme.dll from being automatically marked as
a delay-load DLL.

NOTE: If neither _WTL_USE_CSTRING nor _WTL_NO_CSTRING is defined, then CString can
be used at any point after atlmisc.h is included.

The Sample Project

The demo project for this article is a downloader application called Kibbles that demonstrates the various classes
that have been covered in this article. It uses the BITS
(background intelligent transfer service) component that you can get for Windows 2000 and later; since this
app only runs on NT-based OSes, I also made it a Unicode project.

The app has a view window that shows the download progress, using various GDI calls including Pie()
which draws the pie chart shapes. When the app is first run, you'll see the UI in its initial state:

You can drag a link from a browser into the window to create a new BITS job that will download the target of
the link to your My Documents folder. You can also click the third toolbar button to add any URL that you want to
the job. The fourth button lets you change the default download directory.

When a download job is in progress, Kibbles shows some details about the job, and shows the download progress
like so:

The first two buttons in the toolbar let you change the colors used in the progress display. The first button
opens an options dialog where you can set the colors used for various parts of the display:

The dialog uses the great button class from Tim Smith's article Color Picker
for WTL with XP themes; check out the CChooseColorsDlg class in the Kibbles project to see it
in action. The Text color button is a regular button, and the OnChooseTextColor() handler demonstrates
how to use the WTL class CColorDialog. The second toolbar button changes all the colors to random
values.

The fifth button lets you set a background picture, which will be drawn in the part of the pie that shows how
much has been downloaded. The default picture is included as a resource, but if you have any BMP files in your
My Pictures directory, you can select one of those as well.

CMainFrame::OnToolbarDropdown() contains the code that handles the button press event and shows
a popup menu. That function also uses CFindFile to enumerate the contents of the My Pictures directory.
You can check out CKibblesView::OnPaint() to see the code that does the various GDI operations that
draw the UI.

An important note about the toolbar: The toolbar uses a 256-color bitmap, however the VC toolbar editor only
works with 16-color bitmaps. If you ever edit the toolbar using the editor, VC will reduce the bitmap to 16 colors.
What I suggest is keeping a high-color version of the bitmap in a separate directory, making changes to it directly
using a graphics program, then saving a 256-color version in the res directory.

Copyright and License

This article is copyrighted material, (c)2006 by Michael Dunn. I realize this isn't going to stop people from
copying it all around the 'net, but I have to say it anyway. If you are interested in doing a translation of this
article, please email me to let me know. I don't foresee denying anyone permission to do a translation, I would
just like to be aware of the translation so I can post a link to it here.

With the exception of ColorButton.cpp and ColorButton.h, the demo code that accompanies this article
is released to the public domain. I release it this way so that the code can benefit everyone. (I don't make the
article itself public domain because having the article available only on CodeProject helps both my own visibility
and the CodeProject site.) If you use the demo code in your own application, an email letting me know would be
appreciated (just to satisfy my curiosity about whether folks are benefitting from my code) but is not required.
Attribution in your own source code is also appreciated but not required.

The files ColorButton.cpp and ColorButton.h come from Color
Picker for WTL with XP themes by Tim Smith. They are not covered by the above license statement; see the comments
in those files for their license.

Revision History

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Michael lives in sunny Mountain View, California. He started programming with an Apple //e in 4th grade, graduated from UCLA with a math degree in 1994, and immediately landed a job as a QA engineer at Symantec, working on the Norton AntiVirus team. He pretty much taught himself Windows and MFC programming, and in 1999 he designed and coded a new interface for Norton AntiVirus 2000.Mike has been a a developer at Napster and at his own lil' startup, Zabersoft, a development company he co-founded with offices in Los Angeles and Odense, Denmark. Mike is now a senior engineer at VMware.

He also enjoys his hobbies of playing pinball, bike riding, photography, and Domion on Friday nights (current favorite combo: Village + double Pirate Ship). He would get his own snooker table too if they weren't so darn big! He is also sad that he's forgotten the languages he's studied: French, Mandarin Chinese, and Japanese.

Write a C++ class for a COM object that implements IBackgroundCopyCallback. Create an instance of that class and pass it to IBackgroundCopyJob::SetNotifyInterface()Call IBackgroundCopyJob::SetNotifyFlags() to tell BITS which events you want to be notified of

//Add logic that will not block the callback thread. If you need to perform //extensive logic at this time, consider creating a separate thread to perform //the work.

hr = pJob->Complete(); if (FAILED(hr)) { //Handle error. BITS probably was unable to rename one or more of the //temporary files. See the Remarks section of the IBackgroundCopyJob::Complete //method for more details. }

//If you do not return S_OK, BITS continues to call this callback. return S_OK;}

//Use pJob and pError to retrieve information of interest. For example, //if the job is an upload reply, call the IBackgroundCopyError::GetError method //to determine the context in which the job failed. If the context is //BG_JOB_CONTEXT_REMOTE_APPLICATION, the server application that received the //upload file failed. hr = pJob->GetDisplayName(&pszJobName); hr = pError->GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), &pszErrorDescription);

if (pszJobName && pszErrorDescription) { //Do something with the job name and description. }

CoTaskMemFree(pszJobName); CoTaskMemFree(pszErrorDescription);

//If you do not return S_OK, BITS continues to call this callback. return S_OK;}

hr = pJob->GetDisplayName(&pszJobName); if (SUCCEEDED(hr)) { hr = pJob->GetProgress(&Progress); if (SUCCEEDED(hr)) { hr = pJob->GetState(&State); if (SUCCEEDED(hr)) { //Do something with the progress and state information. //BITS generates a high volume of modification //callbacks. Use this callback with discretion. Consider creating a timer and //polling for state and progress information. } } CoTaskMemFree(pszJobName); }

Simon W's translation is the "official" one. Another author did a "better" translation, instead of improving Simon's work, however I personally can't vouch for which one is the better version. Caveat lector.

I tried a few links to drop to the sample app window from Internet Explorer, but have not succeeded in making it work.Most of the time the Job state goes from "Connecting" to "Transient error", while Files downloaded may show "0 of 6" and Bytes downloaded may show "0 of 64667" or something like this. Are there some links on Internet that have been tested and proven to work with this sample application?Do I need anything extra to install to make BITS to work? I have Win XP Pro with SP2.

Overall, good article about WTL GDI. However, I am also interested in BITS. Are there other samples of WTL/ATL code working with BITS API available somewhere?

You can use the bitsadmin.exe app in the Platform SDK to look at the status of your BITS jobs.I haven't really seen a whole lot of writing about BITS, when I started working on Kibbles a while ago, I just stared at the docs until they made sense.

I tried to use a few hyperlinks to drop to the sample window, but have not succeeded in making it work: it goes from Job State: Connecting (files and bytes counts are initialized)to to Job state: Ttansient error. Is there anything else necessary to make BITS work? I have Windows XP Pro SP2. Are there on Internet the hyperlinks that have been tested and proven to work with this sample?

The WTL stuff looks really good, but I am also interested in BITS part. Are there any other good code samples of BITS usage in WTL/ATL environment?

As a games programmer, I rarely delve into the depths of MFC nor ATL, so I'm a little unfamiliar with the terminology but I was wondering if WTL is actually the 'new' name for ATL or are they different? If they're different, then why does all this WTL stuff refer to function etc. with Atl prefixes?Either way, how about some consistency, Microsoft?

WTL is a set of classes that build on ATL, for example the UI classes like CSplitterWindow and the control wrappers use ATL::CWindowImpl.As for why the functions are named with Atl instead of Wtl, I don't know.

WTL is an ATL-stylish wrapping of Win32 API relating to creating and manupulating windows, dialogs, and Windows controls. It has semi-independence, i.e. it is used and distributed as an open source in spite of link to ATL.