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