[PATCH] comctl32/taskdialog: Implement nDefaultButton and add tests
Fabian Maurer
dark.shadow4 at web.de
Sat Nov 4 10:22:10 CDT 2017
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/comctl32/taskdialog.c | 21 +++++--
dlls/comctl32/tests/taskdialog.c | 115 +++++++++++++++++++++++++++++++++++++++
2 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 5c4af2ab03..4f80311a61 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -151,7 +151,7 @@ static void taskdialog_get_text_extent(const struct taskdialog_template_desc *de
}
static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc, WORD id, const WCHAR *class,
- HINSTANCE hInstance, const WCHAR *text, short x, short y, short cx, short cy)
+ HINSTANCE hInstance, const WCHAR *text, DWORD style, short x, short y, short cx, short cy)
{
struct taskdialog_control *control = Alloc(sizeof(*control));
unsigned int size, class_size, text_size;
@@ -178,7 +178,7 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
control->template = template = Alloc(size);
control->template_size = size;
- template->style = WS_VISIBLE;
+ template->style = WS_VISIBLE | style;
template->dwExtendedStyle = 0;
template->x = x;
template->y = y;
@@ -206,7 +206,7 @@ static unsigned int taskdialog_add_static_label(struct taskdialog_template_desc
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, 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;
@@ -268,6 +268,7 @@ static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc
unsigned int location_x, *line_widths, alignment = ~0u;
const TASKDIALOGCONFIG *taskconfig = desc->taskconfig;
struct taskdialog_button_desc *buttons;
+ int default_button;
/* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
buttons_size = 6;
@@ -340,18 +341,26 @@ static unsigned int taskdialog_add_buttons(struct taskdialog_template_desc *desc
alignment = new_alignment;
}
+ /* Check if the default button is actually valid, if no default to the first created button */
+ default_button = buttons[0].id;
+ for (i = 0; i < count; i++)
+ if (buttons[i].id == taskconfig->nDefaultButton)
+ default_button = taskconfig->nDefaultButton;
+
/* Now that we got them all positioned, create all buttons */
location_x = alignment;
for (i = 0; i < count; i++)
{
+ DWORD style = (buttons[i].id == 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, location_x,
- desc->dialog_height, buttons[i].width, DIALOG_BUTTON_HEIGHT);
+ 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;
}
@@ -583,7 +592,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *butto
Free(template);
if (button) *button = ret;
- if (radio_button) *radio_button = taskconfig->nDefaultButton;
+ if (radio_button) *radio_button = FALSE;
if (verification_flag_checked) *verification_flag_checked = TRUE;
return S_OK;
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index dfb6808c38..589ada548f 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -33,6 +33,11 @@
#define NUM_MSG_SEQUENCES 1
#define TASKDIALOG_SEQ_INDEX 0
+#define TEST_NUM_BUTTONS 20 /* Number of custom buttons to test with */
+
+#define ID_START 20 /* Lower IDs might be used by the system */
+#define ID_START_BUTTON (ID_START + 0)
+
static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
TASKDIALOG_COMMON_BUTTON_FLAGS, const WCHAR *, int *);
@@ -66,6 +71,48 @@ static const struct message_info msg_return_press_ok[] =
{ 0 }
};
+static const struct message_info msg_return_press_yes[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, IDYES, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_no[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, IDNO, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_cancel[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_retry[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, IDRETRY, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_custom1[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_custom4[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_return },
+ { TDN_BUTTON_CLICKED, ID_START_BUTTON + 3, 0, S_OK, NULL },
+ { 0 }
+};
+
static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
{
msg->message = WM_TD_CALLBACK;
@@ -138,6 +185,24 @@ static HRESULT CALLBACK taskdialog_callback_proc(HWND hwnd, UINT notification,
return current_message_info[msg_pos].callback_retval;
}
+static TASKDIALOG_BUTTON* buttons_make(void)
+{
+ static const WCHAR str_format[] = {'%','0','2','d',0};
+ static TASKDIALOG_BUTTON buttons[TEST_NUM_BUTTONS];
+ static WCHAR titles[TEST_NUM_BUTTONS * 3]; /* Each button has two digits as title, plus null-terminator */
+ int i;
+
+ for (i = 0; i < TEST_NUM_BUTTONS; i++)
+ {
+ WCHAR *text = &titles[i * 3];
+ wsprintfW(text, str_format, i);
+
+ buttons[i].pszButtonText = text;
+ buttons[i].nButtonID = ID_START_BUTTON + i;
+ }
+ return buttons;
+}
+
static void test_invalid_parameters(void)
{
TASKDIALOGCONFIG info = { 0 };
@@ -170,6 +235,55 @@ static void test_callback(void)
run_test(&info, IDOK, 0, msg_return_press_ok, "Press VK_RETURN.");
}
+static void test_buttons(void)
+{
+ TASKDIALOG_BUTTON *custom_buttons;
+ TASKDIALOGCONFIG info = {0};
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc;
+ info.lpCallbackData = test_ref_data;
+
+ custom_buttons = buttons_make();
+
+ /* Test nDefaultButton */
+
+ /* Test common buttons with invalid default ID */
+ info.nDefaultButton = 0; /* Should default to first created button */
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
+ | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ run_test(&info, IDOK, 0, msg_return_press_ok, "default button: unset default");
+ info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
+ | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ run_test(&info, IDYES, 0, msg_return_press_yes, "default button: unset default");
+ info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ run_test(&info, IDNO, 0, msg_return_press_no, "default button: unset default");
+ info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: unset default");
+ info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
+ run_test(&info, IDCANCEL, 0, msg_return_press_cancel, "default button: unset default");
+
+ /* Test with all common and custom buttons and invalid default ID */
+ info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
+ info.cButtons = 10;
+ info.pButtons = custom_buttons;
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons");
+
+ /* Test with only custom buttons and invalid default ID */
+ info.dwCommonButtons = 0;
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, no common buttons");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
+ | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ info.nDefaultButton = IDRETRY;
+ run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.nDefaultButton = ID_START_BUTTON + 3;
+ run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
+}
+
START_TEST(taskdialog)
{
ULONG_PTR ctx_cookie;
@@ -205,6 +319,7 @@ START_TEST(taskdialog)
test_invalid_parameters();
test_callback();
+ test_buttons();
unload_v6_module(ctx_cookie, hCtx);
}
--
2.15.0
More information about the wine-patches
mailing list