[PATCH 2/7] comctl32/taskdialog: Use dynamic resizing.

Zhiyi Zhang yi.gd.cn at gmail.com
Wed May 16 11:14:33 CDT 2018


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/comctl32/taskdialog.c | 476 +++++++++++++++++++++----------------
 1 file changed, 268 insertions(+), 208 deletions(-)

diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 1ab9e133da..4fdea1e889 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -2,6 +2,7 @@
  * Task dialog control
  *
  * Copyright 2017 Fabian Maurer
+ * Copyright 2018 Zhiyi Zhang
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -71,37 +72,23 @@ struct taskdialog_button_desc
 struct taskdialog_template_desc
 {
     const TASKDIALOGCONFIG *taskconfig;
-    unsigned int dialog_height;
-    unsigned int dialog_width;
     struct list controls;
     WORD control_count;
-    LONG x_baseunit;
-    LONG y_baseunit;
-    HFONT font;
-    struct taskdialog_button_desc *default_button;
 };
 
 struct taskdialog_info
 {
     HWND hwnd;
-    PFTASKDIALOGCALLBACK callback;
-    LONG_PTR callback_data;
+    const TASKDIALOGCONFIG *taskconfig;
+    LONG x_baseunit;
+    LONG y_baseunit;
+    HFONT hfont;
 };
 
-static void pixels_to_dialogunits(const struct taskdialog_template_desc *desc, LONG *width, LONG *height)
+static void dialogunits_to_pixels(const struct taskdialog_info *dialog_info, LONG *width, LONG *height)
 {
-    if (width)
-        *width = MulDiv(*width, 4, desc->x_baseunit);
-    if (height)
-        *height = MulDiv(*height, 8, desc->y_baseunit);
-}
-
-static void dialogunits_to_pixels(const struct taskdialog_template_desc *desc, LONG *width, LONG *height)
-{
-    if (width)
-        *width = MulDiv(*width, desc->x_baseunit, 4);
-    if (height)
-        *height = MulDiv(*height, desc->y_baseunit, 8);
+    if (width) *width = MulDiv(*width, dialog_info->x_baseunit, 4);
+    if (height) *height = MulDiv(*height, dialog_info->y_baseunit, 8);
 }
 
 static void template_write_data(char **ptr, const void *src, unsigned int size)
@@ -110,66 +97,54 @@ static void template_write_data(char **ptr, const void *src, unsigned int size)
     *ptr += size;
 }
 
-/* used to calculate size for the controls */
-static void taskdialog_get_text_extent(const struct taskdialog_template_desc *desc, const WCHAR *text,
-        BOOL user_resource, SIZE *sz)
+static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam)
+{
+    const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+    return taskconfig->pfCallback
+               ? taskconfig->pfCallback(dialog_info->hwnd, notification, wparam, lparam, taskconfig->lpCallbackData)
+               : S_OK;
+}
+
+const WCHAR *taskdialog_loadstring(const WCHAR *text, BOOL user_resource, HINSTANCE hinstance, LONG *length)
 {
-    RECT rect = { 0, 0, desc->dialog_width - DIALOG_SPACING * 2, 0}; /* padding left and right of the control */
-    const WCHAR *textW = NULL;
     static const WCHAR nulW;
-    unsigned int length;
-    HFONT oldfont;
-    HDC hdc;
+    const WCHAR *textW = NULL;
 
     if (IS_INTRESOURCE(text))
     {
-        if (!(length = LoadStringW(user_resource ? desc->taskconfig->hInstance : COMCTL32_hModule,
-                (UINT_PTR)text, (WCHAR *)&textW, 0)))
+        if (!(*length = LoadStringW(user_resource ? hinstance : COMCTL32_hModule, (UINT_PTR)text, (WCHAR *)&textW, 0)))
         {
             WARN("Failed to load text\n");
             textW = &nulW;
-            length = 0;
+            *length = 0;
         }
     }
     else
     {
         textW = text;
-        length = strlenW(textW);
+        *length = strlenW(textW);
     }
 
-    hdc = GetDC(0);
-    oldfont = SelectObject(hdc, desc->font);
-
-    dialogunits_to_pixels(desc, &rect.right, NULL);
-    DrawTextW(hdc, textW, length, &rect, DT_LEFT | DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK);
-    pixels_to_dialogunits(desc, &rect.right, &rect.bottom);
-
-    SelectObject(hdc, oldfont);
-    ReleaseDC(0, hdc);
-
-    sz->cx = rect.right - rect.left;
-    sz->cy = rect.bottom - rect.top;
+    return textW;
 }
 
 static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc, WORD id, const WCHAR *class,
-        HINSTANCE hInstance, const WCHAR *text, DWORD style, short x, short y, short cx, short cy)
+                                           HINSTANCE hInstance, const WCHAR *text, DWORD style)
 {
     struct taskdialog_control *control = Alloc(sizeof(*control));
     unsigned int size, class_size, text_size;
     DLGITEMTEMPLATE *template;
     static const WCHAR nulW;
     const WCHAR *textW;
+    LONG length;
     char *ptr;
 
     class_size = (strlenW(class) + 1) * sizeof(WCHAR);
 
-    if (IS_INTRESOURCE(text))
-        text_size = LoadStringW(hInstance, (UINT_PTR)text, (WCHAR *)&textW, 0) * sizeof(WCHAR);
-    else
-    {
-        textW = text;
-        text_size = strlenW(textW) * sizeof(WCHAR);
-    }
+    if (!text) text = &nulW;
+
+    textW = taskdialog_loadstring(text, TRUE, hInstance, &length);
+    text_size = length * sizeof(WCHAR);
 
     size = sizeof(DLGITEMTEMPLATE);
     size += class_size;
@@ -180,11 +155,6 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
     control->template_size = size;
 
     template->style = WS_VISIBLE | style;
-    template->dwExtendedStyle = 0;
-    template->x = x;
-    template->y = y;
-    template->cx = cx;
-    template->cy = cy;
     template->id = id;
     ptr = (char *)(template + 1);
     template_write_data(&ptr, class, class_size);
@@ -198,19 +168,8 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
 
 static unsigned int taskdialog_add_static_label(struct taskdialog_template_desc *desc, WORD id, const WCHAR *str)
 {
-    unsigned int size;
-    SIZE sz;
-
-    if (!str)
-        return 0;
-
-    taskdialog_get_text_extent(desc, str, TRUE, &sz);
-
-    desc->dialog_height += DIALOG_SPACING;
-    size = taskdialog_add_control(desc, id, WC_STATICW, desc->taskconfig->hInstance, str, 0, DIALOG_SPACING,
-            desc->dialog_height, sz.cx, sz.cy);
-    desc->dialog_height += sz.cy + DIALOG_SPACING;
-    return size;
+    if (!str) return 0;
+    return taskdialog_add_control(desc, id, WC_STATICW, desc->taskconfig->hInstance, str, 0);
 }
 
 static unsigned int taskdialog_add_main_instruction(struct taskdialog_template_desc *desc)
@@ -223,97 +182,214 @@ static unsigned int taskdialog_add_content(struct taskdialog_template_desc *desc
     return taskdialog_add_static_label(desc, ID_CONTENT, desc->taskconfig->pszContent);
 }
 
-static void taskdialog_init_button(struct taskdialog_button_desc *button, struct taskdialog_template_desc *desc,
-        int id, const WCHAR *text, BOOL custom_button)
+static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc)
 {
-    SIZE sz;
-
-    taskdialog_get_text_extent(desc, text, custom_button, &sz);
+    const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
+    DWORD style, flags = taskconfig->dwCommonButtons;
+    struct taskdialog_button_desc *buttons;
+    unsigned int max_count, count = 0, i, size = 0;
+    int default_id = 0;
 
-    button->id = id;
-    button->text = text;
-    button->width = max(DIALOG_BUTTON_WIDTH, sz.cx + DIALOG_SPACING * 2);
-    button->line = 0;
-    button->hinst = custom_button ? desc->taskconfig->hInstance : COMCTL32_hModule;
+    /* Allocate enough memory for the custom and the default buttons. Maximum 6
+   * default buttons possible. */
+    max_count = 6;
 
-    if (id == desc->taskconfig->nDefaultButton)
-        desc->default_button = button;
-}
+    if (taskconfig->cButtons && taskconfig->pButtons) max_count += taskconfig->cButtons;
 
-static void taskdialog_init_common_buttons(struct taskdialog_template_desc *desc, struct taskdialog_button_desc *buttons,
-    unsigned int *button_count)
-{
-    DWORD flags = desc->taskconfig->dwCommonButtons;
+    buttons = Alloc(max_count * sizeof(*buttons));
+    if (!buttons) return 0;
 
-#define TASKDIALOG_INIT_COMMON_BUTTON(id) \
-    do { \
-        taskdialog_init_button(&buttons[(*button_count)++], desc, ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), FALSE); \
-    } while(0)
+    if (taskconfig->cButtons && taskconfig->pButtons)
+        for (count = 0; count < taskconfig->cButtons; count++)
+        {
+            buttons[count].id = taskconfig->pButtons[count].nButtonID;
+            buttons[count].text = taskconfig->pButtons[count].pszButtonText;
+            buttons[count].hinst = taskconfig->hInstance;
+        }
 
-    if (flags & TDCBF_OK_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(OK);
+    if (flags & TDCBF_OK_BUTTON
+        || (count == 0 && !(flags & (TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON))))
+    {
+        buttons[count].id = IDOK;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_OK);
+    }
     if (flags & TDCBF_YES_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(YES);
+    {
+        buttons[count].id = IDYES;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_YES);
+    }
     if (flags & TDCBF_NO_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(NO);
+    {
+        buttons[count].id = IDNO;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_NO);
+    }
     if (flags & TDCBF_RETRY_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(RETRY);
+    {
+        buttons[count].id = IDRETRY;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_RETRY);
+    }
     if (flags & TDCBF_CANCEL_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
+    {
+        buttons[count].id = IDCANCEL;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_CANCEL);
+    }
     if (flags & TDCBF_CLOSE_BUTTON)
-        TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
+    {
+        buttons[count].id = IDCLOSE;
+        buttons[count++].text = MAKEINTRESOURCEW(IDS_BUTTON_CLOSE);
+    }
+
+    for (i = 0; i < count; i++)
+        if (buttons[i].id == taskconfig->nDefaultButton) default_id = buttons[i].id;
+
+    if (!default_id) default_id = buttons[0].id;
+
+    for (i = 0; i < count; i++)
+    {
+        style = buttons[i].id == default_id ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON;
+        size += taskdialog_add_control(desc, buttons[i].id, WC_BUTTONW,
+                                       buttons[i].hinst ? buttons[i].hinst : COMCTL32_hModule, buttons[i].text, style);
+    }
 
-#undef TASKDIALOG_INIT_COMMON_BUTTON
+    Free(buttons);
+    return size;
 }
 
-static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc)
+static unsigned int taskdialog_get_reference_rect(struct taskdialog_info *dialog_info, RECT *ret)
 {
-    unsigned int count = 0, buttons_size, i, line_count, size = 0;
-    unsigned int location_x, *line_widths, alignment = ~0u;
-    const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
+    const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+    HMONITOR monitor = MonitorFromWindow(taskconfig->hwndParent ? taskconfig->hwndParent : GetActiveWindow(),
+                                         MONITOR_DEFAULTTOPRIMARY);
+    MONITORINFO info;
+
+    info.cbSize = sizeof(info);
+    GetMonitorInfoW(monitor, &info);
+
+    if (taskconfig->dwFlags & TDF_POSITION_RELATIVE_TO_WINDOW && taskconfig->hwndParent)
+        GetWindowRect(taskconfig->hwndParent, ret);
+    else
+        *ret = info.rcWork;
+
+    return info.rcWork.right - info.rcWork.left;
+}
+
+static void taskdialog_get_label_size(HWND hwnd, LONG max_width, SIZE *size)
+{
+    HFONT hfont, old_hfont;
+    HDC hdc;
+    RECT rect = {0};
+    WCHAR text[1024];
+    INT text_length;
+
+    hfont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0);
+    text_length = GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+    hdc = GetDC(hwnd);
+    old_hfont = SelectObject(hdc, hfont);
+    rect.right = max_width;
+    size->cy = DrawTextW(hdc, text, text_length, &rect, DT_LEFT | DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK);
+    size->cx = min(max_width, rect.right - rect.left);
+    if(old_hfont) SelectObject(hdc, old_hfont);
+    ReleaseDC(hwnd, hdc);
+}
+
+static void taskdialog_resize(struct taskdialog_info *dialog_info)
+{
+    const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+    static BOOL first_time = TRUE;
+    RECT ref_rect, window_rect;
+    LONG screen_width;
+    LONG dialog_width, dialog_height = 0;
+    LONG x, y;
+    SIZE size;
+    LONG horizontal_spacing, vertical_spacing;
+    HWND hwnd;
+    DWORD flags = taskconfig->dwCommonButtons;
+    LONG buttons_max_size, button_min_width, button_count = 0, line_count;
+    LONG *line_widths, alignment;
     struct taskdialog_button_desc *buttons;
+    INT i;
 
-    /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
-    buttons_size = 6;
-    if (taskconfig->cButtons && taskconfig->pButtons)
-        buttons_size += taskconfig->cButtons;
+    screen_width = taskdialog_get_reference_rect(dialog_info, &ref_rect);
 
-    if (!(buttons = Alloc(buttons_size * sizeof(*buttons))))
-        return 0;
+    dialog_width = max(taskconfig->cxWidth, DIALOG_MIN_WIDTH);
+    dialogunits_to_pixels(dialog_info, &dialog_width, 0);
+    dialog_width = min(dialog_width, screen_width);
 
-    /* Custom buttons */
-    if (taskconfig->cButtons && taskconfig->pButtons)
-        for (i = 0; i < taskconfig->cButtons; i++)
-            taskdialog_init_button(&buttons[count++], desc, taskconfig->pButtons[i].nButtonID,
-                    taskconfig->pButtons[i].pszButtonText, TRUE);
+    horizontal_spacing = DIALOG_SPACING;
+    vertical_spacing = DIALOG_SPACING;
 
-    /* Common buttons */
-    taskdialog_init_common_buttons(desc, buttons, &count);
+    dialogunits_to_pixels(dialog_info, &horizontal_spacing, &vertical_spacing);
 
-    /* There must be at least one button */
-    if (count == 0)
-        taskdialog_init_button(&buttons[count++], desc, IDOK, MAKEINTRESOURCEW(IDS_BUTTON_OK), FALSE);
+    /* Main instruction */
+    hwnd = GetDlgItem(dialog_info->hwnd, ID_MAIN_INSTRUCTION);
+    if (hwnd)
+    {
+        x = horizontal_spacing;
+        y = dialog_height + vertical_spacing;
+        size.cx = dialog_width - x - horizontal_spacing;
+        taskdialog_get_label_size(hwnd, size.cx, &size);
+        MoveWindow(hwnd, x, y, size.cx, size.cy, TRUE);
+        dialog_height = y + size.cy;
+    }
+
+    /* Main content */
+    hwnd = GetDlgItem(dialog_info->hwnd, ID_CONTENT);
+    if (hwnd)
+    {
+        x = horizontal_spacing;
+        y = dialog_height + vertical_spacing;
+        size.cx = dialog_width - x - horizontal_spacing;
+        taskdialog_get_label_size(hwnd, size.cx, &size);
+        MoveWindow(hwnd, x, y, size.cx, size.cy, TRUE);
+        dialog_height = y + size.cy;
+    }
+
+    /* Common Buttons and Custom Buttons */
+    /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
+    buttons_max_size = 6;
+    /* Custom buttons */
+    if (taskconfig->cButtons && taskconfig->pButtons) buttons_max_size += taskconfig->cButtons;
 
-    if (!desc->default_button)
-        desc->default_button = &buttons[0];
+    /* For easy handling just allocate as many lines as buttons, the worst case. s*/
+    buttons = Alloc(buttons_max_size * sizeof(*buttons));
+    line_widths = Alloc(buttons_max_size * sizeof(*line_widths));
 
-    /* For easy handling just allocate as many lines as buttons, the worst case. */
-    line_widths = Alloc(count * sizeof(*line_widths));
+    if (taskconfig->cButtons && taskconfig->pButtons)
+        for (button_count = 0; button_count < taskconfig->cButtons; button_count++)
+            buttons[button_count].id = taskconfig->pButtons[button_count].nButtonID;
+
+    /* Ok button may be added if no button is specified in taskconfig */
+    if (GetDlgItem(dialog_info->hwnd, IDOK)) buttons[button_count++].id = IDOK;
+    if (flags & TDCBF_YES_BUTTON) buttons[button_count++].id = IDYES;
+    if (flags & TDCBF_NO_BUTTON) buttons[button_count++].id = IDNO;
+    if (flags & TDCBF_RETRY_BUTTON) buttons[button_count++].id = IDRETRY;
+    if (flags & TDCBF_CANCEL_BUTTON) buttons[button_count++].id = IDCANCEL;
+    if (flags & TDCBF_CLOSE_BUTTON) buttons[button_count++].id = IDCLOSE;
+
+    button_min_width = DIALOG_BUTTON_WIDTH;
+    dialogunits_to_pixels(dialog_info, &button_min_width, 0);
+    for (i = 0; i < button_count; i++)
+    {
+        hwnd = GetDlgItem(dialog_info->hwnd, buttons[i].id);
+        taskdialog_get_label_size(hwnd, dialog_width - horizontal_spacing, &size);
+        buttons[i].width = max(size.cx, button_min_width);
+        buttons[i].line = 0;
+    }
 
     /* Separate buttons into lines */
-    location_x = DIALOG_SPACING;
-    for (i = 0, line_count = 0; i < count; i++)
+    x = horizontal_spacing;
+    for (i = 0, line_count = 0; i < button_count; i++)
     {
-        if (location_x + buttons[i].width + DIALOG_SPACING > desc->dialog_width)
+        if (x + buttons[i].width + horizontal_spacing >= dialog_width)
         {
-            location_x = DIALOG_SPACING;
+            x = horizontal_spacing;
             line_count++;
         }
 
         buttons[i].line = line_count;
 
-        location_x += buttons[i].width + DIALOG_SPACING;
-        line_widths[line_count] += buttons[i].width + DIALOG_SPACING;
+        x += buttons[i].width + horizontal_spacing;
+        line_widths[line_count] += buttons[i].width + horizontal_spacing;
     }
     line_count++;
 
@@ -324,9 +400,8 @@ static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc
         unsigned int j, last_button = 0;
         int diff_changed;
 
-        for (j = 0; j < count; j++)
-            if (buttons[j].line == i - 1)
-                last_button = j;
+        for (j = 0; j < button_count; j++)
+            if (buttons[j].line == i - 1) last_button = j;
 
         /* Difference in length of both lines if we wrapped the last button from the last line into this one */
         diff_changed = abs(2 * buttons[last_button].width + line_widths[i] - line_widths[i - 1]);
@@ -340,38 +415,58 @@ static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc
     }
 
     /* Calculate left alignment so all lines are as far right as possible. */
+    alignment = dialog_width;
     for (i = 0; i < line_count; i++)
     {
-        int new_alignment = desc->dialog_width - line_widths[i];
-        if (new_alignment < alignment)
-            alignment = new_alignment;
+        int new_alignment = dialog_width - line_widths[i];
+        if (new_alignment < alignment) alignment = new_alignment;
     }
 
-    /* Now that we got them all positioned, create all buttons */
-    location_x = alignment;
-    for (i = 0; i < count; i++)
+    /* Now that we got them all positioned, move all buttons */
+    x = alignment;
+    size.cy = DIALOG_BUTTON_HEIGHT;
+    dialogunits_to_pixels(dialog_info, NULL, &size.cy);
+    for (i = 0; i < button_count; i++)
     {
-        DWORD style = &buttons[i] == desc->default_button ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON;
-
-        if (i > 0 && buttons[i].line != buttons[i - 1].line) /* New line */
+        /* New line */
+        if (i > 0 && buttons[i].line != buttons[i - 1].line)
         {
-            location_x = alignment;
-            desc->dialog_height += DIALOG_BUTTON_HEIGHT + DIALOG_SPACING;
+            x = alignment;
+            dialog_height += size.cy + vertical_spacing;
         }
 
-        size += taskdialog_add_control(desc, buttons[i].id, WC_BUTTONW, buttons[i].hinst, buttons[i].text, style,
-                location_x, desc->dialog_height, buttons[i].width, DIALOG_BUTTON_HEIGHT);
-
-        location_x += buttons[i].width + DIALOG_SPACING;
+        y = dialog_height + vertical_spacing;
+        size.cx = buttons[i].width;
+        hwnd = GetDlgItem(dialog_info->hwnd, buttons[i].id);
+        MoveWindow(hwnd, x, y, size.cx, size.cy, TRUE);
+        x += buttons[i].width + horizontal_spacing;
     }
 
-    /* Add height for last row and spacing */
-    desc->dialog_height += DIALOG_BUTTON_HEIGHT + DIALOG_SPACING;
+    /* Add height for last row button and spacing */
+    dialog_height += size.cy + vertical_spacing;
 
     Free(line_widths);
     Free(buttons);
 
-    return size;
+    /* Add height for spacing, title height and frame height */
+    dialog_height += vertical_spacing;
+    dialog_height += GetSystemMetrics(SM_CYCAPTION);
+    dialog_height += GetSystemMetrics(SM_CXDLGFRAME);
+
+    if (first_time)
+    {
+        x = (ref_rect.left + ref_rect.right + dialog_width) / 2;
+        y = (ref_rect.top + ref_rect.bottom + dialog_height) / 2;
+        first_time = FALSE;
+    }
+    else
+    {
+        GetWindowRect(dialog_info->hwnd, &window_rect);
+        x = window_rect.left;
+        y = window_rect.top;
+    }
+
+    MoveWindow(dialog_info->hwnd, x, y, dialog_width, dialog_height, TRUE);
 }
 
 static void taskdialog_clear_controls(struct list *controls)
@@ -386,28 +481,6 @@ static void taskdialog_clear_controls(struct list *controls)
     }
 }
 
-static unsigned int taskdialog_get_reference_rect(const struct taskdialog_template_desc *desc, RECT *ret)
-{
-    HMONITOR monitor = MonitorFromWindow(desc->taskconfig->hwndParent ? desc->taskconfig->hwndParent : GetActiveWindow(),
-            MONITOR_DEFAULTTOPRIMARY);
-    MONITORINFO info;
-
-    info.cbSize = sizeof(info);
-    GetMonitorInfoW(monitor, &info);
-
-    if (desc->taskconfig->dwFlags & TDF_POSITION_RELATIVE_TO_WINDOW && desc->taskconfig->hwndParent)
-        GetWindowRect(desc->taskconfig->hwndParent, ret);
-    else
-        *ret = info.rcWork;
-
-    pixels_to_dialogunits(desc, &ret->left, &ret->top);
-    pixels_to_dialogunits(desc, &ret->right, &ret->bottom);
-
-    pixels_to_dialogunits(desc, &info.rcWork.left, &info.rcWork.top);
-    pixels_to_dialogunits(desc, &info.rcWork.right, &info.rcWork.bottom);
-    return info.rcWork.right - info.rcWork.left;
-}
-
 static WCHAR *taskdialog_get_exe_name(const TASKDIALOGCONFIG *taskconfig, WCHAR *name, DWORD length)
 {
     DWORD len = GetModuleFileNameW(NULL, name, length);
@@ -425,17 +498,14 @@ static WCHAR *taskdialog_get_exe_name(const TASKDIALOGCONFIG *taskconfig, WCHAR
 static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfig)
 {
     struct taskdialog_control *control, *control2;
-    unsigned int size, title_size, screen_width;
+    unsigned int size, title_size;
     struct taskdialog_template_desc desc;
     static const WORD fontsize = 0x7fff;
     static const WCHAR emptyW[] = { 0 };
     const WCHAR *titleW = NULL;
     DLGTEMPLATE *template;
-    NONCLIENTMETRICSW ncm;
     WCHAR pathW[MAX_PATH];
-    RECT ref_rect;
     char *ptr;
-    HDC hdc;
 
     /* Window title */
     if (!taskconfig->pszWindowTitle)
@@ -459,22 +529,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
     desc.taskconfig = taskconfig;
     desc.control_count = 0;
 
-    ncm.cbSize = sizeof(ncm);
-    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
-    desc.font = CreateFontIndirectW(&ncm.lfMessageFont);
-
-    hdc = GetDC(0);
-    SelectObject(hdc, desc.font);
-    desc.x_baseunit = GdiGetCharDimensions(hdc, NULL, &desc.y_baseunit);
-    ReleaseDC(0, hdc);
-
-    screen_width = taskdialog_get_reference_rect(&desc, &ref_rect);
-
-    desc.dialog_height = 0;
-    desc.dialog_width = max(taskconfig->cxWidth, DIALOG_MIN_WIDTH);
-    desc.dialog_width = min(desc.dialog_width, screen_width);
-    desc.default_button = NULL;
-
     size += taskdialog_add_main_instruction(&desc);
     size += taskdialog_add_content(&desc);
     size += taskdialog_add_buttons(&desc);
@@ -483,16 +537,11 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
     if (!template)
     {
         taskdialog_clear_controls(&desc.controls);
-        DeleteObject(desc.font);
         return NULL;
     }
 
     template->style = DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
     template->cdit = desc.control_count;
-    template->x = (ref_rect.left + ref_rect.right + desc.dialog_width) / 2;
-    template->y = (ref_rect.top + ref_rect.bottom + desc.dialog_height) / 2;
-    template->cx = desc.dialog_width;
-    template->cy = desc.dialog_height;
 
     ptr = (char *)(template + 1);
     ptr += 2; /* menu */
@@ -513,22 +562,32 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
         Free(control);
     }
 
-    DeleteObject(desc.font);
     return template;
 }
 
-static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam)
-{
-    return dialog_info->callback ? dialog_info->callback(dialog_info->hwnd, notification, wparam, lparam,
-            dialog_info->callback_data) : S_OK;
-}
-
 static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD command_id)
 {
     if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK)
         EndDialog(dialog_info->hwnd, command_id);
 }
 
+static void taskdialog_init_dialog_info(struct taskdialog_info *dialog_info, HWND hwnd)
+{
+    NONCLIENTMETRICSW ncm;
+    HDC hdc;
+
+    dialog_info->hwnd = hwnd;
+
+    ncm.cbSize = sizeof(ncm);
+    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
+    dialog_info->hfont = CreateFontIndirectW(&ncm.lfMessageFont);
+
+    hdc = GetDC(0);
+    SelectObject(hdc, dialog_info->hfont);
+    dialog_info->x_baseunit = GdiGetCharDimensions(hdc, NULL, &dialog_info->y_baseunit);
+    ReleaseDC(0, hdc);
+}
+
 static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     static const WCHAR taskdialog_info_propnameW[] = {'T','a','s','k','D','i','a','l','o','g','I','n','f','o',0};
@@ -546,8 +605,10 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
             break;
         case WM_INITDIALOG:
             dialog_info = (struct taskdialog_info *)lParam;
-            dialog_info->hwnd = hwnd;
+            taskdialog_init_dialog_info(dialog_info, hwnd);
+
             SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
+            taskdialog_resize(dialog_info);
 
             taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
             break;
@@ -584,8 +645,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *butto
     if (!taskconfig || taskconfig->cbSize != sizeof(TASKDIALOGCONFIG))
         return E_INVALIDARG;
 
-    dialog_info.callback = taskconfig->pfCallback;
-    dialog_info.callback_data = taskconfig->lpCallbackData;
+    dialog_info.taskconfig = taskconfig;
 
     template = create_taskdialog_template(taskconfig);
     ret = (short)DialogBoxIndirectParamW(taskconfig->hInstance, template, taskconfig->hwndParent,
-- 
2.17.0





More information about the wine-devel mailing list