[PATCH 4/8] comctl32/taskdialog: Support dynamic layout.

Zhiyi Zhang zzhang at codeweavers.com
Mon Jun 11 23:10:32 CDT 2018


Support dynamic layout since some controls might change
their own layout after creation.

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

diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 549c7f2bf9..bd9e68b604 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -66,21 +66,14 @@ struct taskdialog_button_desc
 {
     int id;
     const WCHAR *text;
-    unsigned int width;
-    unsigned int line;
     HINSTANCE hinst;
 };
 
 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;
 };
 
@@ -89,23 +82,30 @@ struct taskdialog_info
     HWND hwnd;
     const TASKDIALOGCONFIG *taskconfig;
     DWORD last_timer_tick;
+    HFONT font;
     HFONT main_instruction_font;
+    /* Dialog metrics */
+    struct
+    {
+        LONG x_baseunit;
+        LONG y_baseunit;
+        LONG h_spacing;
+        LONG v_spacing;
+    } m;
 };
 
-static void pixels_to_dialogunits(const struct taskdialog_template_desc *desc, LONG *width, LONG *height)
+struct button_layout_info
 {
-    if (width)
-        *width = MulDiv(*width, 4, desc->x_baseunit);
-    if (height)
-        *height = MulDiv(*height, 8, desc->y_baseunit);
-}
+    INT id;
+    HWND hwnd;
+    LONG width;
+    LONG line;
+};
 
-static void dialogunits_to_pixels(const struct taskdialog_template_desc *desc, LONG *width, LONG *height)
+static void taskdialog_du_to_px(struct taskdialog_info *dialog_info, 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->m.x_baseunit, 4);
+    if (height) *height = MulDiv(*height, dialog_info->m.y_baseunit, 8);
 }
 
 static void template_write_data(char **ptr, const void *src, unsigned int size)
@@ -132,49 +132,8 @@ static void taskdialog_set_main_instruction_font(struct taskdialog_info *dialog_
     SendMessageW(hwnd, WM_SETFONT, (WPARAM)dialog_info->main_instruction_font, TRUE);
 }
 
-/* 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)
-{
-    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;
-
-    if (IS_INTRESOURCE(text))
-    {
-        if (!(length = LoadStringW(user_resource ? desc->taskconfig->hInstance : COMCTL32_hModule,
-                (UINT_PTR)text, (WCHAR *)&textW, 0)))
-        {
-            WARN("Failed to load text\n");
-            textW = &nulW;
-            length = 0;
-        }
-    }
-    else
-    {
-        textW = text;
-        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;
-}
-
 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;
@@ -203,10 +162,6 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
 
     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);
@@ -221,17 +176,11 @@ 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;
+    size = taskdialog_add_control(desc, id, WC_STATICW, desc->taskconfig->hInstance, str, 0);
     return size;
 }
 
@@ -248,14 +197,8 @@ static unsigned int taskdialog_add_content(struct taskdialog_template_desc *desc
 static void taskdialog_init_button(struct taskdialog_button_desc *button, struct taskdialog_template_desc *desc,
         int id, const WCHAR *text, BOOL custom_button)
 {
-    SIZE sz;
-
-    taskdialog_get_text_extent(desc, text, custom_button, &sz);
-
     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;
 
     if (id == desc->taskconfig->nDefaultButton)
@@ -290,8 +233,7 @@ static void taskdialog_init_common_buttons(struct taskdialog_template_desc *desc
 
 static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc)
 {
-    unsigned int count = 0, buttons_size, i, line_count, size = 0;
-    unsigned int location_x, *line_widths, alignment = ~0u;
+    unsigned int count = 0, buttons_size, i, size = 0;
     const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
     struct taskdialog_button_desc *buttons;
 
@@ -319,78 +261,13 @@ static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc
     if (!desc->default_button)
         desc->default_button = &buttons[0];
 
-    /* For easy handling just allocate as many lines as buttons, the worst case. */
-    line_widths = Alloc(count * sizeof(*line_widths));
-
-    /* Separate buttons into lines */
-    location_x = DIALOG_SPACING;
-    for (i = 0, line_count = 0; i < count; i++)
-    {
-        if (location_x + buttons[i].width + DIALOG_SPACING > desc->dialog_width)
-        {
-            location_x = DIALOG_SPACING;
-            line_count++;
-        }
-
-        buttons[i].line = line_count;
-
-        location_x += buttons[i].width + DIALOG_SPACING;
-        line_widths[line_count] += buttons[i].width + DIALOG_SPACING;
-    }
-    line_count++;
-
-    /* Try to balance lines so they are about the same size */
-    for (i = 1; i < line_count - 1; i++)
-    {
-        int diff_now = abs(line_widths[i] - line_widths[i - 1]);
-        unsigned int j, last_button = 0;
-        int diff_changed;
-
-        for (j = 0; j < 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]);
-
-        if (diff_changed < diff_now)
-        {
-            buttons[last_button].line = i;
-            line_widths[i] += buttons[last_button].width;
-            line_widths[i - 1] -= buttons[last_button].width;
-        }
-    }
-
-    /* Calculate left alignment so all lines are as far right as possible. */
-    for (i = 0; i < line_count; i++)
-    {
-        int new_alignment = desc->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;
+    /* create all buttons */
     for (i = 0; i < 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 */
-        {
-            location_x = alignment;
-            desc->dialog_height += DIALOG_BUTTON_HEIGHT + DIALOG_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;
+        size += taskdialog_add_control(desc, buttons[i].id, WC_BUTTONW, buttons[i].hinst, buttons[i].text, style);
     }
 
-    /* Add height for last row and spacing */
-    desc->dialog_height += DIALOG_BUTTON_HEIGHT + DIALOG_SPACING;
-
-    Free(line_widths);
     Free(buttons);
 
     return size;
@@ -408,25 +285,20 @@ static void taskdialog_clear_controls(struct list *controls)
     }
 }
 
-static unsigned int taskdialog_get_reference_rect(const struct taskdialog_template_desc *desc, RECT *ret)
+static unsigned int taskdialog_get_reference_rect(const TASKDIALOGCONFIG *taskconfig, RECT *ret)
 {
-    HMONITOR monitor = MonitorFromWindow(desc->taskconfig->hwndParent ? desc->taskconfig->hwndParent : GetActiveWindow(),
-            MONITOR_DEFAULTTOPRIMARY);
+    HMONITOR monitor = MonitorFromWindow(taskconfig->hwndParent ? 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);
+    if (taskconfig->dwFlags & TDF_POSITION_RELATIVE_TO_WINDOW && taskconfig->hwndParent)
+        GetWindowRect(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;
 }
 
@@ -447,17 +319,14 @@ static WCHAR *taskdialog_get_exe_name(WCHAR *name, DWORD length)
 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)
@@ -480,21 +349,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
     list_init(&desc.controls);
     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);
@@ -505,7 +359,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
     if (!template)
     {
         taskdialog_clear_controls(&desc.controls);
-        DeleteObject(desc.font);
         return NULL;
     }
 
@@ -514,10 +367,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
     if (!(taskconfig->dwFlags & TDF_NO_SET_FOREGROUND)) template->style |= DS_SETFOREGROUND;
     if (taskconfig->dwFlags & TDF_RTL_LAYOUT) template->dwExtendedStyle = WS_EX_LAYOUTRTL | WS_EX_RIGHT | WS_EX_RTLREADING;
     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 */
@@ -538,7 +387,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
         Free(control);
     }
 
-    DeleteObject(desc.font);
     return template;
 }
 
@@ -556,13 +404,219 @@ static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD
         EndDialog(dialog_info->hwnd, command_id);
 }
 
+static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND hwnd, LONG max_width, SIZE *size)
+{
+    DWORD style = DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK;
+    HFONT hfont, old_hfont;
+    HDC hdc;
+    RECT rect = {0};
+    WCHAR text[1024];
+    INT text_length;
+
+    if (dialog_info->taskconfig->dwFlags & TDF_RTL_LAYOUT)
+        style |= DT_RIGHT | DT_RTLREADING;
+    else
+        style |= DT_LEFT;
+
+    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, style);
+    size->cx = min(max_width, rect.right - rect.left);
+    if (old_hfont) SelectObject(hdc, old_hfont);
+    ReleaseDC(hwnd, hdc);
+}
+
+static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hwnd, INT start_x, LONG dialog_width,
+                                    LONG *dialog_height)
+{
+    LONG x, y, max_width;
+    SIZE size;
+
+    if (!hwnd) return;
+
+    x = start_x + dialog_info->m.h_spacing;
+    y = *dialog_height + dialog_info->m.v_spacing;
+    max_width = dialog_width - x - dialog_info->m.h_spacing;
+    taskdialog_get_label_size(dialog_info, hwnd, max_width, &size);
+    SetWindowPos(hwnd, 0, x, y, size.cx, size.cy, SWP_NOZORDER);
+    *dialog_height = y + size.cy;
+}
+
+static void taskdialog_layout(struct taskdialog_info *dialog_info)
+{
+    const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+    DWORD flags = taskconfig->dwCommonButtons;
+    static BOOL first_time = TRUE;
+    HWND hwnd;
+    RECT ref_rect;
+    LONG screen_width, dialog_width, dialog_height = 0;
+    LONG h_spacing, v_spacing;
+    INT button_max_count, button_count = 0;
+    struct button_layout_info *button_layout_infos;
+    LONG button_min_width, button_height;
+    LONG *line_widths, line_count, align;
+    LONG x, y;
+    SIZE size;
+    INT i;
+
+    screen_width = taskdialog_get_reference_rect(dialog_info->taskconfig, &ref_rect);
+    dialog_width = max(taskconfig->cxWidth, DIALOG_MIN_WIDTH);
+    taskdialog_du_to_px(dialog_info, &dialog_width, 0);
+    dialog_width = min(dialog_width, screen_width);
+
+    h_spacing = dialog_info->m.h_spacing;
+    v_spacing = dialog_info->m.v_spacing;
+
+    /* Main instruction */
+    hwnd = GetDlgItem(dialog_info->hwnd, ID_MAIN_INSTRUCTION);
+    taskdialog_label_layout(dialog_info, hwnd, 0, dialog_width, &dialog_height);
+
+    /* Content */
+    hwnd = GetDlgItem(dialog_info->hwnd, ID_CONTENT);
+    taskdialog_label_layout(dialog_info, hwnd, 0, dialog_width, &dialog_height);
+
+    /* Common and custom buttons */
+    /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
+    button_max_count = 6;
+    /* Custom buttons */
+    if (taskconfig->cButtons && taskconfig->pButtons) button_max_count += taskconfig->cButtons;
+
+    button_layout_infos = Alloc(button_max_count * sizeof(*button_layout_infos));
+    line_widths = Alloc(button_max_count * sizeof(*line_widths));
+
+    if (taskconfig->cButtons && taskconfig->pButtons)
+        for (button_count = 0; button_count < taskconfig->cButtons; button_count++)
+            button_layout_infos[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)) button_layout_infos[button_count++].id = IDOK;
+    if (flags & TDCBF_YES_BUTTON) button_layout_infos[button_count++].id = IDYES;
+    if (flags & TDCBF_NO_BUTTON) button_layout_infos[button_count++].id = IDNO;
+    if (flags & TDCBF_RETRY_BUTTON) button_layout_infos[button_count++].id = IDRETRY;
+    if (flags & TDCBF_CANCEL_BUTTON) button_layout_infos[button_count++].id = IDCANCEL;
+    if (flags & TDCBF_CLOSE_BUTTON) button_layout_infos[button_count++].id = IDCLOSE;
+
+    button_min_width = DIALOG_BUTTON_WIDTH;
+    button_height = DIALOG_BUTTON_HEIGHT;
+    taskdialog_du_to_px(dialog_info, &button_min_width, &button_height);
+    for (i = 0; i < button_count; i++)
+    {
+        button_layout_infos[i].hwnd = GetDlgItem(dialog_info->hwnd, button_layout_infos[i].id);
+        taskdialog_get_label_size(dialog_info, button_layout_infos[i].hwnd, dialog_width - h_spacing * 2, &size);
+        button_layout_infos[i].width = max(size.cx, button_min_width);
+    }
+
+    /* Separate buttons into lines */
+    x = h_spacing;
+    for (i = 0, line_count = 0; i < button_count; i++)
+    {
+        if (x + button_layout_infos[i].width + h_spacing >= dialog_width)
+        {
+            x = h_spacing;
+            line_count++;
+        }
+
+        button_layout_infos[i].line = line_count;
+
+        x += button_layout_infos[i].width + h_spacing;
+        line_widths[line_count] += button_layout_infos[i].width + h_spacing;
+    }
+    line_count++;
+
+    /* Try to balance lines so they are about the same size */
+    for (i = 1; i < line_count - 1; i++)
+    {
+        int diff_now = abs(line_widths[i] - line_widths[i - 1]);
+        unsigned int j, last_button = 0;
+        int diff_changed;
+
+        for (j = 0; j < button_count; j++)
+            if (button_layout_infos[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 * button_layout_infos[last_button].width + line_widths[i] - line_widths[i - 1]);
+
+        if (diff_changed < diff_now)
+        {
+            button_layout_infos[last_button].line = i;
+            line_widths[i] += button_layout_infos[last_button].width;
+            line_widths[i - 1] -= button_layout_infos[last_button].width;
+        }
+    }
+
+    /* Calculate left alignment so all lines are as far right as possible. */
+    align = dialog_width - h_spacing;
+    for (i = 0; i < line_count; i++)
+    {
+        int new_alignment = dialog_width - line_widths[i];
+        if (new_alignment < align) align = new_alignment;
+    }
+
+    /* Now that we got them all positioned, move all buttons */
+    x = align;
+    size.cy = button_height;
+    for (i = 0; i < button_count; i++)
+    {
+        /* New line */
+        if (i > 0 && button_layout_infos[i].line != button_layout_infos[i - 1].line)
+        {
+            x = align;
+            dialog_height += size.cy + v_spacing;
+        }
+
+        y = dialog_height + v_spacing;
+        size.cx = button_layout_infos[i].width;
+        SetWindowPos(button_layout_infos[i].hwnd, 0, x, y, size.cx, size.cy, SWP_NOZORDER);
+        x += button_layout_infos[i].width + h_spacing;
+    }
+
+    /* Add height for last row button and spacing */
+    dialog_height += size.cy + v_spacing;
+
+    Free(button_layout_infos);
+    Free(line_widths);
+
+    /* Add height for spacing, title height and frame height */
+    dialog_height += v_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;
+        SetWindowPos(dialog_info->hwnd, 0, x, y, dialog_width, dialog_height, SWP_NOZORDER);
+        first_time = FALSE;
+    }
+    else
+        SetWindowPos(dialog_info->hwnd, 0, 0, 0, dialog_width, dialog_height, SWP_NOMOVE | SWP_NOZORDER);
+}
+
 static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
 {
     const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+    NONCLIENTMETRICSW ncm;
+    HDC hdc;
+
+    ncm.cbSize = sizeof(ncm);
+    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
 
     memset(dialog_info, 0, sizeof(*dialog_info));
     dialog_info->taskconfig = taskconfig;
     dialog_info->hwnd = hwnd;
+    dialog_info->font = CreateFontIndirectW(&ncm.lfMessageFont);
+
+    hdc = GetDC(dialog_info->hwnd);
+    SelectObject(hdc, dialog_info->font);
+    dialog_info->m.x_baseunit = GdiGetCharDimensions(hdc, NULL, &dialog_info->m.y_baseunit);
+    ReleaseDC(dialog_info->hwnd, hdc);
+
+    dialog_info->m.h_spacing = DIALOG_SPACING;
+    dialog_info->m.v_spacing = DIALOG_SPACING;
+    taskdialog_du_to_px(dialog_info, &dialog_info->m.h_spacing, &dialog_info->m.v_spacing);
 
     if (taskconfig->dwFlags & TDF_CALLBACK_TIMER)
     {
@@ -571,11 +625,13 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
     }
 
     taskdialog_set_main_instruction_font(dialog_info);
+    taskdialog_layout(dialog_info);
 }
 
 static void taskdialog_destroy(struct taskdialog_info *dialog_info)
 {
     if (dialog_info->taskconfig->dwFlags & TDF_CALLBACK_TIMER) KillTimer(dialog_info->hwnd, ID_TIMER);
+    if (dialog_info->font) DeleteObject(dialog_info->font);
     if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
 }
 
-- 
2.17.1





More information about the wine-devel mailing list