Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/comctl32/taskdialog.c | 17 ++++++++++ dlls/comctl32/tests/taskdialog.c | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c index c6a3aa7ae5..efe159f891 100644 --- a/dlls/comctl32/taskdialog.c +++ b/dlls/comctl32/taskdialog.c @@ -1142,8 +1142,16 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd) taskdialog_layout(dialog_info); }
+static BOOL CALLBACK takdialog_destroy_control(HWND hwnd, LPARAM lParam) +{ + DestroyWindow(hwnd); + return TRUE; +} + static void taskdialog_destroy(struct taskdialog_info *dialog_info) { + EnumChildWindows(dialog_info->hwnd, takdialog_destroy_control, 0); + 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); @@ -1167,6 +1175,15 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
switch (msg) { + case TDM_NAVIGATE_PAGE: + dialog_info->taskconfig = (const TASKDIALOGCONFIG *)lParam; + taskdialog_destroy(dialog_info); + taskdialog_init(dialog_info, hwnd); + taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0); + /* Default radio button click notification is sent before TDN_NAVIGATED */ + taskdialog_check_default_radio_buttons(dialog_info); + taskdialog_notify(dialog_info, TDN_NAVIGATED, 0, 0); + break; case TDM_CLICK_BUTTON: taskdialog_click_button(dialog_info, wParam); break; diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c index 8d60fb2eb8..093671c30f 100644 --- a/dlls/comctl32/tests/taskdialog.c +++ b/dlls/comctl32/tests/taskdialog.c @@ -271,6 +271,25 @@ static const struct message_info msg_return_verification_checked[] = { 0 } };
+static TASKDIALOGCONFIG navigated_info = {0}; + +static const struct message_info msg_send_navigate[] = +{ + { TDM_NAVIGATE_PAGE, 0, (LPARAM)&navigated_info, 0}, + { 0 } +}; + +static const struct message_info msg_return_navigated_page[] = +{ + { TDN_CREATED, 0, 0, S_OK, NULL }, + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_navigate }, + { TDN_DIALOG_CONSTRUCTED, 0, 0, S_OK, NULL }, + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL }, + { TDN_NAVIGATED, 0, 0, S_OK, msg_send_click_ok }, + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL }, + { 0 } +}; + static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg) { msg->message = WM_TD_CALLBACK; @@ -682,6 +701,44 @@ static void test_verification_box(void) "default verification box: default unchecked and then checked"); }
+static void test_navigate_page(void) +{ + TASKDIALOGCONFIG info = {0}; + static const WCHAR textW[] = {'t', 'e', 'x', 't', 0}; + static const WCHAR button_format[] = {'%', '0', '2', 'd', 0}; + TASKDIALOG_BUTTON radio_buttons[TEST_NUM_RADIO_BUTTONS]; + WCHAR radio_button_titles[TEST_NUM_BUTTONS * 3]; + int i; + + /* Init radio buttons */ + for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++) + { + WCHAR *text = &radio_button_titles[i * 3]; + wsprintfW(text, button_format, i); + + radio_buttons[i].pszButtonText = text; + radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i; + } + + info.cbSize = sizeof(TASKDIALOGCONFIG); + info.pfCallback = taskdialog_callback_proc; + info.lpCallbackData = test_ref_data; + info.dwCommonButtons = TDCBF_OK_BUTTON; + info.cRadioButtons = TEST_NUM_RADIO_BUTTONS; + info.pRadioButtons = radio_buttons; + + navigated_info = info; + navigated_info.pszVerificationText = textW; + navigated_info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED; + + run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: default"); + + /* TDM_NAVIGATE_PAGE doesn't check cbSize. + * And null taskconfig pointer crash applicatioin, thus doesn't check pointer either */ + navigated_info.cbSize = 0; + run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page, "navigate page: invalid taskconfig cbSize"); +} + START_TEST(taskdialog) { ULONG_PTR ctx_cookie; @@ -722,6 +779,7 @@ START_TEST(taskdialog) test_timer(); test_progress_bar(); test_verification_box(); + test_navigate_page();
unload_v6_module(ctx_cookie, hCtx); }