Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/comctl32/taskdialog.c | 34 +++++++++----- dlls/comctl32/tests/taskdialog.c | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 12 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c index 0adfb2f32c..5645d53f79 100644 --- a/dlls/comctl32/taskdialog.c +++ b/dlls/comctl32/taskdialog.c @@ -95,7 +95,8 @@ struct button_layout_info LONG line; };
-static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, HWND hwnd); +static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam); +static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, HWND hwnd, WORD id); static void taskdialog_layout(struct taskdialog_info *dialog_info);
static void taskdialog_du_to_px(struct taskdialog_info *dialog_info, LONG *width, LONG *height) @@ -209,9 +210,7 @@ static void taskdialog_enable_button(const struct taskdialog_info *dialog_info,
static void taskdialog_click_button(struct taskdialog_info *dialog_info, INT id) { - HWND hwnd = taskdialog_find_button(dialog_info->command_links, dialog_info->command_link_count, id); - if (!hwnd) hwnd = taskdialog_find_button(dialog_info->buttons, dialog_info->button_count, id); - if (hwnd) taskdialog_on_button_click(dialog_info, hwnd); + if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, id, 0) == S_OK) EndDialog(dialog_info->hwnd, id); }
static void taskdialog_button_set_shield(const struct taskdialog_info *dialog_info, INT id, BOOL elevate) @@ -303,19 +302,22 @@ static void taskdialog_toggle_expando_control(struct taskdialog_info *dialog_inf } }
-static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, HWND hwnd) +static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, HWND hwnd, WORD id) { - INT command_id = GetWindowLongW(hwnd, GWLP_ID); - HWND radio_button; + INT command_id; + HWND button, radio_button; + + /* Prefer the id from hwnd because the id from WM_COMMAND is truncated to WORD */ + command_id = hwnd ? GetWindowLongW(hwnd, GWLP_ID) : id;
- if (hwnd == dialog_info->expando_button) + if (hwnd && hwnd == dialog_info->expando_button) { taskdialog_toggle_expando_control(dialog_info); taskdialog_notify(dialog_info, TDN_EXPANDO_BUTTON_CLICKED, dialog_info->expanded, 0); return; }
- if (hwnd == dialog_info->verification_box) + if (hwnd && hwnd == dialog_info->verification_box) { dialog_info->verification_checked = !dialog_info->verification_checked; taskdialog_notify(dialog_info, TDN_VERIFICATION_CLICKED, dialog_info->verification_checked, 0); @@ -330,7 +332,15 @@ static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, HWND return; }
- if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK) + button = taskdialog_find_button(dialog_info->command_links, dialog_info->command_link_count, command_id); + if (!button) button = taskdialog_find_button(dialog_info->buttons, dialog_info->button_count, command_id); + if (!button && command_id == IDOK) + { + button = dialog_info->command_link_count > 0 ? dialog_info->command_links[0] : dialog_info->buttons[0]; + command_id = GetWindowLongW(button, GWLP_ID); + } + + if (button && taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK) EndDialog(dialog_info->hwnd, command_id); }
@@ -582,7 +592,7 @@ static void taskdialog_check_default_radio_buttons(struct taskdialog_info *dialo if (default_button) { SendMessageW(default_button, BM_SETCHECK, BST_CHECKED, 0); - taskdialog_on_button_click(dialog_info, default_button); + taskdialog_on_button_click(dialog_info, default_button, 0); } }
@@ -1332,7 +1342,7 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { - taskdialog_on_button_click(dialog_info, (HWND)lParam); + taskdialog_on_button_click(dialog_info, (HWND)lParam, LOWORD(wParam)); break; } return FALSE; diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c index 8f4c97b750..d25c67f7bc 100644 --- a/dlls/comctl32/tests/taskdialog.c +++ b/dlls/comctl32/tests/taskdialog.c @@ -229,6 +229,66 @@ static const struct message_info msg_return_press_negative_id_radio_button[] = { 0 } };
+static const struct message_info msg_send_all_common_button_click[] = +{ + { TDM_CLICK_BUTTON, IDOK, 0 }, + { TDM_CLICK_BUTTON, IDYES, 0 }, + { TDM_CLICK_BUTTON, IDNO, 0 }, + { TDM_CLICK_BUTTON, IDCANCEL, 0 }, + { TDM_CLICK_BUTTON, IDRETRY, 0 }, + { TDM_CLICK_BUTTON, IDCLOSE, 0 }, + { TDM_CLICK_BUTTON, ID_START_BUTTON + 99, 0 }, + { 0 } +}; + +static const struct message_info msg_press_nonexistent_buttons[] = +{ + { TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click }, + { TDN_BUTTON_CLICKED, IDOK, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, IDYES, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, IDNO, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, IDRETRY, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, IDCLOSE, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, ID_START_BUTTON + 99, 0, S_OK, NULL }, + { 0 } +}; + +static const struct message_info msg_send_all_common_button_click_with_command[] = +{ + { WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDYES, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDNO, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDCANCEL, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDRETRY, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDCLOSE, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(ID_START_BUTTON + 99, BN_CLICKED), 0 }, + { WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 }, + { 0 } +}; + +static const struct message_info msg_press_nonexistent_buttons_with_command[] = +{ + { TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click_with_command }, + { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_FALSE, NULL }, + { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, NULL }, + { 0 } +}; + +static const struct message_info msg_send_nonexistent_radio_button_click[] = +{ + { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON + 99, 0 }, + { TDM_CLICK_BUTTON, IDOK, 0 }, + { 0 } +}; + +static const struct message_info msg_press_nonexistent_radio_button[] = +{ + { TDN_CREATED, 0, 0, S_OK, msg_send_nonexistent_radio_button_click }, + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL }, + { 0 } +}; + static const struct message_info msg_return_default_verification_unchecked[] = { { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok }, @@ -568,6 +628,23 @@ static void test_buttons(void) info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON; run_test(&info, IDOK, -2, FALSE, msg_return_press_negative_id_radio_button, "radio button: manually click radio button with negative id"); + + /* Test sending clicks to non-existent buttons. Notification of non-existent buttons will be sent */ + info.cButtons = TEST_NUM_BUTTONS; + info.pButtons = custom_buttons; + info.cRadioButtons = TEST_NUM_RADIO_BUTTONS; + info.pRadioButtons = radio_buttons; + info.dwCommonButtons = 0; + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON; + run_test(&info, ID_START_BUTTON + 99, 0, FALSE, msg_press_nonexistent_buttons, "sends click to non-existent buttons"); + + /* Non-existent button clicks sent by WM_COMMAND won't generate TDN_BUTTON_CLICKED except IDOK. + * And will get the first existent button identifier instead of IDOK */ + run_test(&info, ID_START_BUTTON, 0, FALSE, msg_press_nonexistent_buttons_with_command, + "sends click to non-existent buttons with WM_COMMAND"); + + /* Non-existent radio button won't get notifications */ + run_test(&info, IDOK, 0, FALSE, msg_press_nonexistent_radio_button, "sends click to non-existent radio buttons"); }
static void test_help(void)