[08/18] comctl32: TaskDialog - Implement buttons

Fabian Maurer dark.shadow4 at web.de
Fri Feb 24 14:04:02 CST 2017


They are properly placed but aren't working yet.

Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
 dlls/comctl32/taskdialog.c | 158 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 152 insertions(+), 6 deletions(-)

diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 9297264ad4..3d6b99000c 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -34,6 +34,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
+#define MIN_SIZE_BUTTON 30
+
 typedef struct
 {
     DLGITEMTEMPLATE template;
@@ -58,6 +60,15 @@ typedef struct
     UINT titleSize; /* Length in bytes including null-terminator */
 }dialog_header;
 
+typedef struct
+{
+    int id;
+    const WCHAR *text;
+    UINT width;
+    UINT x;
+    UINT y;
+}button_info;
+
 #define MEMCPY_MOVEPTR(target, source, size) memcpy(target, source, size); target += size;
 
 #define STR_SIZE(str) ((lstrlenW(str) + 1) * sizeof(WCHAR))
@@ -187,7 +198,7 @@ static void controls_destroy(struct list *controls)
 }
 
 /* Adds a control for the TaskDialog into our list */
-static void controls_add(struct list *controls, WORD id, const WCHAR *class, const WCHAR *text,
+static DLGITEMTEMPLATE* controls_add(struct list *controls, WORD id, const WCHAR *class, const WCHAR *text,
                        DWORD style, short x, short y, short cx, short cy)
 {
     control_info *data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(control_info));
@@ -205,6 +216,8 @@ static void controls_add(struct list *controls, WORD id, const WCHAR *class, con
     data->text_size = STR_SIZE(text);
 
     list_add_tail(controls, &data->entry);
+
+    return &data->template;
 }
 
 /* used to calculate size for the static controls */
@@ -241,6 +254,30 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
         case WM_INITDIALOG:
             PostMessageW(GetDlgItem(hwndDlg, ID_TEXTMAIN), WM_SETFONT, (WPARAM)font_main, TRUE);
             PostMessageW(GetDlgItem(hwndDlg, ID_TEXTCONTENT), WM_SETFONT, (WPARAM)font_default, TRUE);
+
+            if(task_config->dwCommonButtons & TDCBF_OK_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDOK), WM_SETFONT, (WPARAM)font_default, TRUE);
+            if(task_config->dwCommonButtons & TDCBF_YES_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDYES), WM_SETFONT, (WPARAM)font_default, TRUE);
+            if(task_config->dwCommonButtons & TDCBF_NO_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDNO), WM_SETFONT, (WPARAM)font_default, TRUE);
+            if(task_config->dwCommonButtons & TDCBF_CANCEL_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDCANCEL), WM_SETFONT, (WPARAM)font_default, TRUE);
+            if(task_config->dwCommonButtons & TDCBF_RETRY_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDRETRY), WM_SETFONT, (WPARAM)font_default, TRUE);
+            if(task_config->dwCommonButtons & TDCBF_CLOSE_BUTTON)
+                PostMessageW(GetDlgItem(hwndDlg, IDCLOSE), WM_SETFONT, (WPARAM)font_default, TRUE);
+
+            if(task_config->cButtons && task_config->pButtons)
+            {
+                int i;
+                for(i=0; i< task_config->cButtons; i++)
+                {
+                    PostMessageW(GetDlgItem(hwndDlg, task_config->pButtons[i].nButtonID),
+                                 WM_SETFONT, (WPARAM)font_default, TRUE);
+                }
+            }
+
             callback(hwndDlg, TDN_DIALOG_CONSTRUCTED, 0, 0);
             callback(hwndDlg, TDN_CREATED, 0, 0);
 
@@ -275,6 +312,118 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
     return FALSE;
 }
 
+static button_info make_button(HDC hdc, UINT dialog_width, int id, const WCHAR *text)
+{
+    RECT rect;
+    button_info button;
+
+    button.id = id;
+    button.text = text;
+    rect = text_get_rect(hdc, text, dialog_width);
+    button.width = rect.right + 10;
+    if(button.width < MIN_SIZE_BUTTON)
+        button.width = MIN_SIZE_BUTTON;
+
+    return button;
+}
+
+static UINT add_buttons(HDC hdc, const TASKDIALOGCONFIG *pTaskConfig, struct list *controls,
+                        UINT dialog_width, UINT dialog_height)
+{
+    static const WCHAR class_button[] = {'B','u','t','t','o','n',0};
+    static const WCHAR text_ok[] = {'O','K',0};
+    static const WCHAR text_yes[] = {'Y','e','s',0};
+    static const WCHAR text_no[] = {'N','o',0};
+    static const WCHAR text_cancel[] = {'C','a','n','c','e','l',0};
+    static const WCHAR text_retry[] = {'R','e','t','r','y',0};
+    static const WCHAR text_close[] = {'C','l','o','s','e',0};
+    UINT alignment = 40; /* minimum distance from the left dialog border */
+    UINT location_x;
+    BOOL first_row = TRUE;
+    button_info *buttons;
+    int count = 0;
+    int i;
+
+    /* Allocate enough memory for the custom and the default buttons */
+    if(pTaskConfig->cButtons && pTaskConfig->pButtons)
+        buttons = HeapAlloc(GetProcessHeap(), 0, (pTaskConfig->cButtons + 6)*sizeof(button_info));
+    else
+    {
+        buttons = HeapAlloc(GetProcessHeap(), 0, 6*sizeof(button_info));
+    }
+
+    /* Custom buttons */
+    if(pTaskConfig->cButtons && pTaskConfig->pButtons)
+    {
+        for(i=0; i<pTaskConfig->cButtons; i++)
+        {
+            buttons[count++] = make_button(hdc, dialog_width, pTaskConfig->pButtons[i].nButtonID,
+                                           pTaskConfig->pButtons[i].pszButtonText);
+        }
+    }
+
+    /* Default buttons */
+    if(pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDOK, text_ok);
+    if(pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDYES, text_yes);
+    if(pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDNO, text_no);
+    if(pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDRETRY, text_retry);
+    if(pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDCANCEL, text_cancel);
+    if(pTaskConfig->dwCommonButtons & TDCBF_CLOSE_BUTTON)
+        buttons[count++] = make_button(hdc, dialog_width, IDCLOSE, text_close);
+
+    /* There must be at least one button */
+    if(!(pTaskConfig->cButtons && pTaskConfig->pButtons) && !pTaskConfig->dwCommonButtons)
+        buttons[count++] = make_button(hdc, dialog_width, IDOK, text_ok);
+
+    /* Position buttons */
+    location_x = alignment;
+    for(i=0; i<count; i++)
+    {
+        if(location_x + buttons[i].width + 4 > dialog_width) /* When beginning new row, align the first */
+        {
+            if(first_row)
+            {
+                int diff = dialog_width - location_x;
+
+                first_row = FALSE;
+                for(int j=0; j<i; j++) /* Align first row to the right */
+                    buttons[j].x += diff;
+                alignment = buttons[0].x; /* left-align all coming rows to the first row */
+            }
+            location_x = alignment;
+            dialog_height += 11;
+        }
+
+        buttons[i].x = location_x;
+        buttons[i].y = dialog_height;
+
+        location_x += buttons[i].width + 4;
+    }
+    if(first_row) /* Always align first row to the right */
+    {
+        int diff = dialog_width -(buttons[count-1].x + buttons[count-1].width + 4) ;
+        for(int i=0; i<count; i++)
+            buttons[i].x += diff;
+    }
+
+     /* Now that we got them all positioned, create all buttons */
+    for(i=0; i<count; i++)
+    {
+        controls_add(controls, buttons[i].id, class_button, buttons[i].text, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
+                               buttons[i].x, buttons[i].y, buttons[i].width, 10);
+    }
+
+    dialog_height += 20;
+
+    HeapFree(GetProcessHeap(), 0, buttons);
+    return dialog_height;
+}
+
 /***********************************************************************
  * TaskDialogIndirect [COMCTL32.@]
  */
@@ -283,9 +432,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
 {
     static const WCHAR empty_string[] = {0};
     static const WCHAR font_name[] = {'T','a','h','o','m','a',0};
-    static const WCHAR class_button[] = {'B','u','t','t','o','n',0};
     static const WCHAR class_static[] = {'S','t','a','t','i','c',0};
-    static const WCHAR text_ok[] = {'O','K',0};
     RECT desktop;
     UINT dialog_width; /* In dialog units */
     UINT dialog_height; /* In dialog units */
@@ -348,9 +495,8 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
         dialog_height += rect.bottom + 10;
     }
 
-    controls_add(controls, IDOK, class_button, text_ok,
-                 WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, dialog_width - 40 - 10, dialog_height + 5, 40, 10);
-    dialog_height += 10 + 10;
+    /* Create buttons */
+    dialog_height = add_buttons(dc_dummy, pTaskConfig, controls, dialog_width, dialog_height);
 
     header.title = pTaskConfig->pszWindowTitle;
     if(!header.title)
-- 
2.11.1




More information about the wine-patches mailing list