Signed-off-by: Zhiyi Zhang zzhang@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,