Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1483

[VB6] TaskDialogIndirect: Complete class implementation of Vista+ Task Dialogs

$
0
0
cTaskDialog 0.3.3
Say goodbye to unsightly, primitive messageboxes forever!



Download Attachment: cTaskDialog 0.3.3.zip

**If you have 0.3 please replace it. Important bugfixes have been made with dll icons and ReleaseButtonHold**


cTaskDialog is the sequel to my previous TaskDialogIndirect project, mTaskDialog. This version adds support for all TaskDialogIndirect features, including the progress bar, timer feedback, updating the text and icons while the dialog is open, and events for all the notifications. It's also much easier to use.

What is TaskDialog?

TaskDialog, introduced in Windows Vista, is a massive upgrade to the MessageBox. While not as simple, it offers a huge array of features... custom icons, custom button text, command link style buttons, expanded info button, a footer, a checkbox for 'i read this' or 'don't show this again' type messages, radio buttons, hyperlinks, and more.

This project can be used to create a simple messagebox like the older ones, to an extremely complex dialog with all the features mentioned, even all at once!

Before using cTaskDialog

The TaskDialog was introduced with version 6.0 of the common controls, with Windows Vista. That means a manifest is required for your compiled application, and for VB6.exe in order to use it from the IDE. In addition, your project must start from Sub Main() and initialize the common controls before any forms are loaded. The sample project includes Sub Main(), and see LaVolpe's Manifest Creator to create the manifests.

Setting Up cTaskDialog

Your project must include cTaskDialog.cls and mTaskDialogHelper.bas. mTaskDialogSample.bas is only required for the sample project, though if you want to use hyperlinks make sure you keep the ShellExecuteW api and do not use regular ShellExecute common API as it usually points to ShellExecuteA.
Once you've got a project using the modern common controls, cTaskDialog is similar in use to a lot of other class modules, like the other common controls.

To initialize the class, put the following at the start of a form and in the Form_Load code:
Code:

Private WithEvents TaskDialog1 As cTaskDialog

Private Sub Form_Load()
Set TaskDialog1 = New cTaskDialog
End Sub



Now, you're all ready to begin using it. Let's start with a simple messagebox like we've seen before.

Creating this box is very straightforward. Unlike the previous incarnation, you don't have to worry about anything you're not using.

Code:

Private Sub Command2_Click()

With TaskDialog1
    .MainInstruction = "This is a simple dialog."
    .CommonButtons = TDCBF_YES_BUTTON Or TDCBF_NO_BUTTON
    .IconMain = TD_INFORMATION_ICON
    .Title = "cTaskDialog Project"
   
    .ShowDialog

    If .ResultMain = TD_YES Then
        Label1.Caption = "Yes Yes Yes!"
    ElseIf .ResultMain = TD_NO Then
        Label1.Caption = "Nope. No. Non. Nein."
    Else
        Label1.Caption = "Cancelled."
    End If
End With
End Sub

That's all it takes for a basic messagebox. The .Init() call resets the dialog. If you want to re-use all the previous settings and just change a couple things, it can be skipped.
If you put your text in .Content and nothing in .MainInstruction, it will look like the dialog on the bottom.


Now that basic usage is covered, let's get down to what you really came for: advanced features!

Here's a few basic changes that make a much more fancy looking dialog:

Code:

    .Init
    .MainInstruction = "You're about to do something stupid."
    .Content = "Are you absolutely sure you want to continue with this really bad idea?"
    .CommonButtons = TDCBF_YES_BUTTON Or TDCBF_NO_BUTTON
    .IconMain = TD_SHIELD_WARNING_ICON 'TD_INFORMATION_ICON
    .Title = "cTaskDialog Project"
   
    .ShowDialog

The TaskDialog supports several special shield icons that create the colored bar uptop. If you use a regular icon, or a custom icon, it will look like the dialog on the bottom.



All the other text fields are added the same way, so I'm just going to skip over those. One thing to note, with expanded information set, the little expando button appears automatically when you set those fields and requires no additional code to operate; where it appears is set by a flag, which is described later. Also note that the major text fields can be changed while the dialog is open, just set it again the same way.

One of the big features is the ability to customize the text on the buttons. Due to limitations in VB, I've implemented them by using a .AddButton function. You can assign the button the same id as one of the regular buttons, or give it a unique id. Custom buttons can be removed with .ClearCustomButtons so a full Init() call isn't needed.

Code:

With TaskDialog1
    .Init
    .MainInstruction = "You're about to do something stupid."
    .Content = "Are you absolutely sure you want to continue with this really bad idea?"
    .IconMain = TD_INFORMATION_ICON
    .Title = "cTaskDialog Project"
    .AddCustomButton 101, "YeeHaw!"
    .AddCustomButton 102, "NEVER!!!"
    .AddCustomButton 103, "I dunno?"
   
    .ShowDialog

    Label1.Caption = "ID of button clicked: " & .ResultMain
End With

Note that we have removed the .CommonButtons. If you specify buttons there as well, they will appear in addition to your custom buttons.

Radio buttons are added the exact same way as common buttons; and the ID of the radio button selected is found in the .ResultRad property.

Code:

    .AddRadioButton 110, "Let's do item 1"
    .AddRadioButton 111, "Or maybe 2"
    .AddRadioButton 112, "super secret option"
   
    .ShowDialog

    Label1.Caption = "ID of button clicked: " & .ResultMain
    Label2.Caption = "ID of radio button selected: " & .ResultRad


One of the other biggies are Hyperlinks. These require a few additional steps. First, you need to include TDF_ENABLE_HYPERLINKS in the .Flags property. Then, you add in the hyperlink as normal html, but the url needs to be in quotes. Then you'll need to use one of the events for the class. The most common thing to do is just execute the link, so that's what's shown here, but you could also get the URL back from the pointer and do something else with it. You must use ShellExecuteW, not ShellExecuteA (which is normally what just plain ShellExecute points to). The declare is included in the sample project.

Code:

With TaskDialog1
    .Init
    .MainInstruction = "Let's see some hyperlinking!"
    .Content = "Where else to link to but <a href=""http://www.microsoft.com"">Microsoft.com</a>"
    .IconMain = TD_INFORMATION_ICON
    .Title = "cTaskDialog Project"
    .CommonButtons = TDCBF_CLOSE_BUTTON
    .Flags = TDF_ENABLE_HYPERLINKS
   
    .ShowDialog

    Label1.Caption = "ID of button clicked: " & .ResultMain
    Label2.Caption = "ID of radio button selected: " & .ResultRad
   
End With

Private Sub TaskDialog1_HyperlinkClick(ByVal lPtr As Long)

Call ShellExecuteW(0, 0, lPtr, 0, 0, SW_SHOWNORMAL)

End Sub


Let's talk about custom icons. You can have a custom icon for both the main icon and the footer icon.
Thanks to the brilliant idea of Schmidt over here, the option to specify an icon id from either shell32.dll or imageres.dll, the two main Windows icon libraries, has been added. This massively expands the icons you can show without having to provider an hIcon.
TDF_USE_SHELL32_ICONID, TDF_USE_IMAGERES_ICONID
Simply specify if you're going to use one of those sources by adding the above to the flags, and set the icon to the index you want. Only one can be used, so both header and footer index will come from the chosen DLL. Standard icons (the TDICONS group) work regardless of the source of other icons. NOTE: These do not run from 0-# of icons, so if your icon browser is telling you that, you need to use a different one, otherwise the dialog may display the wrong icon, or not show at all if the id doesn't exist.

Code:

With TaskDialog1
    .Init
    .MainInstruction = "Show me the icons!"
    .Content = "Yeah, that's the stuff."
    .Footer = "Got some footer icon action here too."
    .Flags = TDF_USE_SHELL32_ICONID
    .IconMain = 18
    .IconFooter = 35
    .Title = "cTaskDialog Project"
    .CommonButtons = TDCBF_CLOSE_BUTTON
   
    .ShowDialog
End With


You can also specify a truly custom icon from a .ico file on disk, in your resource file, or anywhere you can get an hIcon from.
The sample project uses a method I adapted from Leandro Ascierto's cMenuImage. It gets around VB's limitations on icons by adding them to the resource file as a custom resource, and not an icon. This way, you can include any size and any color depth and any number of them inside the .ico. Then, the ResIcontoHICON function will give you the hIcon you need for cTaskDialog. But remember, any other function returning an hIcon will work. Icons can also be updated while the dialog is open by another .IconMain= or .IconFooter= statement. You can use a standard icon for main and custom for footer, and vice versa, or both. When you're going to use a custom icon, you must include TDF_USE_HICON_MAIN/TDF_USE_HICON_FOOTER in the flags. If you create an hIcon, don't forget to destroy it when you're done.
The icon size can't really be changed much; the main icon will be distorted but not larger if you give it a larger size, although you can make it a smaller size. The footer icon won't change at all.

Code:

Dim hIconM As Long, hIconF As Long
hIconM = ResIconTohIcon("ICO_CLOCK", 32, 32)
hIconF = ResIconTohIcon("ICO_HEART", 16, 16)
With TaskDialog1
    .Init
    .MainInstruction = "What time is it?"
    .Content = "Is is party time yet???"
    .Footer = "Don't you love TaskDialogIndirect?"
    .Flags = TDF_USE_HICON_MAIN Or TDF_USE_HICON_FOOTER
    .IconMain = hIconM
    .IconFooter = hIconF
    .Title = "cTaskDialog Project"
    .CommonButtons = TDCBF_CLOSE_BUTTON
   
    .ShowDialog

    Label1.Caption = "ID of button clicked: " & .ResultMain
End With
Call DestroyIcon(hIconM)
Call DestroyIcon(hIconF)

Due to the severe limitations on what icons can be put in a VB project res file in the actual icon group, I strongly recommend a different method. But if you want to try anyway I believe you can just set pszIcon.. to its ID, and not set any of the icon flags.

The last basic feature is the verification checkbox. Here's an example with that, and all the other text fields. Note also what happens in this example when no buttons are specified anywhere: the OK button appears by default.

Code:

With TaskDialog1
    .Init
    .MainInstruction = "Let's see all the basic fields."
    .Content = "We can really fit in a lot of organized information now."
    .Title = "cTaskDialog Project"
    .Footer = "Have some footer text."
    .CollapsedControlText = "Click here for some more info."
    .ExpandedControlText = "Click again to hide that extra info."
    .ExpandedInfo = "Here's a whole bunch more information you probably don't need."
    .VerifyText = "Never ever show me this dialog again!"
   
    .IconMain = TD_INFORMATION_ICON
    .IconFooter = TD_ERROR_ICON
   
    .ShowDialog
   
    Label1.Caption = "ID of button clicked: " & .ResultMain
End With


One of the major stylistic differences are the CommandLink buttons. When using the Command Link style, the first line is considered the main text, and lines are made into sub-text. Note that the line is broken with vbLf only; not vbCrLf. vbCrLf results in the text not being smaller on Win7 x64, I haven't tested other systems but it should be the same.
With the custom button sample from above, these changes are made:

Code:

    .Flags = TDF_USE_COMMAND_LINKS
    .AddCustomButton 101, "YeeHaw!" & vbLf & "Put some additional information about the command here."




That covers all the basic functionality.
Download Attachment: cTaskDialog 0.3.3.zip
Attached Files

Viewing all articles
Browse latest Browse all 1483

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>