Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2018
- 68 participants
- 1149 messages
Re: [PATCH 3/3] msvcrt: Implement quick_exit and _crt_at_quick_exit
by Fabian Maurer
> Why don't you just call onexit functions instead of reimplementing it?
> Note that you don't need to call MSVCRT__initialize_onexit_table when
> quick_exit table is declared static.
What do you mean? AFAIK the onquickexit functions are different
functions than the one registered onexit, no? So I need to have a second
function that uses a different table. Or put the shared functionality into a
shared function.
Regards,
Fabian Maurer
June 12, 2018
Re: [PATCH 2/3] msvcrt: Add quick_exit
by Fabian Maurer
> quick_exit function should not call exit. I'm attaching a test that
> shows that atexit callbacks should not be called.
I know, and MSVCRT__exit only calls ExitProcess, not calling any
callbacks.
Regards,
Fabian Maurer
June 12, 2018
[PATCH 8/8] comctl32/taskdialog: Delete unused template related code.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 101 +------------------------------------
1 file changed, 1 insertion(+), 100 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index fef269fc0b..7a09b8a6d2 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -34,16 +34,10 @@
#include "comctl32.h"
#include "wine/debug.h"
-#include "wine/list.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(taskdialog);
-#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
-#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
-#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
-#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
-
static const UINT DIALOG_MIN_WIDTH = 240;
static const UINT DIALOG_SPACING = 5;
static const UINT DIALOG_BUTTON_WIDTH = 50;
@@ -52,21 +46,6 @@ static const UINT DIALOG_TIMER_MS = 200;
static const UINT ID_TIMER = 1;
-struct taskdialog_control
-{
- struct list entry;
- DLGITEMTEMPLATE *template;
- unsigned int template_size;
-};
-
-struct taskdialog_template_desc
-{
- const TASKDIALOGCONFIG *taskconfig;
- struct list controls;
- WORD control_count;
- struct taskdialog_button_desc *default_button;
-};
-
struct taskdialog_info
{
HWND hwnd;
@@ -108,59 +87,6 @@ static void template_write_data(char **ptr, const void *src, unsigned int size)
*ptr += size;
}
-static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc, WORD id, const WCHAR *class,
- 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;
- 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);
- }
-
- size = sizeof(DLGITEMTEMPLATE);
- size += class_size;
- size += text_size + sizeof(WCHAR);
- size += sizeof(WORD); /* creation data */
-
- control->template = template = Alloc(size);
- control->template_size = size;
-
- template->style = WS_VISIBLE | style;
- template->dwExtendedStyle = 0;
- template->id = id;
- ptr = (char *)(template + 1);
- template_write_data(&ptr, class, class_size);
- template_write_data(&ptr, textW, text_size);
- template_write_data(&ptr, &nulW, sizeof(nulW));
-
- list_add_tail(&desc->controls, &control->entry);
- desc->control_count++;
- return ALIGNED_LENGTH(size, 3);
-}
-
-static void taskdialog_clear_controls(struct list *controls)
-{
- struct taskdialog_control *control, *control2;
-
- LIST_FOR_EACH_ENTRY_SAFE(control, control2, controls, struct taskdialog_control, entry)
- {
- list_remove(&control->entry);
- Free(control->template);
- Free(control);
- }
-}
-
static unsigned int taskdialog_get_reference_rect(const TASKDIALOGCONFIG *taskconfig, RECT *ret)
{
HMONITOR monitor = MonitorFromWindow(taskconfig->hwndParent ? taskconfig->hwndParent : GetActiveWindow(),
@@ -194,9 +120,7 @@ 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;
- struct taskdialog_template_desc desc;
static const WORD fontsize = 0x7fff;
static const WCHAR emptyW[] = { 0 };
const WCHAR *titleW = NULL;
@@ -222,23 +146,13 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
size += title_size;
size += 2; /* font size */
- list_init(&desc.controls);
- desc.taskconfig = taskconfig;
- desc.control_count = 0;
- desc.default_button = NULL;
-
template = Alloc(size);
- if (!template)
- {
- taskdialog_clear_controls(&desc.controls);
- return NULL;
- }
+ if (!template) return NULL;
template->style = DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
if (taskconfig->dwFlags & TDF_CAN_BE_MINIMIZED) template->style |= WS_MINIMIZEBOX;
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;
ptr = (char *)(template + 1);
ptr += 2; /* menu */
@@ -246,19 +160,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
template_write_data(&ptr, titleW, title_size);
template_write_data(&ptr, &fontsize, sizeof(fontsize));
- /* write control entries */
- LIST_FOR_EACH_ENTRY_SAFE(control, control2, &desc.controls, struct taskdialog_control, entry)
- {
- ALIGN_POINTER(ptr, 3);
-
- template_write_data(&ptr, control->template, control->template_size);
-
- /* list item won't be needed later */
- list_remove(&control->entry);
- Free(control->template);
- Free(control);
- }
-
return template;
}
--
2.17.1
June 12, 2018
[PATCH 7/8] comctl32/taskdialog: Create buttons without templates.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 192 ++++++++++++++-----------------------
1 file changed, 73 insertions(+), 119 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index d71189d4de..fef269fc0b 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -59,13 +59,6 @@ struct taskdialog_control
unsigned int template_size;
};
-struct taskdialog_button_desc
-{
- int id;
- const WCHAR *text;
- HINSTANCE hinst;
-};
-
struct taskdialog_template_desc
{
const TASKDIALOGCONFIG *taskconfig;
@@ -84,6 +77,9 @@ struct taskdialog_info
/* Control handles */
HWND main_instruction;
HWND content;
+ HWND *buttons;
+ INT button_count;
+ HWND default_button;
/* Dialog metrics */
struct
{
@@ -96,8 +92,6 @@ struct taskdialog_info
struct button_layout_info
{
- INT id;
- HWND hwnd;
LONG width;
LONG line;
};
@@ -155,85 +149,6 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
return ALIGNED_LENGTH(size, 3);
}
-static void taskdialog_init_button(struct taskdialog_button_desc *button, struct taskdialog_template_desc *desc,
- int id, const WCHAR *text, BOOL custom_button)
-{
- button->id = id;
- button->text = text;
- button->hinst = custom_button ? desc->taskconfig->hInstance : COMCTL32_hModule;
-
- if (id == desc->taskconfig->nDefaultButton)
- desc->default_button = button;
-}
-
-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;
-
-#define TASKDIALOG_INIT_COMMON_BUTTON(id) \
- do { \
- taskdialog_init_button(&buttons[(*button_count)++], desc, ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), FALSE); \
- } while(0)
-
- if (flags & TDCBF_OK_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(OK);
- if (flags & TDCBF_YES_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(YES);
- if (flags & TDCBF_NO_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(NO);
- if (flags & TDCBF_RETRY_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(RETRY);
- if (flags & TDCBF_CANCEL_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
- if (flags & TDCBF_CLOSE_BUTTON)
- TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
-
-#undef TASKDIALOG_INIT_COMMON_BUTTON
-}
-
-static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc)
-{
- unsigned int count = 0, buttons_size, i, size = 0;
- const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
- struct taskdialog_button_desc *buttons;
-
- /* 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;
-
- if (!(buttons = Alloc(buttons_size * sizeof(*buttons))))
- return 0;
-
- /* 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);
-
- /* Common buttons */
- taskdialog_init_common_buttons(desc, buttons, &count);
-
- /* There must be at least one button */
- if (count == 0)
- taskdialog_init_button(&buttons[count++], desc, IDOK, MAKEINTRESOURCEW(IDS_BUTTON_OK), FALSE);
-
- if (!desc->default_button)
- desc->default_button = &buttons[0];
-
- /* create all buttons */
- for (i = 0; i < count; i++)
- {
- DWORD style = &buttons[i] == desc->default_button ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON;
- size += taskdialog_add_control(desc, buttons[i].id, WC_BUTTONW, buttons[i].hinst, buttons[i].text, style);
- }
-
- Free(buttons);
-
- return size;
-}
-
static void taskdialog_clear_controls(struct list *controls)
{
struct taskdialog_control *control, *control2;
@@ -312,8 +227,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
desc.control_count = 0;
desc.default_button = NULL;
- size += taskdialog_add_buttons(&desc);
-
template = Alloc(size);
if (!template)
{
@@ -450,6 +363,58 @@ static void taskdialog_add_content(struct taskdialog_info *dialog_info)
dialog_info->content = taskdialog_create_label(dialog_info, dialog_info->taskconfig->pszContent, dialog_info->font);
}
+static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT id, const WCHAR *text,
+ BOOL custom_button)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ WCHAR *textW;
+
+ textW = taskdialog_gettext(dialog_info, custom_button, text);
+ *button = CreateWindowW(WC_BUTTONW, textW, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 0, 0, dialog_info->hwnd,
+ (HMENU)id, 0, NULL);
+ Free(textW);
+ SendMessageW(*button, WM_SETFONT, (WPARAM)dialog_info->font, 0);
+
+ if (id == taskconfig->nDefaultButton && !dialog_info->default_button) dialog_info->default_button = *button;
+}
+
+static void taskdialog_add_buttons(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ DWORD flags = taskconfig->dwCommonButtons;
+ INT count, max_count;
+
+ /* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
+ max_count = 6;
+ if (taskconfig->cButtons && taskconfig->pButtons) max_count += taskconfig->cButtons;
+
+ dialog_info->buttons = Alloc(max_count * sizeof(*dialog_info->buttons));
+ if (!dialog_info->buttons) return;
+
+ for (count = 0; count < taskconfig->cButtons; count++)
+ taskdialog_add_button(dialog_info, &dialog_info->buttons[count], taskconfig->pButtons[count].nButtonID,
+ taskconfig->pButtons[count].pszButtonText, TRUE);
+
+#define TASKDIALOG_INIT_COMMON_BUTTON(id) \
+ do \
+ { \
+ taskdialog_add_button(dialog_info, &dialog_info->buttons[count++], ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), \
+ FALSE); \
+ } while (0)
+
+ if (flags & TDCBF_OK_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(OK);
+ if (flags & TDCBF_YES_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(YES);
+ if (flags & TDCBF_NO_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(NO);
+ if (flags & TDCBF_RETRY_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(RETRY);
+ if (flags & TDCBF_CANCEL_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
+ if (flags & TDCBF_CLOSE_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
+
+ if (!count) TASKDIALOG_INIT_COMMON_BUTTON(OK);
+#undef TASKDIALOG_INIT_COMMON_BUTTON
+
+ dialog_info->button_count = count;
+}
+
static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hwnd, INT start_x, LONG dialog_width,
LONG *dialog_height)
{
@@ -469,12 +434,10 @@ static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hw
static void taskdialog_layout(struct taskdialog_info *dialog_info)
{
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
- DWORD flags = taskconfig->dwCommonButtons;
static BOOL first_time = TRUE;
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;
@@ -497,39 +460,21 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
taskdialog_label_layout(dialog_info, dialog_info->content, 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_layout_infos = Alloc(dialog_info->button_count * sizeof(*button_layout_infos));
+ line_widths = Alloc(dialog_info->button_count * sizeof(*line_widths));
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++)
+ for (i = 0; i < dialog_info->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);
+ taskdialog_get_label_size(dialog_info, dialog_info->buttons[i], 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++)
+ for (i = 0, line_count = 0; i < dialog_info->button_count; i++)
{
if (x + button_layout_infos[i].width + h_spacing >= dialog_width)
{
@@ -551,7 +496,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
unsigned int j, last_button = 0;
int diff_changed;
- for (j = 0; j < button_count; j++)
+ for (j = 0; j < dialog_info->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 */
@@ -576,7 +521,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
/* Now that we got them all positioned, move all buttons */
x = align;
size.cy = button_height;
- for (i = 0; i < button_count; i++)
+ for (i = 0; i < dialog_info->button_count; i++)
{
/* New line */
if (i > 0 && button_layout_infos[i].line != button_layout_infos[i - 1].line)
@@ -587,7 +532,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
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);
+ SetWindowPos(dialog_info->buttons[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
x += button_layout_infos[i].width + h_spacing;
}
@@ -618,6 +563,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
NONCLIENTMETRICSW ncm;
HDC hdc;
+ INT id;
ncm.cbSize = sizeof(ncm);
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
@@ -644,6 +590,13 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
taskdialog_add_main_instruction(dialog_info);
taskdialog_add_content(dialog_info);
+ taskdialog_add_buttons(dialog_info);
+
+ /* Set default button */
+ if (!dialog_info->default_button) dialog_info->default_button = dialog_info->buttons[0];
+ SendMessageW(dialog_info->hwnd, WM_NEXTDLGCTL, (WPARAM)dialog_info->default_button, TRUE);
+ id = GetWindowLongW(dialog_info->default_button, GWLP_ID);
+ SendMessageW(dialog_info->hwnd, DM_SETDEFID, id, 0);
taskdialog_layout(dialog_info);
}
@@ -653,6 +606,7 @@ 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);
+ if (dialog_info->buttons) Free(dialog_info->buttons);
}
static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -678,7 +632,7 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
taskdialog_notify(dialog_info, TDN_CREATED, 0, 0);
- break;
+ return FALSE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
--
2.17.1
June 12, 2018
[PATCH 6/8] comctl32/taskdialog: Create content without templates.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 30 ++++++++----------------------
1 file changed, 8 insertions(+), 22 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 46a4ce1a1d..d71189d4de 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -50,8 +50,6 @@ static const UINT DIALOG_BUTTON_WIDTH = 50;
static const UINT DIALOG_BUTTON_HEIGHT = 14;
static const UINT DIALOG_TIMER_MS = 200;
-static const UINT ID_CONTENT = 0xf001;
-
static const UINT ID_TIMER = 1;
struct taskdialog_control
@@ -85,6 +83,7 @@ struct taskdialog_info
HFONT main_instruction_font;
/* Control handles */
HWND main_instruction;
+ HWND content;
/* Dialog metrics */
struct
{
@@ -156,22 +155,6 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
return ALIGNED_LENGTH(size, 3);
}
-static unsigned int taskdialog_add_static_label(struct taskdialog_template_desc *desc, WORD id, const WCHAR *str)
-{
- unsigned int size;
-
- if (!str)
- return 0;
-
- size = taskdialog_add_control(desc, id, WC_STATICW, desc->taskconfig->hInstance, str, 0);
- return size;
-}
-
-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)
{
@@ -329,7 +312,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
desc.control_count = 0;
desc.default_button = NULL;
- size += taskdialog_add_content(&desc);
size += taskdialog_add_buttons(&desc);
template = Alloc(size);
@@ -463,6 +445,11 @@ static void taskdialog_add_main_instruction(struct taskdialog_info *dialog_info)
taskdialog_create_label(dialog_info, taskconfig->pszMainInstruction, dialog_info->main_instruction_font);
}
+static void taskdialog_add_content(struct taskdialog_info *dialog_info)
+{
+ dialog_info->content = taskdialog_create_label(dialog_info, dialog_info->taskconfig->pszContent, dialog_info->font);
+}
+
static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hwnd, INT start_x, LONG dialog_width,
LONG *dialog_height)
{
@@ -484,7 +471,6 @@ 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;
@@ -508,8 +494,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
taskdialog_label_layout(dialog_info, dialog_info->main_instruction, 0, dialog_width, &dialog_height);
/* Content */
- hwnd = GetDlgItem(dialog_info->hwnd, ID_CONTENT);
- taskdialog_label_layout(dialog_info, hwnd, 0, dialog_width, &dialog_height);
+ taskdialog_label_layout(dialog_info, dialog_info->content, 0, dialog_width, &dialog_height);
/* Common and custom buttons */
/* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
@@ -658,6 +643,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
}
taskdialog_add_main_instruction(dialog_info);
+ taskdialog_add_content(dialog_info);
taskdialog_layout(dialog_info);
}
--
2.17.1
June 12, 2018
[PATCH 5/8] comctl32/taskdialog: Create main instruction without templates.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 90 ++++++++++++++++++++++++++------------
1 file changed, 62 insertions(+), 28 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index bd9e68b604..46a4ce1a1d 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -50,7 +50,6 @@ static const UINT DIALOG_BUTTON_WIDTH = 50;
static const UINT DIALOG_BUTTON_HEIGHT = 14;
static const UINT DIALOG_TIMER_MS = 200;
-static const UINT ID_MAIN_INSTRUCTION = 0xf000;
static const UINT ID_CONTENT = 0xf001;
static const UINT ID_TIMER = 1;
@@ -84,6 +83,8 @@ struct taskdialog_info
DWORD last_timer_tick;
HFONT font;
HFONT main_instruction_font;
+ /* Control handles */
+ HWND main_instruction;
/* Dialog metrics */
struct
{
@@ -114,24 +115,6 @@ static void template_write_data(char **ptr, const void *src, unsigned int size)
*ptr += size;
}
-static void taskdialog_set_main_instruction_font(struct taskdialog_info *dialog_info)
-{
- NONCLIENTMETRICSW ncm;
- HWND hwnd;
-
- hwnd = GetDlgItem(dialog_info->hwnd, ID_MAIN_INSTRUCTION);
- if(!hwnd) return;
-
- ncm.cbSize = sizeof(ncm);
- SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
- /* 1.25 times the height */
- ncm.lfMessageFont.lfHeight = ncm.lfMessageFont.lfHeight * 5 / 4;
- ncm.lfMessageFont.lfWeight = FW_BOLD;
- dialog_info->main_instruction_font = CreateFontIndirectW(&ncm.lfMessageFont);
-
- SendMessageW(hwnd, WM_SETFONT, (WPARAM)dialog_info->main_instruction_font, TRUE);
-}
-
static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc, WORD id, const WCHAR *class,
HINSTANCE hInstance, const WCHAR *text, DWORD style)
{
@@ -184,11 +167,6 @@ static unsigned int taskdialog_add_static_label(struct taskdialog_template_desc
return size;
}
-static unsigned int taskdialog_add_main_instruction(struct taskdialog_template_desc *desc)
-{
- return taskdialog_add_static_label(desc, ID_MAIN_INSTRUCTION, desc->taskconfig->pszMainInstruction);
-}
-
static unsigned int taskdialog_add_content(struct taskdialog_template_desc *desc)
{
return taskdialog_add_static_label(desc, ID_CONTENT, desc->taskconfig->pszContent);
@@ -351,7 +329,6 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
desc.control_count = 0;
desc.default_button = NULL;
- size += taskdialog_add_main_instruction(&desc);
size += taskdialog_add_content(&desc);
size += taskdialog_add_buttons(&desc);
@@ -404,6 +381,30 @@ static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD
EndDialog(dialog_info->hwnd, command_id);
}
+static WCHAR *taskdialog_gettext(struct taskdialog_info *dialog_info, BOOL user_resource, const WCHAR *text)
+{
+ const WCHAR *textW = NULL;
+ INT length;
+ WCHAR *ret;
+
+ if (IS_INTRESOURCE(text))
+ {
+ if (!(length = LoadStringW(user_resource ? dialog_info->taskconfig->hInstance : COMCTL32_hModule,
+ (UINT_PTR)text, (WCHAR *)&textW, 0)))
+ return NULL;
+ }
+ else
+ {
+ textW = text;
+ length = strlenW(textW);
+ }
+
+ ret = Alloc((length + 1) * sizeof(WCHAR));
+ if (ret) memcpy(ret, textW, length * sizeof(WCHAR));
+
+ return ret;
+}
+
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;
@@ -429,6 +430,39 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
ReleaseDC(hwnd, hdc);
}
+static HWND taskdialog_create_label(struct taskdialog_info *dialog_info, const WCHAR *text, HFONT font)
+{
+ WCHAR *textW;
+ HWND hwnd;
+
+ if (!text) return NULL;
+
+ textW = taskdialog_gettext(dialog_info, TRUE, text);
+ hwnd = CreateWindowW(WC_STATICW, textW, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, dialog_info->hwnd, NULL, 0, NULL);
+ if (textW) Free(textW);
+
+ SendMessageW(hwnd, WM_SETFONT, (WPARAM)font, 0);
+ return hwnd;
+}
+
+static void taskdialog_add_main_instruction(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ NONCLIENTMETRICSW ncm;
+
+ if (!taskconfig->pszMainInstruction) return;
+
+ ncm.cbSize = sizeof(ncm);
+ SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
+ /* 1.25 times the height */
+ ncm.lfMessageFont.lfHeight = ncm.lfMessageFont.lfHeight * 5 / 4;
+ ncm.lfMessageFont.lfWeight = FW_BOLD;
+ dialog_info->main_instruction_font = CreateFontIndirectW(&ncm.lfMessageFont);
+
+ dialog_info->main_instruction =
+ taskdialog_create_label(dialog_info, taskconfig->pszMainInstruction, dialog_info->main_instruction_font);
+}
+
static void taskdialog_label_layout(struct taskdialog_info *dialog_info, HWND hwnd, INT start_x, LONG dialog_width,
LONG *dialog_height)
{
@@ -471,8 +505,7 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
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);
+ taskdialog_label_layout(dialog_info, dialog_info->main_instruction, 0, dialog_width, &dialog_height);
/* Content */
hwnd = GetDlgItem(dialog_info->hwnd, ID_CONTENT);
@@ -624,7 +657,8 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
dialog_info->last_timer_tick = GetTickCount();
}
- taskdialog_set_main_instruction_font(dialog_info);
+ taskdialog_add_main_instruction(dialog_info);
+
taskdialog_layout(dialog_info);
}
--
2.17.1
June 12, 2018
[PATCH 4/8] comctl32/taskdialog: Support dynamic layout.
by Zhiyi Zhang
Support dynamic layout since some controls might change
their own layout after creation.
Signed-off-by: Zhiyi Zhang <zzhang(a)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
June 12, 2018
[PATCH 3/8] comctl32/taskdialog: Add taskdialog_destroy().
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 7424467af1..549c7f2bf9 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -573,6 +573,12 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
taskdialog_set_main_instruction_font(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->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
+}
+
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};
@@ -618,10 +624,7 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
case WM_DESTROY:
taskdialog_notify(dialog_info, TDN_DESTROYED, 0, 0);
RemovePropW(hwnd, taskdialog_info_propnameW);
- if (dialog_info->taskconfig->dwFlags & TDF_CALLBACK_TIMER)
- KillTimer(hwnd, ID_TIMER);
- if (dialog_info->main_instruction_font)
- DeleteObject(dialog_info->main_instruction_font);
+ taskdialog_destroy(dialog_info);
break;
default:
return FALSE;
--
2.17.1
June 12, 2018
[PATCH 2/8] comctl32/taskdialog: Remove unused parameter.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 56133ffb89..7424467af1 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -430,7 +430,7 @@ static unsigned int taskdialog_get_reference_rect(const struct taskdialog_templa
return info.rcWork.right - info.rcWork.left;
}
-static WCHAR *taskdialog_get_exe_name(const TASKDIALOGCONFIG *taskconfig, WCHAR *name, DWORD length)
+static WCHAR *taskdialog_get_exe_name(WCHAR *name, DWORD length)
{
DWORD len = GetModuleFileNameW(NULL, name, length);
if (len && len < length)
@@ -461,11 +461,11 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
/* Window title */
if (!taskconfig->pszWindowTitle)
- titleW = taskdialog_get_exe_name(taskconfig, pathW, ARRAY_SIZE(pathW));
+ titleW = taskdialog_get_exe_name(pathW, ARRAY_SIZE(pathW));
else if (IS_INTRESOURCE(taskconfig->pszWindowTitle))
{
if (!LoadStringW(taskconfig->hInstance, LOWORD(taskconfig->pszWindowTitle), (WCHAR *)&titleW, 0))
- titleW = taskdialog_get_exe_name(taskconfig, pathW, ARRAY_SIZE(pathW));
+ titleW = taskdialog_get_exe_name(pathW, ARRAY_SIZE(pathW));
}
else
titleW = taskconfig->pszWindowTitle;
--
2.17.1
June 12, 2018
[PATCH 1/8] comctl32/taskdialog: Zero out taskdialog_info at initialization.
by Zhiyi Zhang
Zero init taskdialog_info to avoid garbage values.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 346a079ab6..56133ffb89 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -560,6 +560,8 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
{
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ memset(dialog_info, 0, sizeof(*dialog_info));
+ dialog_info->taskconfig = taskconfig;
dialog_info->hwnd = hwnd;
if (taskconfig->dwFlags & TDF_CALLBACK_TIMER)
--
2.17.1
June 12, 2018