Zhiyi Zhang : comctl32/taskdialog: Handle button clicks better.
Alexandre Julliard
julliard at winehq.org
Tue Oct 30 14:19:34 CDT 2018
Module: wine
Branch: master
Commit: 589cbf3bcc6fbf6e9415bddd322a8d5810f4c804
URL: https://source.winehq.org/git/wine.git/?a=commit;h=589cbf3bcc6fbf6e9415bddd322a8d5810f4c804
Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date: Mon Oct 29 15:25:43 2018 +0800
comctl32/taskdialog: Handle button clicks better.
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 0adfb2f..5645d53 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 8f4c97b..d25c67f 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)
More information about the wine-cvs
mailing list