TaskDialog and TaskDialogIndirect helper functionality
- John
- Oct 20
- 4 min read
This post is one of a series providing implementation examples of Windows API Functions, Types, Enums and Consts using VBA. The code in this post can be used as-is, however, if you regularly (or even just occasionally) work with Windows API declarations in VBA, you may want to see the posts Automatically add Windows API declaration(s) and Using 'F1' to view Windows API web pages which explain some of the functionality that can be added to the VBE by VBE_Extras.
This is the first of four posts relating to the TaskDialog and TaskDialogIndirect Windows API Functions. This post doesn't provide any directly usable code by itself ... just some helper functionality for use with those two Functions. I'll follow-up this post with code for three Class Modules that are 'wrappers' for TaskDialog and TaskDialogIndirect over a series of subsequent posts:
One for TaskDialog which provides "MsgBox-like" functionality but enhanced with options for both a 'main instruction' heading and 'content' within the body of the dialog and options for many more buttons
One for TaskDialogIndirect showing a 'normal' dialog ... this is like a supercharged version of TaskDialog with custom icons, radio buttons, custom buttons, command links, a verification check box, a footer ... and more
One for TaskDialogIndirect showing a 'progress bar' dialog ... as well as the 'progress bar' itself, this includes the 'main information' heading and 'content' within the body as well as a footer and custom icons
This is an example of a TaskDialog with both a 'main instruction' heading and 'content' and a custom icon ...

The reasons for posting this code first, and separately, are:
This code is required by each of the 3 Class Modules ... having one helper standard Module means the code doesn't have to be duplicated in each of the Class Modules
As some of the Enums are not Private then, even though they are in Class Modules, they are Project-level (ie available across the entire VBA Project) ... VBA does not allow identically named non-Private Enums ... this means that, if each Enum were included in each Class Module, then you could only have 1 of the 3 Class Modules in any VBA Project and, while its unlikely any Project would need all 3, there is a case for 2 to be included (the 'normal' TaskDialogIndirect Class Module includes all of the functionality incorporated in the TaskDialog Class Module ... so it's unlikely you would have them both in the same Project ... the 'progress bar' TaskDialogIndirect Class Module, however, provides very different functionality so it would be logical to have that plus either the TaskDialog or the 'normal' TaskDialogIndirect Class Module)
The majority of the code is not complex ... the exception is the functionality that creates and activates (and subsequently deactivates and releases) an 'activation context' if the host application is currently using Common Controls version 5 (I'm looking at you, 32-bit Excel and PowerPoint ... Access, Word and Outlook as well as 64-bit Excel and PowerPoint are in the clear!) as TaskDialog/Indirect are only available from Common Controls version 6 (see the TaskDialog and/or TaskDialogIndirect docs, scroll down to the Requirements table at the bottom of the page and look for the 'DLL' row).
As such, the 3 Class Modules for TaskDialog/Indirect will check the Common Controls version and, if required, call the TryActivateActivationContext() Function immediately before showing the TaskDialog/Indirect and call the DeactivateAndReleaseActivationContext() Function immediately afterwards. This temporarily loads a Common Controls version 6 manifest from the shell32.dll library. I'm not going to claim that this was my idea ... note the comments in the CreateActivationContext() Function linking to Raymond Chen's How can you use both versions 5 and 6 of the common controls within the same module? post plus the two StackOverflow posts here and here.
Here's a brief summary of the rest of the code (I'll provide more of an explanation in the subsequent posts, where relevant):
Enums required by the TaskDialog/Indirect Class Modules ... most of these Enums are in the Windows API as multiple individual Consts ... I used the Consts to Enum / Enum to Consts command of VBE_Extras to automatically turn them into Enums
Private Windows API Functions, Types and Consts used internally by this Module ... obviously (well, I think it's obvious?!) I used the Automatically add Windows API declaration(s) functionality within VBE_Extras to add these for me with the correct parameters, return types etc
Code to load and release icons for display in the dialogs
Code to get the handle for any host application ... this is the same code in (and explained in) the Get the application window handle in any app (well ... in Excel, Word, Access, PowerPoint or Outlook) post
Code to split a LongLong into two Longs (the high 32 bits and the low 32 bits) ... required in 64-bit hosts only
Code to generate hyperlink text in the format expected by TaskDialogIndirect
Code to 'do a "beep"'
Code to get a String from a pointer to that String
Various ProgressBarXxx() methods that help with updating the 'progress bar' variant of TaskDialogIndirect
Code to get Strings for Enum member values to help with debugging ... these were generated automatically using the Add a "GetEnumAsString()" Function command of VBE_Extras
So, here's the code. Everything is commented to provide some explanation about its purpose (other than the Windows API Function declarations themselves ... to get documentation for those, put the cursor on the name of the Function and press F1 ... assuming you have downloaded VBE_Extras first!). When adding this code to your project, add it as a standard Module named UtilsTaskDialog.



Comments