[08/18] comctl32: TaskDialog - Implement buttons
Fabian Maurer
dark.shadow4 at web.de
Fri Feb 24 14:04:02 CST 2017
They are properly placed but aren't working yet.
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/comctl32/taskdialog.c | 158 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 152 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 9297264ad4..3d6b99000c 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -34,6 +34,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
+#define MIN_SIZE_BUTTON 30
+
typedef struct
{
DLGITEMTEMPLATE template;
@@ -58,6 +60,15 @@ typedef struct
UINT titleSize; /* Length in bytes including null-terminator */
}dialog_header;
+typedef struct
+{
+ int id;
+ const WCHAR *text;
+ UINT width;
+ UINT x;
+ UINT y;
+}button_info;
+
#define MEMCPY_MOVEPTR(target, source, size) memcpy(target, source, size); target += size;
#define STR_SIZE(str) ((lstrlenW(str) + 1) * sizeof(WCHAR))
@@ -187,7 +198,7 @@ static void controls_destroy(struct list *controls)
}
/* Adds a control for the TaskDialog into our list */
-static void controls_add(struct list *controls, WORD id, const WCHAR *class, const WCHAR *text,
+static DLGITEMTEMPLATE* controls_add(struct list *controls, WORD id, const WCHAR *class, const WCHAR *text,
DWORD style, short x, short y, short cx, short cy)
{
control_info *data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(control_info));
@@ -205,6 +216,8 @@ static void controls_add(struct list *controls, WORD id, const WCHAR *class, con
data->text_size = STR_SIZE(text);
list_add_tail(controls, &data->entry);
+
+ return &data->template;
}
/* used to calculate size for the static controls */
@@ -241,6 +254,30 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
case WM_INITDIALOG:
PostMessageW(GetDlgItem(hwndDlg, ID_TEXTMAIN), WM_SETFONT, (WPARAM)font_main, TRUE);
PostMessageW(GetDlgItem(hwndDlg, ID_TEXTCONTENT), WM_SETFONT, (WPARAM)font_default, TRUE);
+
+ if(task_config->dwCommonButtons & TDCBF_OK_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDOK), WM_SETFONT, (WPARAM)font_default, TRUE);
+ if(task_config->dwCommonButtons & TDCBF_YES_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDYES), WM_SETFONT, (WPARAM)font_default, TRUE);
+ if(task_config->dwCommonButtons & TDCBF_NO_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDNO), WM_SETFONT, (WPARAM)font_default, TRUE);
+ if(task_config->dwCommonButtons & TDCBF_CANCEL_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDCANCEL), WM_SETFONT, (WPARAM)font_default, TRUE);
+ if(task_config->dwCommonButtons & TDCBF_RETRY_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDRETRY), WM_SETFONT, (WPARAM)font_default, TRUE);
+ if(task_config->dwCommonButtons & TDCBF_CLOSE_BUTTON)
+ PostMessageW(GetDlgItem(hwndDlg, IDCLOSE), WM_SETFONT, (WPARAM)font_default, TRUE);
+
+ if(task_config->cButtons && task_config->pButtons)
+ {
+ int i;
+ for(i=0; i< task_config->cButtons; i++)
+ {
+ PostMessageW(GetDlgItem(hwndDlg, task_config->pButtons[i].nButtonID),
+ WM_SETFONT, (WPARAM)font_default, TRUE);
+ }
+ }
+
callback(hwndDlg, TDN_DIALOG_CONSTRUCTED, 0, 0);
callback(hwndDlg, TDN_CREATED, 0, 0);
@@ -275,6 +312,118 @@ static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
return FALSE;
}
+static button_info make_button(HDC hdc, UINT dialog_width, int id, const WCHAR *text)
+{
+ RECT rect;
+ button_info button;
+
+ button.id = id;
+ button.text = text;
+ rect = text_get_rect(hdc, text, dialog_width);
+ button.width = rect.right + 10;
+ if(button.width < MIN_SIZE_BUTTON)
+ button.width = MIN_SIZE_BUTTON;
+
+ return button;
+}
+
+static UINT add_buttons(HDC hdc, const TASKDIALOGCONFIG *pTaskConfig, struct list *controls,
+ UINT dialog_width, UINT dialog_height)
+{
+ static const WCHAR class_button[] = {'B','u','t','t','o','n',0};
+ static const WCHAR text_ok[] = {'O','K',0};
+ static const WCHAR text_yes[] = {'Y','e','s',0};
+ static const WCHAR text_no[] = {'N','o',0};
+ static const WCHAR text_cancel[] = {'C','a','n','c','e','l',0};
+ static const WCHAR text_retry[] = {'R','e','t','r','y',0};
+ static const WCHAR text_close[] = {'C','l','o','s','e',0};
+ UINT alignment = 40; /* minimum distance from the left dialog border */
+ UINT location_x;
+ BOOL first_row = TRUE;
+ button_info *buttons;
+ int count = 0;
+ int i;
+
+ /* Allocate enough memory for the custom and the default buttons */
+ if(pTaskConfig->cButtons && pTaskConfig->pButtons)
+ buttons = HeapAlloc(GetProcessHeap(), 0, (pTaskConfig->cButtons + 6)*sizeof(button_info));
+ else
+ {
+ buttons = HeapAlloc(GetProcessHeap(), 0, 6*sizeof(button_info));
+ }
+
+ /* Custom buttons */
+ if(pTaskConfig->cButtons && pTaskConfig->pButtons)
+ {
+ for(i=0; i<pTaskConfig->cButtons; i++)
+ {
+ buttons[count++] = make_button(hdc, dialog_width, pTaskConfig->pButtons[i].nButtonID,
+ pTaskConfig->pButtons[i].pszButtonText);
+ }
+ }
+
+ /* Default buttons */
+ if(pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDOK, text_ok);
+ if(pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDYES, text_yes);
+ if(pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDNO, text_no);
+ if(pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDRETRY, text_retry);
+ if(pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDCANCEL, text_cancel);
+ if(pTaskConfig->dwCommonButtons & TDCBF_CLOSE_BUTTON)
+ buttons[count++] = make_button(hdc, dialog_width, IDCLOSE, text_close);
+
+ /* There must be at least one button */
+ if(!(pTaskConfig->cButtons && pTaskConfig->pButtons) && !pTaskConfig->dwCommonButtons)
+ buttons[count++] = make_button(hdc, dialog_width, IDOK, text_ok);
+
+ /* Position buttons */
+ location_x = alignment;
+ for(i=0; i<count; i++)
+ {
+ if(location_x + buttons[i].width + 4 > dialog_width) /* When beginning new row, align the first */
+ {
+ if(first_row)
+ {
+ int diff = dialog_width - location_x;
+
+ first_row = FALSE;
+ for(int j=0; j<i; j++) /* Align first row to the right */
+ buttons[j].x += diff;
+ alignment = buttons[0].x; /* left-align all coming rows to the first row */
+ }
+ location_x = alignment;
+ dialog_height += 11;
+ }
+
+ buttons[i].x = location_x;
+ buttons[i].y = dialog_height;
+
+ location_x += buttons[i].width + 4;
+ }
+ if(first_row) /* Always align first row to the right */
+ {
+ int diff = dialog_width -(buttons[count-1].x + buttons[count-1].width + 4) ;
+ for(int i=0; i<count; i++)
+ buttons[i].x += diff;
+ }
+
+ /* 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, 10);
+ }
+
+ dialog_height += 20;
+
+ HeapFree(GetProcessHeap(), 0, buttons);
+ return dialog_height;
+}
+
/***********************************************************************
* TaskDialogIndirect [COMCTL32.@]
*/
@@ -283,9 +432,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
{
static const WCHAR empty_string[] = {0};
static const WCHAR font_name[] = {'T','a','h','o','m','a',0};
- static const WCHAR class_button[] = {'B','u','t','t','o','n',0};
static const WCHAR class_static[] = {'S','t','a','t','i','c',0};
- static const WCHAR text_ok[] = {'O','K',0};
RECT desktop;
UINT dialog_width; /* In dialog units */
UINT dialog_height; /* In dialog units */
@@ -348,9 +495,8 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnBu
dialog_height += rect.bottom + 10;
}
- controls_add(controls, IDOK, class_button, text_ok,
- WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, dialog_width - 40 - 10, dialog_height + 5, 40, 10);
- dialog_height += 10 + 10;
+ /* Create buttons */
+ dialog_height = add_buttons(dc_dummy, pTaskConfig, controls, dialog_width, dialog_height);
header.title = pTaskConfig->pszWindowTitle;
if(!header.title)
--
2.11.1
More information about the wine-patches
mailing list