TaskDialog

Windows specific questions.
Post Reply
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

TaskDialog

Post by deltarho[1859] »

Been raining a lot lately here in Blighty so I have been at the keyboard keeping dry. I have also been using TaskDialog a fair amount instead of ye olde messagebox.

If you haven't used TaskDialog it is in "commctrl.bi".

Here is a snippet - TaskDialog.bas

Code: Select all

#define UNICODE
#define _WIN32_WINNT &h0602
#include once "windows.bi"
#include once "win\commctrl.bi"
 
Dim pnButton as Long
 
TaskDialog( Null, Null, "MyApp", "Posh main message", "Secondary message", TDCBF_OK_BUTTON or TDCBF_YES_BUTTON or TDCBF_NO_BUTTON _
 or TDCBF_RETRY_BUTTON or TDCBF_CANCEL_BUTTON or TDCBF_CLOSE_BUTTON, TD_WARNING_ICON, @pnButton )
 
Select Case pnButton
  Case IDOK
    TaskDialog( Null, Null, "MyApp", "You clicked on OK button", "", Null, TD_INFORMATION_ICON, @pnButton )
  case IDYES
    TaskDialog( Null, Null, "MyApp", "You clicked on Yes button", "", Null, TD_INFORMATION_ICON, @pnButton )
  case IDNO
    TaskDialog( Null, Null, "MyApp", "You clicked on No button", "", Null, TD_INFORMATION_ICON, @pnButton )
  CASE IDRETRY
    TaskDialog( Null, Null, "MyApp", "You clicked on Retry button", "", Null, TD_INFORMATION_ICON, @pnButton )
  case IDCANCEL
    TaskDialog( Null, Null, "MyApp", "You clicked on Cancel button", "", Null, TD_INFORMATION_ICON, @pnButton )
  case IDCLOSE
    TaskDialog( Null, Null, "MyApp", "You clicked on Close button", "", Null, TD_INFORMATION_ICON, @pnButton )
End Select
Six buttons to choose from is a bit much but it shows how much more we can do compared with a messagebox.

Notice with the second message that there is no secondary message; it is not a requirement - we just use an empty string.

Now, if you want to be outrageous, which I do from the moment that I wake up, we can use own icon instead of a built in icon. However, we now need to use a resource file and a manifest. No big deal.

Save this snippet - TaskDialog2.bas

Code: Select all

#define UNICODE
#define _WIN32_WINNT &h0602
#include once "windows.bi"
#include once "win\commctrl.bi"
 
Dim as hInstance hInstance = GetModuleHandle(NULL)
 
LoadImage(hInstance, MAKEINTRESOURCE(100), IMAGE_ICON, 0, 0, LR_SHARED)
 
Dim pnButton as Long
 
TaskDialog( Null, hInstance, "MyApp", "Gimmee a break.", "Do you seriously expect me to do that!", TDCBF_YES_BUTTON, "#100", @pnButton )
 
TaskDialog( Null, hInstance, "MyApp", "OK", "..  but I really have better things to do, I really do.", Null, TD_INFORMATION_ICON, @pnButton )

and put the following two next to it.
TD.rc

Code: Select all

#define IDR_VERSION 1
 
100 icon what.ico
 
1 24 "Theme.xml" 
Theme.xml

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
 
    <assemblyIdentity
        version="1.0.0.1"
        processorArchitecture="*"
        name="MyAppName.exe"
        type="win32"
    />
    <description>Optional MyDescription for MyAppName.exe</description>
 
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
        <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
 
    <!-- Compatibility section for Program Compatibility Assistant (PCA) -->
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows 10 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        </application>
    </compatibility>
 
    <!-- Trustinfo section for User Account Control (UAC) -->
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges>
                <!-- level   = "asInvoker"            -->
                <!-- level   = "highestAvailable"     -->
                <!-- level   = "requireAdministrator" -->
                <requestedExecutionLevel
                    level    = "asInvoker"
                    uiAccess = "false"
                />
            </requestedPrivileges>
        </security>
    </trustInfo>
 
    <!-- Dependency section -->
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0"
                processorArchitecture="*"
                publicKeyToken="6595b64144ccf1df"
                language="*"
            />
        </dependentAssembly>
    </dependency>
 
</assembly>

You will also need an icon. Try this one: What.zip and put with above.

Compile with: -gen gcc -Wc -O3 TD.rc

If that does not bring a smile to your face then I give up. <smile>
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

We don't need #define UNICODE.

We also need a manifest for the first snippet. I must have had TD.rc in the command line. In that case we only need
TD.rc

Code: Select all

1 24 "Theme.xml"
With the second snippet we only need
TD.rc

Code: Select all

100 icon what.ico
1 24 "Theme.xml"
It looks like we only need '#define IDR_VERSION 1' when building a Property Sheet.

I have a habit of removing stuff to see at what point they break. Very often it is the only way I learn how to do things as some subjects don't seem to be detailed anywhere.
nimdays
Posts: 236
Joined: May 29, 2014 22:01
Location: West Java, Indonesia

Re: TaskDialog

Post by nimdays »

deltarho[1859] wrote: If that does not bring a smile to your face then I give up. <smile>
Entry point not found. Mine is xp32
The procedure entry point TaskDialog could not be loaded ... COMCTL32.DLL
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

Apologies, nimdays. I read TaskDialog at MSDN but did not check out the very bottom: 'Requirements', which read.

Minimum supported client | Windows Vista [desktop apps only]

I thought it had been around longer than that. Extended support for Windows XP ended on April 8, 2014 and I stopped writing code with XP in mind at the same time. I find it amazing that XP has a market share of just over 3%. Last November Windows 10 overtook Windows 7 and now dominates the Windows market. The sad thing about Vista is that it got a flaming from users and the computing press but it had shed loads of APIs added. I use a lot of APIs which originated with Vista.

I must remember to head my posts with 'Minimum OS required blah, blah, blah'. I use one API which did not appear until Windows 8.1. I wrote some code at PowerBASIC using it but did warn folk, on that occasion. <smile>
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

Image

The icon used started life as a 89,317 640x640 png from Emoji Island and ended up as a 4,286 32x32 ico using XnConvert (Freeware)

How outrageous do you want to be today? <smile>
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: TaskDialog

Post by dodicat »

The taskdialog gives me an entry point not found error message (win 10).
both 64 and 32
I also could not get TaskDialogIndirect (same error).
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

It seems that a manifest is mandatory for both TaskDialog and TaskDialogIndirect. I found no mention of this at MSDN. If I remove the rc file, which loads the manifest, from the command line then I get the same error.

In José Roca's examples which use these functions he writes 'Remarks: Requires the use of a manifest'. He always includes a disclaimer at the head of his source code examples so I went sailing past the manifest comment when I looked at his TaskDialog example.

So far that is the only way I have seen this run-time failure other than nimdays who is on Win XP; which has no idea what TaskDialog is, being introduced in Window Vista.

I originally thought that a manifest was only required if we did not use a system supplied icon, but I was wrong. I mentioned the error in the second post above.

I hope that it is as simple as no manifest being loaded.

I now have 20 icons which can be used instead of the system icons - some are outrageous but some of them are quite 'professional' and superior to the built in icons.

Added: I should add that I did not write Theme.xml. There was a discussion at the PowerBASIC forums where quite a few folk put their two cents in with their versions. I 'grabbed' the one which was deemed to be the most comprehensive. I have searched the Internet but did not find a better one.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: TaskDialog

Post by Josep Roca »

A manifest is required because, otherwise, Windows loads version 5 of the common controls library instead of version 6, and these functions aren't implemented in version 5.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: TaskDialog

Post by dodicat »

Guilty of not reading the instructions.
I went through the process, icon rc and theme.
Works perfectly.
Thank you.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

Thanks José. I can always rely on you to tell me more than Microsoft does.

From my manifest.

Code: Select all

<assemblyIdentity
  type="win32"
  name="Microsoft.Windows.Common-Controls"
  version="6.0.0.0"
  processorArchitecture="*"
  publicKeyToken="6595b64144ccf1df"
  language="*"
/>
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: TaskDialog

Post by dodicat »

I put COMCTL32.DLL into a desktop folder and loaded using loadlibraryex (with 0,0 as the other parameters)
It works fine with built in information icon.

I suppose I could set a path directly to the dll in Windows instead.

Code: Select all


#define _WIN32_WINNT &h0602
#include "windows.bi"
#include once "win\commctrl.bi"
Dim pnButton as integer


dim as any ptr L=loadlibraryex("C:\Users\User\Desktop\dlls\COMCTL32.DLL",0,0)
dim dialog as function (byval hwndOwner as HWND, byval hInstance as HINSTANCE, byval pszWindowTitle as PCWSTR, byval pszMainInstruction as PCWSTR, byval pszContent as PCWSTR, byval dwCommonButtons as TASKDIALOG_COMMON_BUTTON_FLAGS, byval pszIcon as PCWSTR, byval pnButton as long ptr) as HRESULT
print L
dialog=dylibsymbol(L,"TaskDialog")
print dialog


dialog( Null, null, "MyApp", "OK", "..  but I really have better things to do, I really do.", Null, TD_INFORMATION_ICON, @pnButton )

 
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: TaskDialog

Post by deltarho[1859] »

Image

<Big grin>
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: TaskDialog

Post by dodicat »

Thank you deltarho[~] and Josep Roca.
The night wears on, I shall retire now.
Post Reply