It is not a widely know feature of the Task Dialog, perhaps because Microsoft
didn't bother to initially document the TDM_NAVIGATE_PAGE
message that invokes this function.
In multi-page mode you can replace the existing page shown in the Task Dialog
on the fly. This allows you to instantly provide a new page if the user presses
a button or some other event happens on the page shown.
The Task Dialog offers several improvements to the old MessageBox API, including
custom buttontext, hyperlinks, expanding footer areas and a callback programming style.
Still, because the Task Dialog internally uses Microsoft's DirectUser layout library you
are limited to exactly the functionality defined in the Task Dialog, since
traditional window subclassing is likely not to work properly.
There are however a number of simple tasks that would span several dialogs that can be
implemented much faster by using the functionality already available in the Task Dialog
APIs. I have found that scenarios where the user is prompted to start one of several
long-running work processes are good candidates to be used with a multi-paged
Task Dialog: First the user is prompted to choose the work to be done, then it immediately
continues to the progress page and eventually ends with the presentation of a completion
page.
Using the control
This is a wrapper for the TaskDialog API, allowing you to easily set up several pages and to navigate between these pages. To use this control, you'll need to create aCTaskDialogWizard
instance and add pages to it. Each page must derive from the
C++ template CTaskDialogWizardPageImpl
which
is a basic wrapper for the native WTL class CTaskDialogImpl
.
The CTaskDialogImpl
class is managing the TaskDialog notifications
and eases the creation of dialog configurations as we'll see later.
CMyPage1 dlgPage1;
CMyPage2 dlgPage2;
CTaskDialogWizard dlgWizard;
dlgWizard.SetTitle(L"Burn CD Wizard");
dlgWizard.AddPage(&dlgPage1);
dlgWizard.AddPage(&dlgPage2);
// Show dialogs...
dlgWizard.DoModal();
This sets up a wizard with two pages. You can apply a few settings on the wizard
level that trickle down to the pages. This is great for setting a common window
title for instance.
Each Wizard page ends up deriving from the WTL CTaskDialogImpl
class
that offers many wrapper functions for manipulating the TASKDIALOGCONFIG
structure and for processing the Task Dialog callback notifications from a C++ class.
Here is an example:
class CMyPage1 : public CTaskDialogWizardPageImpl<CMyPage1>
{
public:
enum { IDD = IDD_PAGE1 };
CMyPage1()
{
// Set page texts and stuff...
SetMainIcon(TD_INFORMATION_ICON);
SetMainInstructionText(L"Begin Work");
SetContentText(L"This is the description text.");
SetCommonButtons(TDCBF_OK_BUTTON | TDCBF_CLOSE_BUTTON);
ModifyFlags(0, TDF_ENABLE_HYPERLINKS);
SetFooterIcon(IDR_MAINFRAME);
SetFooterText(L"Visit <a>www.viksoe.dk</a>");
}
void OnHyperlinkClicked(LPCWSTR pszHREF)
{
::ShellExecute(m_hWnd, L"open", L"http://www.viksoe.dk/code/",
NULL, NULL, SW_SHOW);
}
};
This is a standard Task Dialog implementation as you would do it with the
CTaskDialogImpl
WTL class. The only new thing is the IDD
constant that identifies the page for navigation.
Once you have added several pages to the wizard, you'll want to navigate between the pages. This is done by handing one of the events triggered in the Task Dialog (such as a button click) and then decide which page to navigate to.
BOOL OnButtonClicked(int nButton)
{
if( nButton == TDCBF_OK_BUTTON ) return NavigatePage(IDD_PAGE2);
return FALSE; // Otherwise close dialog
}
The new NavigatePage()
override takes the IDD
constant
of a page previously added to the wizard.
Source Code Dependencies
Microsoft WTL 8.5 LibraryDownload Files
![]() | Source Code and Sample (30 Kb) |