comctl32: Display icon (if possible) and all supplied texts in TaskDialogIndirect

Joachim Priesner joachim.priesner at web.de
Tue Sep 30 08:21:27 CDT 2014


The TaskDialogIndirect function takes three texts: content, main instruction, and footer. The current implementation would only display the main instruction. Now all texts are displayed, concatenated by two newlines if necessary.

Also, if the requested icon is one that is supported by MessageBoxW (error, warning, question, information), that icon is displayed.

Tested on openSuse 13.1 and Windows 8.1 x64.

---
 dlls/comctl32/commctrl.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-
 include/commctrl.h       |  5 ++++
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index 4f4e2b1..f69a23d 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -68,6 +68,7 @@
 #include "shlwapi.h"
 #include "comctl32.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
@@ -92,6 +93,9 @@ static const WCHAR strCC32SubclassInfo[] = {
     'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
 };
 
+static const WCHAR strTwoNewlines[] = {
+    '\r','\n','\r','\n',0
+};
 
 /***********************************************************************
  * DllMain [Internal]
@@ -1607,6 +1611,8 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
 {
     UINT uType = 0;
     INT  ret;
+    UINT mainInstructionLength, contentLength, footerLength, totalLength;
+    WCHAR *buffer;
     FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);
 
     if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
@@ -1628,8 +1634,71 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
     else
     if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
         uType |= MB_OK;
-    ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
+
+    TRACE("flags=%#x, hInstance=%p, icon=%s\n", pTaskConfig->dwFlags, pTaskConfig->hInstance,
+            debugstr_w(pTaskConfig->pszMainIcon));
+
+    if (!(pTaskConfig->dwFlags & TDF_USE_HICON_MAIN))
+    {
+        /* If hInstance is NULL, but pszMainIcon is not one of TD_*_ICON, the icon is taken from
+         * the system's image resources (imageres.dll). This is not really documented, but mentioned
+         * in the documentation for the TDM_UPDATE_ICON message. As a workaround, the values for the
+         * symbols that MessageBoxW supports are hard-coded here. */
+        if (pTaskConfig->pszMainIcon == TD_ERROR_ICON ||
+                (pTaskConfig->hInstance == NULL && pTaskConfig->pszMainIcon == MAKEINTRESOURCEW(0x62)))
+            uType |= MB_ICONERROR;
+        else
+        if (pTaskConfig->pszMainIcon == TD_WARNING_ICON ||
+                (pTaskConfig->hInstance == NULL && pTaskConfig->pszMainIcon == MAKEINTRESOURCEW(0x54)))
+            uType |= MB_ICONWARNING;
+        else
+        if (pTaskConfig->pszMainIcon == TD_INFORMATION_ICON ||
+                (pTaskConfig->hInstance == NULL && pTaskConfig->pszMainIcon == MAKEINTRESOURCEW(0x51)))
+            uType |= MB_ICONINFORMATION;
+        else
+        if (pTaskConfig->hInstance == NULL && pTaskConfig->pszMainIcon == MAKEINTRESOURCEW(0x63))
+            uType |= MB_ICONQUESTION;
+        else
+        if (pTaskConfig->pszMainIcon == TD_SHIELD_ICON)
+            FIXME("TD_SHIELD_ICON not implemented yet\n");
+    }
+
+    /* Concatenate main instruction, content and footer by two newlines each
+     * to simulate the layout of the task dialog. */
+    mainInstructionLength = pTaskConfig->pszMainInstruction == NULL ? 0 : lstrlenW(pTaskConfig->pszMainInstruction);
+    contentLength = pTaskConfig->pszContent == NULL ? 0 : lstrlenW(pTaskConfig->pszContent);
+    footerLength = pTaskConfig->pszFooter == NULL ? 0 : lstrlenW(pTaskConfig->pszFooter);
+
+    totalLength = mainInstructionLength;
+    if (contentLength > 0)
+        totalLength += (totalLength == 0 ? 0 : 4) + contentLength;
+    if (footerLength > 0)
+        totalLength += (totalLength == 0 ? 0 : 4) + footerLength;
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, (totalLength + 1) * sizeof(WCHAR));
+    if (!buffer)
+        return E_OUTOFMEMORY;
+    buffer[0] = '\0';
+    if (mainInstructionLength > 0)
+    {
+        strcatW(buffer, pTaskConfig->pszMainInstruction);
+    }
+    if (contentLength > 0)
+    {
+        if (buffer[0] != '\0')
+            strcatW(buffer, strTwoNewlines);
+        strcatW(buffer, pTaskConfig->pszContent);
+    }
+    if (footerLength > 0)
+    {
+        if (buffer[0] != '\0')
+            strcatW(buffer, strTwoNewlines);
+        strcatW(buffer, pTaskConfig->pszFooter);
+    }
+
+    ret = MessageBoxW(pTaskConfig->hwndParent, buffer,
                       pTaskConfig->pszWindowTitle, uType);
+    HeapFree(GetProcessHeap(), 0, buffer);
     FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);
 
     if (pnButton) *pnButton = ret;
diff --git a/include/commctrl.h b/include/commctrl.h
index 9993ec7..73cc136 100644
--- a/include/commctrl.h
+++ b/include/commctrl.h
@@ -5086,6 +5086,11 @@ static const WCHAR WC_SCROLLBARW[] = { 'S','c','r','o','l','l','B','a','r',0 };
 
 #include <pshpack1.h>
 
+#define TD_WARNING_ICON         MAKEINTRESOURCEW(-1)
+#define TD_ERROR_ICON           MAKEINTRESOURCEW(-2)
+#define TD_INFORMATION_ICON     MAKEINTRESOURCEW(-3)
+#define TD_SHIELD_ICON          MAKEINTRESOURCEW(-4)
+
 enum _TASKDIALOG_FLAGS
 {
     TDF_ENABLE_HYPERLINKS           = 0x0001,
-- 
1.8.4.5




More information about the wine-patches mailing list