Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

See how Windows Forms applications can be adapted to use the new .NET Add-in framework (System.AddIn) this month.

Mueez Siddiqui

MSDN Magazine July 2008

...

Read more!

Learn how you can set up every mobile device in your company with a few lines of code and some XML--thanks to the provisioning APIs in the Windows Mobile SDK.

Mike Calligaro

MSDN Magazine April 2008

...

Read more!

Our security experts present 10 vulnerable pieces of code. Your mission is to find the holes (a.k.a. bad security practices) in the code.

Michael Howard and Bryan Sullivan

MSDN Magazine November 2008

...

Read more!

This month's column explains how to use Windows HTTP Services, or WinHTTP, the new, powerful API for implementing HTTP clients.

Kenny Kerr

MSDN Magazine August 2008

...

Read more!

This month we explain how pseudo variables and format specifiers provide a wealth of information for use in debugging.

Kenny Kerr

MSDN Magazine December 2008

...

Read more!

Also by this Author

This month's column explains how to use Windows HTTP Services, or WinHTTP, the new, powerful API for implementing HTTP clients.

Kenny Kerr

MSDN Magazine August 2008

...

Read more!

With the release of Windows Vista, C++ developers will be happy to know there's plenty of magic left to perform. This new column will provide the necessary insight.

Kenny Kerr

MSDN Magazine August 2007

...

Read more!

Windows Imaging Component (WIC) is an extensible framework for encoding, decoding, and manipulating images. See how to use WIC to encode and decode different image formats.

Kenny Kerr

MSDN Magazine April 2008

...

Read more!

Cryptography Next Generation (CNG) is meant to be a long-term replacement for the CryptoAPI, providing replacements for all of the cryptographic primitives it offered.

Kenny Kerr

MSDN Magazine July 2007

...

Read more!

This month we explain how pseudo variables and format specifiers provide a wealth of information for use in debugging.

Kenny Kerr

MSDN Magazine December 2008

...

Read more!

Popular Articles

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

Ray Djajadinata

MSDN Magazine May 2007

...

Read more!

James Avery does it again with his popular list of developer tools. This time he covers the best Visual Studio add-ins available today that you can download for free.

James Avery

MSDN Magazine December 2005

...

Read more!

One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

Dan Griffin

MSDN Magazine May 2008

...

Read more!

Learn how to automate custom SharePoint application deployments, use the SharePoint API, and avoid the hassle of custom site definitions.

E. Wilansky, P. Olszewski, and R. Sneddon

MSDN Magazine May 2008

...

Read more!

Our Blog

Choosing the best alternative is a common task in software development and testing. A group of beta users may need to choose the best user interface from a set of prototypes. Or imagine the members of an open source project voting for a policy.

In the November 2008 issue of MSDN Magazine, Dr. James McCaffrey describes five of the ...

Read more!

Every month, the CLR team gives us insight into the core of managed code, .NET programming best practices, technologies underlying the CLR and .NET Framework, and other tips and suggestions.

In the December 2008 issue of MSDN Magazine, Erika Fuentes and Eric Eilebrecht cover some common issues developers encounter when tuning ...

Read more!

With the releases of LINQ to SQL and the ADO.NET Entity Framework, developers now have two products from Microsoft designed to tie together relational data and object-oriented programming.

In the December 2008 issue of MSDN Magazine, Anthony Sneed provides a roadmap to these technologies and demonstrates how you can create ...

Read more!

Because Windows Workflow Foundation (WF) is based on a runtime that manages the execution of workflows and activities, testing must, in almost all cases, involve the use of the runtime – and this can introduce some interesting challenges.

In the November 2008 issue of MSDN Magazine, Matt Milner presents some techniques for unit testing ...

Read more!

Windows Presentation Foundation (WPF) adds functionality to the Microsoft .NET Framework so that you actually can reliably keep bound controls synchronized with their data sources.

In the December 2008 issue of MSDN Magazine, Ken Getz demonstrates how to use the ObservableCollection class provided by WPF to keep bound controls in ...

Read more!

Windows with C++
Windows Template Library 8.0
Kenny Kerr

Code download available at: WindowsWithC++2007_12.exe (175 KB)
Browse the Code Online
The developers responsible for the Windows® Template Library (WTL) recently released a new version of this excellent library that fully supports virtually all of the new user interface features and enhancements introduced with Windows Vista®. This month I'll be highlighting some of the new features in this latest release. In case you are not familiar with WTL and how it fits into the Visual C++® development landscape, I will start with a brief introduction.
The Visual C++ team developed the Active Template Library (ATL) to allow COM clients and servers to be easily created while producing the smallest and fastest code possible. Unlike MFC, which is focused on developing user interface applications and which only later added support for COM, ATL was designed from the start to enable COM development and it does this well. It supported only rudimentary user interface development but the classes it provided were incredibly useful as lightweight building blocks and base classes for a more sophisticated user interface library.
WTL extends ATL with a very rich set of class templates for building applications as simple or as complex as you can imagine. WTL is not included with Visual C++ but is made available both on the SourceForge Web site at sourceforge.net/projects/wtl and through the Microsoft Download Center.
WTL 8.0 was primarily developed with a focus on Windows Vista UI support so I will cover some topics that I've covered in previous columns and articles. But the focus this month is on how the new WTL improvements will accelerate adoption of these new features and ensure that you have even less code you need to write yourself! The download for this column, available from the MSDN® Magazine Web site, provides examples of most of the features described here.

Task Dialogs
Task dialogs are one of my favorite new features in Windows Vista, providing a powerful API for developing both simple and sophisticated dialogs with very little effort.
The TaskDialogIndirect function and the TASKDIALOGCONFIG structure can be quite daunting and well-deserving of some help from C++ to simplify its use. WTL provides support for task dialogs via the CTaskDialogImpl base class template. Internally the CTaskDialogImpl class uses the CTaskDialogConfig class to wrap the TASKDIALOGCONFIG structure. This is exposed through the public m_tdc variable should you need to access it directly, but you're unlikely to need it as the CTaskDialogImpl class does an excellent job of providing suitable member functions that wrap it up for you. The CTaskDialog concrete class that derives from CTaskDialogImpl is also provided for very simple scenarios, but it is usually best simply to derive a class from CTaskDialogImpl to implement your task dialog.
Figure 1 illustrates a number of task dialog features and how you can make use of them from WTL. The example sets the window title, main instruction and content text captions. Task dialogs support a number of additional text captions, though they require different mechanisms to set them depending on whether the task dialog has been constructed or not. Unfortunately, the CTaskDialogImpl class does not abstract these differences and this can make updating these text captions a bit confusing. Figure 2 summarizes how to set the various text captions using the CTaskDialogImpl class depending on whether it is set before or after the task dialog is constructed. Typically you use the pre-construction method in your task dialog's constructor and the post-construction method in various event handlers to update the captions.

Text Caption Pre-Construction Post-Construction
Window title SetWindowTitle() ::SetWindowText()
Main instruction SetMainInstructionText() SetElementText(TDE_MAIN_INSTRUCTION, ...
Content SetContentText() SetElementText(TDE_CONTENT, ...
Footer SetFooterText() SetElementText(TDE_FOOTER, ...
Expanded information SetExpandedInformationText() SetElementText(TDE_EXPANDED_INFORMATION, ...
Expanded control text SetExpandedControlText() N/A
Collapsed control text SetCollapsedControlText() N/A
Verification SetVerificationText() N/A
enum
{
    Button_Save = 101,
    Button_DontSave,
};

class SampleDialog : public CTaskDialogImpl<SampleDialog>
{
public:

    SampleDialog()
    {
        SetWindowTitle(L"Title");
        SetMainInstructionText(L"Main instruction");
        SetContentText(L"Content");

        ModifyFlags(0, TDF_ALLOW_DIALOG_CANCELLATION |
                       TDF_USE_COMMAND_LINKS);

        static TASKDIALOG_BUTTON buttons[] =
        {
            { Button_Save, L"&Save", },
            { Button_DontSave, L"Do&n't save", },
        };

        SetButtons(buttons,
                   _countof(buttons));
    }
};

Figure 1 Task Dialog Example 
The code in Figure 1 also makes use of the ModifyFlags method. Various flags are documented in the Windows SDK for customizing the task dialog's appearance. The ModifyFlags method's first parameter indicates the flags to remove and the second parameter indicates the flags to add. The SetButtons method is also used to specify the buttons that will be displayed on the task dialog. The example declares the array of TASKDIALOG_BUTTON structures static to ensure that its storage lives beyond the constructor. This is critical since the button definitions are referenced later on when the DoModal method is called that finally passes all of the information to the TaskDialogIndirect function to actually display the task dialog.
Calling the DoModal method is straightforward and can optionally provide the identifier of the button the user selected. Figure 3 shows an example of how you might display the task dialog from Figure 1 and handle the various button identifiers.
SampleDialog dialog;
int selectedButtonId = 0;

COM_VERIFY(dialog.DoModal(
    0,                   // parent window
    &selectedButtonId));

switch (selectedButtonId)
{
    case Button_Save:
    {
        // TODO: save
        break;
    }
    case Button_DontSave:
    {
        // TODO: don't save
        break;
    }
    case IDCANCEL:
    {
        // TODO: cancel
        break;
    }
    default:
    {
        ASSERT(false);
    }
}

Alternatively, you can use the task dialog's callback facility that the CTaskDialogImpl class exposes through a set of public methods that you can optionally implement in your derived class to handle different events. For example, in order to handle button clicks within your dialog class, you can add the public method shown in Figure 4.
class SampleDialog : public CTaskDialogImpl<SampleDialog>
{
public:

...

    bool OnButtonClicked(int buttonId)
    {
        bool closeDialog = false;

        switch (buttonId)
        {
            // Do something here
        }

        return !closeDialog;
    }
};

Handling this event is especially useful when you want to handle a particular button click but don't necessarily want the task dialog to close. There are also quite a few other events that can be handled in a similar way. Figure 5 shows a list of overrides that the CTaskDialogImpl class provides. Remember that these are ATL-style overrides that are evaluated at compile-time, so they do not require virtual function calls.

Method Description
void OnDialogConstructed() Task dialog created but not yet visible. Window handle is valid.
bool OnButtonClicked(int buttonId) Button or command link clicked. Return true to prevent dialog from closing.
void OnRadioButtonClicked(int buttonId) Radio buttons clicked.
void OnHyperlinkClicked(PCWSTR url) Hyperlink clicked.
void OnExpandoButtonClicked(bool expanded) Expando button clicked.
void OnVerificationClicked(bool checked) Verification checkbox was checked or cleared.
void OnHelp() F1 key pressed.
bool OnTimer(DWORD milliseconds) Sent every 200 milliseconds. Parameter indicates milliseconds since timer started or reset.
void OnNavigated() Navigation has occurred.
void OnDestroyed() Task dialog destroyed. Window handle no longer valid.
Task dialogs provide many more features. The sample code for this column provides a comprehensive set of examples illustrating virtually all of the task dialog's capabilities with the help of WTL. For a detailed look at the extensive capabilities of the task dialog API, read my blog posting "Windows Vista for Developers–Part 2–Task Dialogs in Depth" (weblogs.asp.net/kennykerr/archive/2006/07/18/Windows-Vista-for-Developers-_1320_-Part-2-_1320_-Task-Dialogs-in-Depth.aspx).

Aero Wizards
Windows Vista introduces a new, modern look for the common wizard. As with the older wizard standard, AeroTM wizards are just a variation on the property sheet API. This makes it quite simple to update your applications to take advantage of the new user interface. WTL makes it even easier by providing a set of class templates that wrap all of the new functionality for you.
Simply derive your wizard window class from the CAeroWizardFrameImpl class template and it will take care of applying the appropriate flags to instruct Windows to use the new Aero user interface. CAeroWizardFrameImpl derives from CPropertySheetImpl, which provides all of the common functionality. The wizard pages simply derive from the CAeroWizardPageImpl class, which provides methods to control the new Aero wizard buttons. Figure 6 provides a simple yet complete example of an Aero wizard with a single page.
class SamplePage : 
    public CAeroWizardPageImpl<SamplePage>
{
public:

    BEGIN_MSG_MAP(SamplePage)
        MESSAGE_HANDLER_EX(WM_INITDIALOG, OnInitDialog)
        CHAIN_MSG_MAP(__super)
    END_MSG_MAP()

    enum { IDD = IDD_SAMPLE_PAGE };

    SamplePage()
    {
        VERIFY(m_title.LoadString(IDS_PAGE_TITLE));
        SetHeaderTitle(m_title);
    }

private:

    LRESULT OnInitDialog(UINT /*message*/, 
                         WPARAM /*wParam*/, 
                         LPARAM /*lParam*/)
    {
        ShowWizardButtons(
            PSWIZB_BACK | PSWIZB_NEXT | PSWIZB_FINISH | PSWIZB_CANCEL,
            PSWIZB_BACK | PSWIZB_NEXT | PSWIZB_CANCEL);

        EnableWizardButtons(PSWIZB_BACK,
                            0);

        SetButtonText(PSWIZB_NEXT,
                      L"&Run");

        return TRUE;
    }

    CString m_title;
};

class SampleWizard : 
    public CAeroWizardFrameImpl<SampleWizard>
{
public:

    BEGIN_MSG_MAP(SampleWizard)
        CHAIN_MSG_MAP(__super)
    END_MSG_MAP()

    SampleWizard() :
        CAeroWizardFrameImpl<SampleWizard>(IDS_WIZARD_TITLE)
    {
        VERIFY(AddPage(m_page));
    }

private:

    SamplePage m_page;
};

Figure 6 Simple Aero Wizard 
As you can see, there isn't much new to talk about and moving to Aero wizards is pretty painless. The main task will be to manage the standard buttons that adorn an Aero wizard. The example demonstrates the ShowWizardButtons, EnableWizardButtons, and SetButtonText methods. ShowWizardButtons shows or hides one or more buttons. The first parameter indicates the buttons to operate on and the second parameter indicates which of those buttons to show. Similarly, the first parameter of EnableWizardButtons indicates the buttons to operate on and the second parameter indicates which of those buttons to enable. The rest will be disabled. Finally, SetButtonText updates the text captions for the Next, Finish, and Cancel buttons.

New File Dialogs
The new file dialogs provided by Windows Vista present a fresh appearance consistent with the new Windows Explorer user interface and are a welcome replacement for the aging GetOpenFileName and GetSaveFileName functions that have been in use for years. The new file dialogs are exposed through a set of COM interfaces so they are not particularly hard to use directly. However, it can get tedious to write the same boilerplate COM code every time you need to pop up a file dialog, especially if you need to respond to the various file dialog events that require you to provide COM interface implementations. Fortunately, WTL does a good job of wrapping it all up in an easy-to-use set of classes. Figure 7 provides an example of a file open dialog implementation.
class SampleOpenDialog : 
    public CShellFileOpenDialogImpl<SampleOpenDialog>
{
public:

    SampleOpenDialog()
    {
        COMDLG_FILTERSPEC fileTypes[] = 
        {
            { L"Text Documents", L"*.txt" },
            { L"All Files", L"*.*" }
        };

        COM_VERIFY(GetPtr()->SetFileTypes(_countof(fileTypes),
                                          fileTypes));
    }
};

Figure 7 File Open Dialog (Click the image for a larger view)
The COMDLG_FILTERSPEC structure provides a much more manageable format for specifying the file types compared to the multi-string approach used by GetOpenFileName. An array of these structures is then passed to the SetFileTypes method to specify the file types the dialog will provide filtering for. The GetPtr method returns the dialog's IFileOpenDialog interface pointer used to customize the dialog appearance and behavior.
The new file dialogs also let you respond to a variety of events. However, you need to implement the IFileDialogEvents interface to receive these events. Fortunately, WTL implements this for you via the CShellFileDialogImpl base class template so you only need to provide the handlers for the events you are interested in.
Figure 8 presents a list of overrides that the CShellFileDialogImpl class provides. You might, for example, want to validate that the selected file is acceptable before closing the file open dialog. This is easily achieved by the OnFileOk event called just before the dialog is about to return the result, by preventing the dialog from closing should you decide that the selected file is not acceptable. The example in Figure 9 illustrates this technique.
class SampleOpenDialog : 
    public CShellFileOpenDialogImpl<SampleOpenDialog>
{
public:

    // ...

    HRESULT OnFileOk()
    {
        CString filePath;
        COM_VERIFY(GetFilePath(filePath));

        // Validate file here...
        bool acceptable = ...

        return acceptable ? S_OK : S_FALSE;
    }
};


Method Description
HRESULT OnFileOk() User made a selection.
HRESULT OnFolderChanging(IShellItem*) Enables preventing folder navigations.
HRESULT OnFolderChange() Called after OnFolderChanging indicating user navigated to new folder.
HRESULT OnSelectionChange() User changes selection in dialog's view.
HRESULT OnShareViolation(IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) Enables handling of sharing violations.
HRESULT OnOverwrite(IShellItem*, FDE_OVERWRITE_RESPONSE*) User chose to overwrite a file.
Finally, the file open dialog can be used as follows:
SampleOpenDialog dialog;

if (IDOK == dialog.DoModal())
{
    CString filePath;
    COM_VERIFY(dialog.GetFilePath(filePath));

    // Use file here...
}
The new file dialogs provide many more features through the various COM interfaces. For a detailed look at the capabilities offered by the new file dialogs API, read my blog post "Windows Vista for Developers–Part 6–The New File Dialogs" (weblogs.asp.net/kennykerr/archive/2006/11/10/Windows-Vista-for-Developers-_1320_-Part-6-_1320_-The-New-File-Dialogs.aspx).

Other WTL Features to Explore
In a previous Windows with C++ column, I introduced many of the control enhancements in Windows Vista (msdn.microsoft.com/msdnmag/issues/07/08/WindowsCPP). WTL now wraps most all of the new features with updated classes and macros for handling the new messages and notifications. There is even more to love about the latest version of WTL, from improvements to the resizable dialog support, a new tab view class as well as many other helpful additions and improvements. Take a few minutes to explore the WTL headers. If you're new to WTL you will be pleasantly surprised at the powerful classes and minimalist design of this excellent C++ library for Windows.

Send your questions and comments for Kenny to mmwincpp@microsoft.com.


Kenny Kerr is a software craftsman specializing in software development for Windows. He has a passion for writing and teaching developers about programming and software design. Reach Kenny at weblogs.asp.net/kennykerr.

Page view tracker