[18/18] comctl32: TaskDialog - Add ability to cancel dialog
Fabian Maurer
dark.shadow4 at web.de
Fri Feb 24 14:04:12 CST 2017
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/comctl32/taskdialog.c | 28 ++++++++++++--
dlls/comctl32/tests/taskdialog.c | 81 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 829102a07d..6057468793 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -76,6 +76,7 @@ typedef struct
HFONT font_default;
HFONT font_main;
HWND hwnd;
+ BOOL has_cancel;
}taskdialog_info;
struct list taskdialogs = LIST_INIT(taskdialogs);
@@ -259,6 +260,10 @@ static void taskdialog_info_init(taskdialog_info **taskdialog, const TASKDIALOGC
dialog->font_main = CreateFontW (19, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, FF_DONTCARE, font_name);
+ dialog->has_cancel = (pTaskConfig->dwFlags & TDF_ALLOW_DIALOG_CANCELLATION)
+ || (pTaskConfig->dwFlags & TDF_CAN_BE_MINIMIZED)
+ || (pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON);
+
*taskdialog = dialog;
}
@@ -316,12 +321,15 @@ static HRESULT callback(taskdialog_info *dialog, UINT uNotification, WPARAM wPar
static void click_button(HWND hwndDlg, taskdialog_info *dialog, WORD command_id)
{
- HRESULT ret_callback = callback(dialog, TDN_BUTTON_CLICKED, command_id, 0);
+ HRESULT ret_callback;
+
+ if(command_id == IDCANCEL && !dialog->has_cancel)
+ return TRUE;
+
+ ret_callback = callback(dialog, TDN_BUTTON_CLICKED, command_id, 0);
if(ret_callback == S_OK)
{
EndDialog(hwndDlg, command_id);
-
- callback(dialog, TDN_DESTROYED, 0, 0);
}
}
@@ -398,6 +406,12 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
case WM_HELP:
callback(dialog, TDN_HELP, 0, 0);
return TRUE;
+ case WM_DESTROY:
+ callback(dialog, TDN_DESTROYED, 0, 0);
+ return FALSE;
+ case WM_CLOSE:
+ click_button(hwndDlg, dialog, IDCANCEL);
+ return FALSE;
/* Custom messages*/
@@ -613,7 +627,12 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
header.title = empty_string; /* FIXME: Set to exe path instead */
header.titleSize = STR_SIZE(header.title);
- header.template.style = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE;
+ header.template.style = DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE;
+ if(dialog->has_cancel)
+ header.template.style |= WS_SYSMENU;
+ if(pTaskConfig->dwFlags & TDF_CAN_BE_MINIMIZED)
+ header.template.style |= WS_SYSMENU | WS_MINIMIZEBOX;
+
header.template.cdit = list_count(controls);
/* TaskDialogs are always desktop centered */
@@ -622,6 +641,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
header.template.x = (desktop.right - dialog_width)/2;
header.template.y = (desktop.bottom - dialog_height)/2;
+
/* Turn template information into a dialog template to display it */
template_data = dialog_template_create(header, controls);
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index 7d6429c9c6..95ffe50eea 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -137,6 +137,15 @@ static const message_data mes_help[] = {
{ TDN_NO_MORE_MESSAGES }
};
+static const message_data mes_cancel_ok_button_press[] = {
+ { TDN_DIALOG_CONSTRUCTED, 0, 0 },
+ { TDN_CREATED, 0, 0 },
+ { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, 1 },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK },
+ { TDN_DESTROYED, 0, 0 },
+ { TDN_NO_MORE_MESSAGES }
+};
+
/* Message lists to send */
static const message_send_data mes_send_return[] = {
@@ -201,6 +210,40 @@ static const message_send_data mes_send_F1[] = {
{ 0 }
};
+static const message_send_data mes_send_esc[] = {
+ { WM_KEYDOWN, VK_ESCAPE, 0 },
+ { 0 }
+};
+
+static const message_send_data mes_send_close[] = {
+ { WM_CLOSE, 0, 0 },
+ { 0 }
+};
+
+static const message_send_data mes_send_esc_return[] = {
+ { WM_KEYDOWN, VK_ESCAPE, 0 },
+ { WM_KEYDOWN, VK_RETURN, 0 },
+ { 0 }
+};
+
+static const message_send_data mes_send_close_return[] = {
+ { WM_CLOSE, 0, 0 },
+ { WM_KEYDOWN, VK_RETURN, 0 },
+ { 0 }
+};
+
+static const message_send_data mes_send_esc_ok_cancel[] = {
+ { WM_KEYDOWN, VK_ESCAPE, 0, NULL, SEND_SYNCRONIZED },
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const message_send_data mes_send_close_ok_cancel[] = {
+ { WM_CLOSE, 0, 0, NULL, SEND_SYNCRONIZED },
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
/* Our only way to get a button handle, since GetDlgItem and FindWindowEx don't work for the official taskdialog */
static HWND taskdialog_child;
@@ -531,6 +574,44 @@ static void test_TaskDialogIndirect(void)
/* Test TDM_HELP */
run_test(&info, IDOK, 0, 0, mes_help, mes_send_F1);
+
+ /* Test ability to cancel dialog */
+
+ /* Test with TDF_ALLOW_DIALOG_CANCELLATION and without cancel button */
+ info.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_esc);
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_close);
+
+ /* Test with TDF_ALLOW_DIALOG_CANCELLATION and without cancel button */
+ info.dwFlags = TDF_CAN_BE_MINIMIZED;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_esc);
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_close);
+
+ /* Test without allow-cancel flag and with cancel button */
+ info.dwFlags = 0;
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_esc);
+ run_test(&info, IDCANCEL, 0, 0, mes_button_clicked_cancel, mes_send_close);
+
+ /* Test without allow-cancel flag and without cancel button */
+ info.dwFlags = 0;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ run_test(&info, IDOK, 0, 0, mes_button_clicked_ok, mes_send_esc_return);
+ run_test(&info, IDOK, 0, 0, mes_button_clicked_ok, mes_send_close_return);
+
+ /* Test if the callback can disable the cancellation with cancel button */
+ info.dwFlags = 0;
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;
+ run_test(&info, IDOK, 0, 0, mes_cancel_ok_button_press, mes_send_esc_ok_cancel);
+ run_test(&info, IDOK, 0, 0, mes_cancel_ok_button_press, mes_send_close_ok_cancel);
+
+ /* Test if the callback can disable the cancellation without cancel button */
+ info.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ run_test(&info, IDOK, 0, 0, mes_cancel_ok_button_press, mes_send_esc_ok_cancel);
+ run_test(&info, IDOK, 0, 0, mes_cancel_ok_button_press, mes_send_close_ok_cancel);
}
START_TEST(taskdialog)
--
2.11.1
More information about the wine-patches
mailing list