From: Fabian Maurer Subject: [08/18] comctl32: TaskDialog - Implement buttons Message-Id: <20170224200412.12968-8-dark.shadow4@web.de> Date: Fri, 24 Feb 2017 21:04:02 +0100 In-Reply-To: <20170224200412.12968-1-dark.shadow4@web.de> References: <20170224200412.12968-1-dark.shadow4@web.de> They are properly placed but aren't working yet. Signed-off-by: Fabian Maurer --- 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; icButtons; 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 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; jpszWindowTitle; if(!header.title) -- 2.11.1