[v3 11/12] comctl32: TaskDialog - Set default button and add tests

Fabian Maurer dark.shadow4 at web.de
Fri Mar 10 12:22:03 CST 2017


v3: Rewrite to implement Nikolay Sivov's suggestions

Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
 dlls/comctl32/taskdialog.c       | 19 +++++++--
 dlls/comctl32/tests/taskdialog.c | 85 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 4a510eb247..47ade8f2f6 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -366,7 +366,7 @@ static button_info make_button(HDC hdc, UINT dialog_width, int id, const WCHAR *
 }
 
 static UINT add_buttons(HDC hdc, const TASKDIALOGCONFIG *task_config, struct list *controls,
-                        UINT dialog_width, UINT dialog_height)
+                        UINT dialog_width, UINT dialog_height, int default_button)
 {
     static const WCHAR class_button[] = WC_BUTTONW; /* Can't use WC_BUTTONW directy, need to store it into a static variable since it goes out of scope */
     static WCHAR text_ok    [20] = {0};
@@ -379,6 +379,7 @@ static UINT add_buttons(HDC hdc, const TASKDIALOGCONFIG *task_config, struct lis
     UINT alignment = DIALOG_SPACING_BUTTONS_LEFT; /* minimum distance from the left dialog border */
     UINT location_x;
     BOOL first_row = TRUE;
+    BOOL found_default = FALSE; /* Whether the default button ID is valid or not */
     button_info *buttons;
     int count = 0;
     int i;
@@ -461,11 +462,21 @@ static UINT add_buttons(HDC hdc, const TASKDIALOGCONFIG *task_config, struct lis
             buttons[i].x += diff;
     }
 
+    for(i=0; i<count; i++)
+        if(buttons[i].id == default_button)
+            found_default = TRUE;
+
      /* Now that we got them all positioned, create all buttons */
     for(i=0; i<count; i++)
     {
-        controls_add(controls, buttons[i].id, class_button, buttons[i].text, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
-                                buttons[i].x, buttons[i].y, buttons[i].width, DIALOG_BUTTON_HEIGHT);
+        DWORD style = 0;
+        if((!found_default && i==0) || buttons[i].id == default_button)
+            style = BS_DEFPUSHBUTTON;
+        else
+            style = BS_PUSHBUTTON;
+
+        controls_add(controls, buttons[i].id, class_button, buttons[i].text, WS_CHILD | WS_VISIBLE | style,
+                               buttons[i].x, buttons[i].y, buttons[i].width, DIALOG_BUTTON_HEIGHT);
     }
 
     dialog_height += DIALOG_BUTTON_HEIGHT*2;
@@ -542,7 +553,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
     dialog_height += DIALOG_SPACING;
 
     /* Create buttons */
-    dialog_height = add_buttons(dc_dummy, pTaskConfig, &controls, dialog_width, dialog_height);
+    dialog_height = add_buttons(dc_dummy, pTaskConfig, &controls, dialog_width, dialog_height, pTaskConfig->nDefaultButton);
 
     header.title = pTaskConfig->pszWindowTitle;
     if(!header.title)
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index f76624c45d..c29ac89792 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -34,6 +34,12 @@
 #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)
+#define ID_START_RADIO (ID_START + 1000)
+
 static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
 
 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
@@ -64,7 +70,7 @@ struct message_info
 static const struct message_info *current_message_info;
 
 
-static const struct message_info mes_simple_show[] = {
+static const struct message_info mes_return_press_ok[] = {
     { TDN_CREATED, 0, 0, S_OK, {
         { WM_KEYDOWN, VK_RETURN, 0, TRUE },
         { 0 }}},
@@ -84,6 +90,30 @@ static const struct message_info mes_cancel_button_press[] = {
     { 0 }
 };
 
+static const struct message_info mes_return_press_custom1[] = {
+    { TDN_CREATED, 0, 0, S_OK, {
+        { WM_KEYDOWN, VK_RETURN, 0, TRUE },
+        { 0 }}},
+    { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, {{ 0 }}},
+    { 0 }
+};
+
+static const struct message_info mes_return_press_custom4[] = {
+    { TDN_CREATED, 0, 0, S_OK, {
+        { WM_KEYDOWN, VK_RETURN, 0, TRUE },
+        { 0 }}},
+    { TDN_BUTTON_CLICKED, ID_START_BUTTON + 3, 0, S_OK, {{ 0 }}},
+    { 0 }
+};
+
+static const struct message_info mes_return_press_retry[] = {
+    { TDN_CREATED, 0, 0, S_OK, {
+        { WM_KEYDOWN, VK_RETURN, 0, TRUE },
+        { 0 }}},
+    { TDN_BUTTON_CLICKED, IDRETRY, 0, S_OK, {{ 0 }}},
+    { 0 }
+};
+
 
 /* Create a message to test against */
 static struct message create_test_message(UINT message, WPARAM wParam, LPARAM lParam)
@@ -206,11 +236,34 @@ static HRESULT CALLBACK TaskDialogCallbackProc(HWND hwnd, UINT uNotification, WP
     return S_OK;
 }
 
+
+
+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_TaskDialogIndirect(void)
 {
     TASKDIALOGCONFIG info = {0};
+    TASKDIALOG_BUTTON *custom_buttons;
     HRESULT ret;
 
+    custom_buttons = buttons_make();
+
     ret = pTaskDialogIndirect(NULL, NULL, NULL, NULL);
     ok(ret == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", ret);
 
@@ -221,8 +274,36 @@ static void test_TaskDialogIndirect(void)
     info.pfCallback = TaskDialogCallbackProc;
     info.lpCallbackData = backup_ref_data = 0x12345678; /* Set data for callback tests */
 
-    run_test(&info, IDOK, 0, FALSE, mes_simple_show, "Simple test with parameters null");
+    run_test(&info, IDOK, 0, FALSE, mes_return_press_ok, "Simple test with parameters null");
     run_test(&info, IDOK, 0, FALSE, mes_cancel_button_press, "Simple test for cancelling button press");
+
+     /* Test nDefaultButton */
+
+    /* Test with all common buttons and 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, FALSE, mes_return_press_ok, "");
+
+    /* 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, FALSE, mes_return_press_custom1, "nDefaultButton: all buttons, invalid default");
+
+    /* Test with only custom buttons and invalid default ID */
+    info.dwCommonButtons = 0;
+    run_test(&info, ID_START_BUTTON, 0, FALSE, mes_return_press_custom1, "nDefaultButton: custom buttons, invalid default");
+
+    /* 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, FALSE, mes_return_press_retry, "nDefaultButton: all buttons, 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, FALSE, mes_return_press_custom4, "nDefaultButton: all buttons, valid default 2");
 }
 
 START_TEST(taskdialog)
-- 
2.12.0




More information about the wine-patches mailing list