// XTPTaskDialogClient.cpp: implementation of the CXTPTaskDialogClient class. // // This file is a part of the XTREME CONTROLS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "../Resource.h" #include "Common/XTPImageManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPResourceManager.h" #include "Common/XTPMarkupRender.h" #include "Common/XTPColorManager.h" #include "Common/XTPWinThemeWrapper.h" #include "../Util/XTPControlTheme.h" #include "../Button/XTPButtonTheme.h" #include "XTPTaskDialogControls.h" #include "../Button/XTPButton.h" #ifdef _XTP_INCLUDE_MARKUP #include #include #include #include #include #include #endif #include "XTPTaskDialogAPI.h" #include "XTPTaskDialogClient.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //--------------------------------------------------------------------------- // dialog units used for dynamic layout. //--------------------------------------------------------------------------- enum XTPDluMetrics { xtpDluMinClient = 180, // minimum client width. xtpDluMaxClient = 265, // maximum client width when using command links. xtpDluMaxVerify = 146, // maximum width for verify and expando buttons. xtpDluPadding = 2, // padding used for button and content. xtpDluBtnSpacing = 3, // spacing between common buttons. xtpDluMargin = 5, // non-client margin. }; #ifndef LAYOUT_BITMAPORIENTATIONPRESERVED #define LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 #endif #define IDC_INPUTBOX 544 CXTPTaskDialogClient::CStringMarkup::CStringMarkup() { m_pUIElement = NULL; m_pClient = NULL; } CXTPTaskDialogClient::CStringMarkup::~CStringMarkup() { XTPMarkupReleaseElement(m_pUIElement); } void CXTPTaskDialogClient::CStringMarkup::SetCaption(const CString& strCaption) { m_strCaption = strCaption; XTPMarkupReleaseElement(m_pUIElement); if (!m_strCaption.IsEmpty() && m_pClient && m_pClient->m_pMarkupContext) { m_pUIElement = XTPMarkupParseText(m_pClient->m_pMarkupContext, m_strCaption); } } void CXTPTaskDialogClient::CStringMarkup::SetFinalRect(const CRect& rcFinalRect) { m_rcFinalRect = rcFinalRect; } //=========================================================================== // CXTPTaskDialogClient //=========================================================================== CXTPTaskDialogClient::CXTPTaskDialogClient() : m_nMaxClientWidth(0) , m_nMinClientWidth(0) , m_nPadding(2) , m_bExpanded(FALSE) , m_bVerification(FALSE) , m_bUseSysIcons(FALSE) , m_bThemeReady(FALSE) , m_hIconFooter(NULL) , m_hIconMain(NULL) , m_crContent(COLORREF_NULL) , m_crContentText(COLORREF_NULL) , m_crFooter(COLORREF_NULL) , m_crFooterText(COLORREF_NULL) , m_crMainText(COLORREF_NULL) , m_cr3DLight(COLORREF_NULL) , m_cr3DShadow(COLORREF_NULL) , m_cr3DHighLight(COLORREF_NULL) , m_ptMargin(0,0) , m_ptPadding(0,0) , m_ptBtnSpacing(0,0) , m_ptBorder(0,0) , m_pBtnVerify(NULL) , m_pBtnExpando(NULL) , m_pConfig(NULL) { m_rcMainInstruction.SetRectEmpty(); m_rcContent.SetRectEmpty(); m_rcCommandButtons.SetRectEmpty(); m_rcFooter.SetRectEmpty(); m_rcExpandedInformation.SetRectEmpty(); m_rcLinkButtons.SetRectEmpty(); m_rcRadioButtons.SetRectEmpty(); m_sizeCommandButton = CSize(0, 0); m_sizeIconFooter = CSize(0, 0); m_sizeIconMain = CSize(0, 0); m_nSelRadioButtonID = 0; m_pMarkupContext = NULL; m_pIconLinkGlyph = NULL; m_bMessageBoxStyle = FALSE; m_strMainInstruction.m_pClient = this; m_strContent.m_pClient = this; m_strFooter.m_pClient = this; m_strVerificationText.m_pClient = this; m_strExpandedInformation.m_pClient = this; m_strExpandedControlText.m_pClient = this; m_strCollapsedControlText.m_pClient = this; m_bEnableMarkup = FALSE; m_bShowInputBox = FALSE; } #define SAFE_DELETE_WINDOW(ptr) if (ptr) { ptr->DestroyWindow(); delete ptr; ptr = NULL; } void CXTPTaskDialogClient::DeleteControls() { SAFE_DELETE_WINDOW(m_pBtnVerify); SAFE_DELETE_WINDOW(m_pBtnExpando); CMDTARGET_RELEASE(m_pIconLinkGlyph); int i; for (i = 0; i < m_arrLinkButtons.GetSize(); ++i) { CButton* pButton = m_arrLinkButtons[i]; SAFE_DELETE_WINDOW(pButton); } m_arrLinkButtons.RemoveAll(); for (i = 0; i < m_arrRadioButtons.GetSize(); ++i) { CButton* pButton = m_arrRadioButtons[i]; SAFE_DELETE_WINDOW(pButton); } m_arrRadioButtons.RemoveAll(); for (i = 0; i < m_arrCommandButtons.GetSize(); ++i) { CButton* pButton = m_arrCommandButtons[i]; SAFE_DELETE_WINDOW(pButton); } m_arrCommandButtons.RemoveAll(); SAFE_DELETE_HICON(m_hIconFooter); SAFE_DELETE_HICON(m_hIconMain); CMDTARGET_RELEASE(m_pIconLinkGlyph); m_wndProgressBar.DestroyWindow(); m_wndFooter.DestroyWindow(); m_wndExpandedInformation.DestroyWindow(); m_wndContent.DestroyWindow(); m_strMainInstruction.SetCaption(_T("")); m_strContent.SetCaption(_T("")); m_strFooter.SetCaption(_T("")); m_strVerificationText.SetCaption(_T("")); m_strExpandedInformation.SetCaption(_T("")); m_strExpandedControlText.SetCaption(_T("")); m_strCollapsedControlText.SetCaption(_T("")); XTPMarkupReleaseContext(m_pMarkupContext); m_mapWndSize.RemoveAll(); } CXTPTaskDialogClient::~CXTPTaskDialogClient() { DeleteControls(); DestroyWindow(); } BEGIN_MESSAGE_MAP(CXTPTaskDialogClient, CWnd) //{{AFX_MSG_MAP(CXTPTaskDialogClient) ON_WM_SETTINGCHANGE() ON_WM_SYSCOLORCHANGE() ON_WM_ERASEBKGND() ON_WM_PAINT() ON_WM_CTLCOLOR() ON_WM_DESTROY() ON_EN_CHANGE(IDC_INPUTBOX, OnInputBoxChanged) //}}AFX_MSG_MAP END_MESSAGE_MAP() //--------------------------------------------------------------------------- // CXTPTaskDialogClient message handlers //--------------------------------------------------------------------------- void CXTPTaskDialogClient::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) { CDialog::OnSettingChange(uFlags, lpszSection); RefreshMetrics(); } void CXTPTaskDialogClient::OnSysColorChange() { CDialog::OnSysColorChange(); RefreshMetrics(); } BOOL CXTPTaskDialogClient::OnEraseBkgnd(CDC* pDC) { UNREFERENCED_PARAMETER(pDC); return TRUE; } void CXTPTaskDialogClient::OnPaint() { CPaintDC dc(this); // device context for painting CXTPBufferDC memDC(dc); CXTPClientRect rcClient(this); if (!memDC.GetSafeHdc()) return; DrawBackground(&memDC, rcClient); memDC.SetBkMode(TRANSPARENT); DrawMainInstruction(&memDC); DrawContent(&memDC); DrawExpandedInfo(&memDC); DrawFootNote(&memDC); } HBRUSH CXTPTaskDialogClient::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { int i; for (i = 0; i < m_arrRadioButtons.GetSize(); i++) { if (m_arrRadioButtons[i] == pWnd) { pDC->SetBkColor(m_crContent); return GetSysColorBrush(m_bThemeReady ? COLOR_WINDOW : COLOR_3DFACE); } } for (i = 0; i < m_arrLinkButtons.GetSize(); i++) { if (m_arrLinkButtons[i] == pWnd) { pDC->SetBkColor(m_crContent); return GetSysColorBrush(m_bThemeReady ? COLOR_WINDOW : COLOR_3DFACE); } } return CWnd::OnCtlColor(pDC, pWnd, nCtlColor); } HRESULT CXTPTaskDialogClient::SendNotify(UINT uNotify, WPARAM wParam /*=0*/, LPARAM lParam /*=0*/) { if (m_pConfig->pfCallback) { return m_pConfig->pfCallback(m_hWnd, uNotify, wParam, lParam, m_pConfig->lpCallbackData); } return E_FAIL; } BOOL CXTPTaskDialogClient::CanCancel() const { if (GetDlgItem(IDCANCEL)) return TRUE; return ((m_pConfig->dwFlags & TDF_ALLOW_DIALOG_CANCELLATION) != 0); } void CXTPTaskDialogClient::OnMarkupHyperlinkClick(CXTPMarkupObject* pSender, CXTPMarkupRoutedEventArgs* pArgs) { pSender; pArgs; #ifdef _XTP_INCLUDE_MARKUP if (pSender->IsKindOf(MARKUP_TYPE(CXTPMarkupHyperlink))) { CXTPMarkupString* pTag = MARKUP_STATICCAST(CXTPMarkupString, ((CXTPMarkupHyperlink*)pSender)->GetTag()); SendNotify(TDN_HYPERLINK_CLICKED, (WPARAM)0, (LPARAM)(pTag ? (LPCWSTR)*pTag : (LPCWSTR)NULL)); pArgs->SetHandled(); } #endif } BOOL CXTPTaskDialogClient::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { // To Handle Hyperlinks: if (m_pMarkupContext) { CPoint ptMouse(0); GetCursorPos(&ptMouse); ScreenToClient(&ptMouse); if (m_strMainInstruction.m_rcFinalRect.PtInRect(ptMouse)) { if (XTPMarkupRelayMessage(m_strMainInstruction.m_pUIElement, message, wParam, lParam, pResult)) return TRUE; } else if (m_strContent.m_rcFinalRect.PtInRect(ptMouse)) { if (XTPMarkupRelayMessage(m_strContent.m_pUIElement, message, wParam, lParam, pResult)) return TRUE; } else if (m_strFooter.m_rcFinalRect.PtInRect(ptMouse)) { if (XTPMarkupRelayMessage(m_strFooter.m_pUIElement, message, wParam, lParam, pResult)) return TRUE; } else if (m_strExpandedInformation.m_rcFinalRect.PtInRect(ptMouse)) { if (XTPMarkupRelayMessage(m_strExpandedInformation.m_pUIElement, message, wParam, lParam, pResult)) return TRUE; } else { if (XTPMarkupRelayMessage(m_pMarkupContext, message, wParam, lParam, pResult)) return TRUE; } } return CDialog::OnWndMsg(message, wParam, lParam, pResult); } LRESULT CXTPTaskDialogClient::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { if (HIWORD(wParam) == BN_CLICKED) { int nID = (int)LOWORD(wParam); HWND hWnd = (HWND)lParam; if (hWnd && m_arrRadioButtons.GetSize() > 0) { for (int i = 0; i < m_arrRadioButtons.GetSize(); i++) { if (m_arrRadioButtons[i]->GetSafeHwnd() == hWnd ) { if (m_arrRadioButtons[i]->GetCheck()) { m_nSelRadioButtonID = nID; SendNotify(TDN_RADIO_BUTTON_CLICKED, (WPARAM)m_nSelRadioButtonID); } return TRUE; } } } if (hWnd && (hWnd == m_wndFooter.GetSafeHwnd() || hWnd == m_wndContent.GetSafeHwnd() || hWnd == m_wndExpandedInformation.GetSafeHwnd())) { CXTPTaskDialogLinkCtrl* pWnd = (CXTPTaskDialogLinkCtrl*)CWnd::FromHandle(hWnd); CXTPTaskDialogLinkCtrl::LINKITEM* pItem = pWnd->GetFocusedLink(); if (pItem) { SendNotify(TDN_HYPERLINK_CLICKED, (WPARAM)0, (LPARAM)XTP_CT2CW(pItem->strUrl)); return 1; } } if (hWnd && m_pBtnVerify->GetSafeHwnd() == hWnd) { m_bVerification = !m_bVerification; SendNotify(TDN_VERIFICATION_CLICKED, m_bVerification); return 0; } if (hWnd && m_pBtnExpando->GetSafeHwnd() == hWnd) { m_bExpanded = !m_bExpanded; SendNotify(TDN_EXPANDO_BUTTON_CLICKED, m_bExpanded); OnExpandExpandoClicked(); return 0; } if (nID == IDCANCEL) { if (!CanCancel()) return FALSE; } if (SendNotify(TDN_BUTTON_CLICKED, (WPARAM)nID) == 0) { if (nID == IDCANCEL) { OnCancel(); } else if (nID == IDOK) { OnOK(); } else { EndDialog(nID); } } return 0; } break; } } return CDialog::WindowProc(message, wParam, lParam); } //--------------------------------------------------------------------------- // Initialization //--------------------------------------------------------------------------- void CXTPTaskDialogClient::RefreshMetrics() { CXTPWinThemeWrapper themeApi; m_bThemeReady = m_bMessageBoxStyle || themeApi.IsAppThemeReady(); m_ptBorder.x = ::GetSystemMetrics(SM_CXEDGE) + ::GetSystemMetrics(SM_CXBORDER); m_ptBorder.y = ::GetSystemMetrics(SM_CYEDGE) + ::GetSystemMetrics(SM_CYBORDER); m_sizeIconFooter.cx = ::GetSystemMetrics(SM_CXSMICON); m_sizeIconFooter.cy = ::GetSystemMetrics(SM_CYSMICON); m_sizeIconMain.cx = ::GetSystemMetrics(SM_CXICON); m_sizeIconMain.cy = ::GetSystemMetrics(SM_CYICON); m_ptMargin = XTPDlu2Pix(xtpDluMargin, xtpDluMargin); m_ptPadding = XTPDlu2Pix(xtpDluPadding, xtpDluPadding); m_ptBtnSpacing = CPoint(XTPDlu2Pix(xtpDluBtnSpacing, xtpDluBtnSpacing).x, 0); if (!m_bThemeReady) m_ptBtnSpacing = CPoint(m_ptMargin.x, 2); m_nMinClientWidth = XTPDlu2Pix(xtpDluMinClient, 0).x - m_ptMargin.x * 2; CRect rcScreen = XTPMultiMonitor()->GetWorkArea(m_pConfig->hwndParent); m_nMaxClientWidth = rcScreen.Width() - ((m_ptBorder.x*2) + (m_ptMargin.x*2)); if (m_nMinClientWidth > m_nMaxClientWidth) m_nMinClientWidth = m_nMaxClientWidth; RefreshColors(); } void CXTPTaskDialogClient::RefreshColors() { XTPColorManager()->RefreshColors(); COLORREF crWindow = GetXtremeColor(COLOR_WINDOW); COLORREF crWindowText = GetXtremeColor(COLOR_WINDOWTEXT); COLORREF crBtnFace = GetXtremeColor(COLOR_BTNFACE); COLORREF crBtnText = GetXtremeColor(COLOR_BTNTEXT); m_cr3DShadow = GetXtremeColor(COLOR_3DSHADOW); m_cr3DHighLight = GetXtremeColor(COLOR_3DHILIGHT); m_cr3DLight = XTPColorManager()->LightColor(crBtnFace, m_cr3DShadow, 750); m_crContent = crBtnFace; m_crMainText = m_crContentText = crBtnText; if (m_bThemeReady) { m_crContent = crWindow; m_crContentText = crWindowText; m_crMainText = RGB(0x00, 0x33, 0x99); if (!XTPColorManager()->LongColor(m_crMainText, crWindow, 1, 50)) m_crMainText = m_crContentText; } m_crFooter = crBtnFace; m_crFooterText = crBtnText; m_wndContent.SetBackColor(m_crContent); m_wndContent.SetTextColor(m_crContentText); m_wndExpandedInformation.SetBackColor(IsExpandFooterArea() ? m_crFooter : m_crContent); m_wndExpandedInformation.SetTextColor(IsExpandFooterArea() ? m_crFooterText : m_crContentText); m_wndFooter.SetBackColor(m_crFooter); m_wndFooter.SetTextColor(m_crFooterText); } CString CXTPTaskDialogClient::LoadItemString(PCWSTR pszBuffer) { CString strItem; if (pszBuffer && IS_INTRESOURCE(pszBuffer)) { UINT uID = (UINT)(UINT_PTR)pszBuffer; if (::FindResource(m_pConfig->hInstance, MAKEINTRESOURCE((uID>>4)+1), RT_STRING)) XTPLoadStringInst(m_pConfig->hInstance, uID, &strItem); else XTPResourceManager()->LoadString(&strItem, uID); ASSERT(!strItem.IsEmpty()); } else { strItem = pszBuffer; } return strItem; } void CXTPTaskDialogClient::LoadStrings() { m_strMainInstruction.SetCaption(LoadItemString(m_pConfig->pszMainInstruction)); m_strContent.SetCaption(LoadItemString(m_pConfig->pszContent)); m_strFooter.SetCaption(LoadItemString(m_pConfig->pszFooter)); m_strVerificationText.SetCaption(LoadItemString(m_pConfig->pszVerificationText)); m_strExpandedInformation.SetCaption(LoadItemString(m_pConfig->pszExpandedInformation)); if (!m_strExpandedInformation.IsEmpty()) { m_strExpandedControlText.SetCaption(LoadItemString(m_pConfig->pszExpandedControlText)); m_strCollapsedControlText.SetCaption(LoadItemString(m_pConfig->pszCollapsedControlText)); if (m_strExpandedControlText.IsEmpty() && m_strCollapsedControlText.IsEmpty()) { CXTPResourceManager::AssertValid(XTPResourceManager()->LoadString(&m_strExpandedControlText.m_strCaption, XTP_IDS_TASK_HIDE_DETAILS)); CXTPResourceManager::AssertValid(XTPResourceManager()->LoadString(&m_strCollapsedControlText.m_strCaption, XTP_IDS_TASK_SEE_DETAILS)); } else if (m_strExpandedControlText.IsEmpty()) { m_strExpandedControlText = m_strCollapsedControlText; } else if (m_strCollapsedControlText.IsEmpty()) { m_strCollapsedControlText = m_strExpandedControlText; } } } BOOL CXTPTaskDialogClient::CreateCommandButtons() { if ((m_pConfig->dwCommonButtons & TDCBF_OK_BUTTON) || (!m_pConfig->pButtons && !m_pConfig->dwCommonButtons)) { if (AddCommandButton(IDOK, XTP_IDS_TASK_OK, m_sizeCommandButton) == NULL) { TRACE0("Failed to create OK button.\n"); return FALSE; } } if (m_pConfig->dwCommonButtons & TDCBF_YES_BUTTON) { if (AddCommandButton(IDYES, XTP_IDS_TASK_YES, m_sizeCommandButton) == NULL) { TRACE0("Failed to create YES button.\n"); return FALSE; } } if (m_pConfig->dwCommonButtons & TDCBF_NO_BUTTON) { if (AddCommandButton(IDNO, XTP_IDS_TASK_NO, m_sizeCommandButton) == NULL) { TRACE0("Failed to create NO button.\n"); return FALSE; } } if (m_pConfig->dwCommonButtons & TDCBF_RETRY_BUTTON) { if (AddCommandButton(IDRETRY, XTP_IDS_TASK_RETRY, m_sizeCommandButton) == NULL) { TRACE0("Failed to create RETRY button.\n"); return FALSE; } } if (m_pConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON) { if (AddCommandButton(IDCANCEL, XTP_IDS_TASK_CANCEL, m_sizeCommandButton) == NULL) { TRACE0("Failed to create CANCEL button.\n"); return FALSE; } } if (m_pConfig->dwCommonButtons & TDCBF_CLOSE_BUTTON) { if (AddCommandButton(IDCLOSE, XTP_IDS_TASK_CLOSE, m_sizeCommandButton) == NULL) { TRACE0("Failed to create CLOSE button.\n"); return FALSE; } } return TRUE; } BOOL CXTPTaskDialogClient::CreateLinkButtons() { if (m_pConfig->pButtons == NULL || m_pConfig->cButtons == 0) return TRUE; for (UINT i = 0; i < m_pConfig->cButtons; ++i) { CString strButtonText = LoadItemString(m_pConfig->pButtons[i].pszButtonText); if (IsLinkButtonsUsed()) { CXTPTaskButtonTheme* pTheme = new CXTPTaskButtonTheme(m_bThemeReady); pTheme->SetTitleFont(&m_fontLarge); CButton* pLinkButton = CreateButton(m_pConfig->pButtons[i].nButtonID, strButtonText, CSize(0, 0), BS_PUSHBUTTON | BS_MULTILINE | WS_TABSTOP, pTheme); if (pLinkButton == NULL) { TRACE0("Error creating command link button.\n"); return FALSE; } if (m_pIconLinkGlyph) { CXTPButton* pButton = DYNAMIC_DOWNCAST(CXTPButton, pLinkButton); if (pButton == NULL) { TRACE0("Error creating command link button.\n"); SAFE_DELETE(pButton); return FALSE; } m_pIconLinkGlyph->InternalAddRef(); // Lets share one icon! pButton->SetIcon(m_pIconLinkGlyph->GetExtent(), m_pIconLinkGlyph); } m_arrLinkButtons.Add(pLinkButton); } else { CSize sizeButton = CalcButtonSize(strButtonText); sizeButton.cx = max(m_sizeCommandButton.cx, sizeButton.cx); if (AddCommandButton(m_pConfig->pButtons[i].nButtonID, strButtonText, sizeButton) == NULL) { TRACE0("Failed to create OK button.\n"); return FALSE; } } } return TRUE; } #ifndef PBS_MARQUEE #define PBS_MARQUEE 0x08 #endif BOOL CXTPTaskDialogClient::CreateProgressBar() { if (!IsProgressBarVisible()) return TRUE; if (!m_wndProgressBar.Create(WS_CHILD | WS_VISIBLE | (m_pConfig->dwFlags & TDF_SHOW_MARQUEE_PROGRESS_BAR ? PBS_MARQUEE : 0), CRect(0, 0, 0, 0), this, 0)) return FALSE; return TRUE; } BOOL CXTPTaskDialogClient::CreateInputBox() { if (!m_bShowInputBox) return TRUE; if (!m_wndInputBox.CreateEx(WS_EX_CLIENTEDGE, _T("EDIT"), m_strInputBoxText, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, CRect(0, 0, 0, 0), this, IDC_INPUTBOX)) return FALSE; m_wndInputBox.SetFont(&m_font); return TRUE; } BOOL CXTPTaskDialogClient::CreateRadioButtons() { if (m_pConfig->pRadioButtons == NULL) return TRUE; for (UINT i = 0; i < m_pConfig->cRadioButtons; ++i) { CString strButton = LoadItemString(m_pConfig->pRadioButtons[i].pszButtonText); int nButtonID = m_pConfig->pRadioButtons[i].nButtonID; CPoint point(10,2); CButton* pButton = CreateButton(nButtonID, strButton, CalcButtonSize(strButton, &point), BS_AUTORADIOBUTTON | BS_TEXT | BS_MULTILINE | BS_TOP); if (pButton == NULL) { TRACE0("Error creating radio button.\n"); return FALSE; } if ((m_pConfig->dwFlags & TDF_NO_DEFAULT_RADIO_BUTTON) == 0) { if (m_pConfig->nDefaultRadioButton == nButtonID) { pButton->SetCheck(TRUE); m_nSelRadioButtonID = nButtonID; pButton->ModifyStyle(0, WS_TABSTOP); } if (m_pConfig->nDefaultRadioButton == 0 && i == 0) { pButton->SetCheck(TRUE); m_nSelRadioButtonID = nButtonID; pButton->ModifyStyle(0, WS_TABSTOP); } } else if (i == 0) { pButton->ModifyStyle(0, WS_TABSTOP); } m_arrRadioButtons.Add(pButton); } return TRUE; } BOOL CXTPTaskDialogClient::CreateVerifyExpandButtons() { // create expando button. if (!m_strExpandedInformation.IsEmpty()) { CString strButtonText = IsExpandedByDefault()? m_strExpandedControlText: m_strCollapsedControlText; CString strButtonSize = m_strExpandedControlText.m_strCaption.GetLength() > m_strCollapsedControlText.m_strCaption.GetLength() ? m_strExpandedControlText : m_strCollapsedControlText; CSize sizeButton = CalcButtonSize(strButtonSize, NULL, XTPDlu2Pix(xtpDluMaxVerify,0).x); CButton* pButton = CreateButton(0, strButtonText, sizeButton, BS_PUSHBUTTON | BS_MULTILINE | WS_TABSTOP, new CXTPTaskButtonThemeExpando); if (pButton == NULL) { TRACE0("Error creating Expando button.\n"); return FALSE; } m_pBtnExpando = DYNAMIC_DOWNCAST(CXTPButton, pButton); if (m_pBtnExpando == NULL) { TRACE0("Error creating Expando button.\n"); SAFE_DELETE(pButton); return FALSE; } m_bExpanded = IsExpandedByDefault(); m_pBtnExpando->SetChecked(m_bExpanded); } // create verification text check box. if (!m_strVerificationText.IsEmpty()) { CString strButtonText = m_strVerificationText; CPoint point(10, 2); CSize sizeButton = CalcButtonSize(strButtonText, &point, XTPDlu2Pix(xtpDluMaxVerify,0).x); CButton* pButton = CreateButton(0, strButtonText, sizeButton, BS_AUTOCHECKBOX | BS_MULTILINE | BS_TOP | BS_LEFT | WS_TABSTOP); if (pButton == NULL) { TRACE0("Error creating Verification check box.\n"); return FALSE; } m_bVerification = ((m_pConfig->dwFlags & TDF_VERIFICATION_FLAG_CHECKED) != 0); m_pBtnVerify = pButton; m_pBtnVerify->SetCheck(m_bVerification); } return TRUE; } BOOL CXTPTaskDialogClient::CreateClient(BOOL bMoveWindow) { DeleteControls(); if (m_bEnableMarkup) { m_pMarkupContext = XTPMarkupCreateContext(m_hWnd); } #ifdef _XTP_INCLUDE_MARKUP if (m_pMarkupContext) { m_pMarkupContext->AddHandler(CXTPMarkupHyperlink::m_pClickEvent, CreateMarkupClassDelegate(this, &CXTPTaskDialogClient::OnMarkupHyperlinkClick)); } #endif RefreshMetrics(); LoadStrings(); CreateIcons(); CreateFonts(); m_sizeCommandButton = CalcCommandButtonSize(); if (!CreateLinkButtons() || // create command link buttons. !CreateCommandButtons()) // create common buttons OK, Cancel, etc. { return FALSE; } // If hyperlinks are enabled, creating the links now with a zero size // will extract all hyperlink information from the string so the layout // can be determined correctly. The links will be resized when RecalcLayout // is called. if (IsHyperlinksEnabled()) { CXTPEmptyRect rect; m_wndContent.Create(rect, m_strContent.m_strCaption, &m_font, this); m_wndExpandedInformation.Create(rect, m_strExpandedInformation.m_strCaption, &m_font, this); m_wndFooter.Create(rect, m_strFooter.m_strCaption, &m_font, this); } if (!CreateProgressBar() || !CreateRadioButtons() || // create radio buttons. !CreateInputBox() || // create input box. !CreateVerifyExpandButtons()) // create verify and expando buttons. { return FALSE; } RecalcLayout(bMoveWindow); return TRUE; } void CXTPTaskDialogClient::OnDestroy() { if (m_wndInputBox.GetSafeHwnd()) { m_wndInputBox.GetWindowText(m_strInputBoxText); } CDialog::OnDestroy(); } void CXTPTaskDialogClient::UpdateZOrder() { ZOrder(&m_wndContent); if (!IsExpandFooterArea()) ZOrder(&m_wndExpandedInformation); ZOrder(&m_wndProgressBar); int i; for (i = 0; i < (int)m_arrRadioButtons.GetSize(); i++) { ZOrder(m_arrRadioButtons[i]); } ZOrder(&m_wndInputBox); for (i = 0; i < (int)m_arrLinkButtons.GetSize(); i++) { ZOrder(m_arrLinkButtons[i]); } ZOrder(m_pBtnExpando); ZOrder(m_pBtnVerify); for (i = 0; i < (int)m_arrCommandButtons.GetSize(); i++) { ZOrder(m_arrCommandButtons[i]); } ZOrder(&m_wndFooter); if (IsExpandFooterArea()) ZOrder(&m_wndExpandedInformation); } void CXTPTaskDialogClient::ZOrder(CWnd* pWnd) { if (!pWnd || !pWnd->GetSafeHwnd() ) return; pWnd->SetWindowPos(&CWnd::wndBottom, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE); } HICON CXTPTaskDialogClient::LoadSysIcon(PCWSTR lpwzIcon, CSize sizeIcon) { DWORD dwID = 0; HICON hNewIcon = 0; if (m_bUseSysIcons) { switch ((ULONG_PTR)lpwzIcon) { case (ULONG_PTR)TD_ERROR_ICON: dwID = 0x0067; break; case (ULONG_PTR)TD_WARNING_ICON: dwID = 0x0065; break; case (ULONG_PTR)TD_INFORMATION_ICON: dwID = 0x0068; break; case (ULONG_PTR)TD_QUESTION_ICON: dwID = 0x0066; break; case (ULONG_PTR)TD_SHIELD_ICON: dwID = 0x006a; break; // vista and later. } hNewIcon = XTPResourceManager()->CreateIconFromResource( CXTPModuleHandle(_T("user32.dll")), MAKEINTRESOURCE(dwID), sizeIcon); } if (hNewIcon == NULL) { switch ((ULONG_PTR)lpwzIcon) { case (ULONG_PTR)TD_ERROR_ICON: dwID = XTP_IDI_TASKERROR; break; case (ULONG_PTR)TD_WARNING_ICON: dwID = XTP_IDI_TASKWARN; break; case (ULONG_PTR)TD_INFORMATION_ICON: dwID = XTP_IDI_TASKINFO; break; case (ULONG_PTR)TD_SHIELD_ICON: dwID = XTP_IDI_TASKSHIELD; break; case (ULONG_PTR)TD_QUESTION_ICON: dwID = XTP_IDI_TASKQUESTION; break; } hNewIcon = XTPResourceManager()->LoadIcon(MAKEINTRESOURCE(dwID), sizeIcon); } return hNewIcon; } HICON CXTPTaskDialogClient::CreateIcon(HICON hIcon, PCWSTR lpwzIcon, CSize sizeIcon, BOOL bUseHandle) { HICON hNewIcon = NULL; if (bUseHandle && hIcon != NULL) { hNewIcon = ::CopyIcon(hIcon); } else if (!bUseHandle) { if (m_pConfig->hInstance == NULL || lpwzIcon == NULL || !IS_INTRESOURCE(lpwzIcon)) { return FALSE; } if (lpwzIcon == TD_ERROR_ICON || lpwzIcon == TD_WARNING_ICON || lpwzIcon == TD_INFORMATION_ICON || lpwzIcon == TD_SHIELD_ICON || lpwzIcon == TD_QUESTION_ICON) { hNewIcon = LoadSysIcon(lpwzIcon, sizeIcon); } else { hNewIcon = XTPResourceManager()->CreateIconFromResource( m_pConfig->hInstance, (LPTSTR)lpwzIcon, sizeIcon); } } ASSERT(hNewIcon != NULL); return hNewIcon; } void CXTPTaskDialogClient::CreateIcons() { CXTPResourceManager::CManageState manageState; // Switch to Toolkit resources // create small icon. SAFE_DELETE_HICON(m_hIconFooter); m_hIconFooter = CreateIcon(m_pConfig->hFooterIcon, m_pConfig->pszFooterIcon, m_sizeIconFooter, IsFooterIconHandleUsed()); // create large icon. SAFE_DELETE_HICON(m_hIconMain); m_hIconMain = CreateIcon(m_pConfig->hMainIcon, m_pConfig->pszMainIcon, m_sizeIconMain, IsMainIconHandleUsed()); if (IsLinkButtonsUsed() && IsLinkButtonsIconVisible() && m_pIconLinkGlyph == 0) { m_pIconLinkGlyph = new CXTPImageManagerIcon(0, 20, 20); BOOL bRTLLayout = (m_pConfig->dwFlags & TDF_RTL_LAYOUT); CXTPImageManagerIconHandle hIconGlyph; CXTPImageManagerIconHandle hIconGlyphHot; HBITMAP hBitmap = (HBITMAP)CXTPImageManagerIcon::LoadAlphaBitmap(XTP_IDB_GLYPH); if (bRTLLayout) { hIconGlyph = CXTPImageManagerIcon::InvertAlphaBitmap(hBitmap); DeleteObject(hBitmap); } else { hIconGlyph = hBitmap; } hBitmap = (HBITMAP)CXTPImageManagerIcon::LoadAlphaBitmap(XTP_IDB_GLYPH_HOT); if (bRTLLayout) { hIconGlyphHot = CXTPImageManagerIcon::InvertAlphaBitmap(hBitmap); DeleteObject(hBitmap); } else { hIconGlyphHot = hBitmap; } m_pIconLinkGlyph->SetIcon(hIconGlyph); m_pIconLinkGlyph->SetHotIcon(hIconGlyphHot); } } void CXTPTaskDialogClient::CreateFonts() { NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(NONCLIENTMETRICS); ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); ncm.lfMenuFont.lfCharSet = XTPResourceManager()->GetFontCharset(); ncm.lfCaptionFont.lfCharSet = XTPResourceManager()->GetFontCharset(); m_font.DeleteObject(); m_fontLarge.DeleteObject(); if (m_bThemeReady) { CWindowDC dc(NULL); if (_tcscmp(ncm.lfMenuFont.lfFaceName, _T("Segoe UI")) == 0) ncm.lfMenuFont.lfQuality = 5; ncm.lfMenuFont.lfWeight = FW_NORMAL; ncm.lfMenuFont.lfItalic = 0; m_font.CreateFontIndirect(&ncm.lfMenuFont); ncm.lfMenuFont.lfHeight = ::MulDiv(-12, ::GetDeviceCaps(dc.m_hDC, LOGPIXELSY), 72); if (_tcscmp(ncm.lfMenuFont.lfFaceName, _T("Segoe UI")) != 0) ncm.lfMenuFont.lfWeight = FW_BOLD; m_fontLarge.CreateFontIndirect(&ncm.lfMenuFont); } else { m_font.CreateFontIndirect(&ncm.lfMenuFont); m_fontLarge.CreateFontIndirect(&ncm.lfCaptionFont); } } //--------------------------------------------------------------------------- // Button //--------------------------------------------------------------------------- CButton *CXTPTaskDialogClient::CreateButton(int nButtonID, LPCTSTR lpszLabel, CSize sizeButton, DWORD dwButtonStyle /*=BS_PUSHBUTTON | BS_MULTILINE*/, CXTPButtonTheme* pTheme /*=NULL*/) { CXTPButton* pButton = new CXTPButton; if (pTheme) dwButtonStyle |= BS_LEFT; CRect rcButton = XTPSize2Rect(sizeButton); if (!pButton->Create(lpszLabel, WS_CHILD | WS_VISIBLE | dwButtonStyle, rcButton, this, nButtonID)) { SAFE_DELETE(pButton); return NULL; } m_mapWndSize[pButton] = sizeButton; if (pTheme) { pButton->SetTheme(pTheme); } pButton->SetFont(&m_font); if (m_pMarkupContext) { pButton->EnableMarkup(); } return pButton; } CButton *CXTPTaskDialogClient::AddCommandButton(int nButtonID, int nIDLabel, CSize sizeButton) { CString strButton; XTPResourceManager()->LoadString(&strButton, nIDLabel); ASSERT(!strButton.IsEmpty()); return AddCommandButton(nButtonID, strButton, sizeButton); } CButton *CXTPTaskDialogClient::AddCommandButton(int nButtonID, LPCTSTR lpszLabel, CSize sizeButton) { CButton* pButton = CreateButton(nButtonID, lpszLabel, sizeButton, BS_PUSHBUTTON | BS_MULTILINE | WS_TABSTOP); if (pButton) { m_arrCommandButtons.Add(pButton); return pButton; } return NULL; } CSize CXTPTaskDialogClient::CalcButtonSize(CString strButton, CPoint* pMarginButton /*=NULL*/, int nMaxWidth /*=0*/) { CPoint ptMarginButton; ptMarginButton.x = m_ptBtnSpacing.x + m_ptMargin.x; ptMarginButton.y = m_ptPadding.y; if (pMarginButton == NULL) pMarginButton = &ptMarginButton; if (m_pMarkupContext) { CXTPMarkupUIElement* pUIElement = XTPMarkupParseText(m_pMarkupContext, strButton); if (pUIElement) { CSize sz = XTPMarkupMeasureElement(pUIElement, nMaxWidth == 0 ? INT_MAX : nMaxWidth); XTPMarkupReleaseElement(pUIElement); return CSize(sz.cx + pMarginButton->x * 2, sz.cy + pMarginButton->y * 2); } } CXTPEmptySize sizeCaptText; CString strCaptText = XTPExtractSubString(strButton, 0); if (!strCaptText.IsEmpty()) { sizeCaptText.cx = nMaxWidth; XTPDrawHelpers()->StripMnemonics(strCaptText); if (nMaxWidth == 0) XTPCalcIdealTextSize(strCaptText, sizeCaptText, m_font, 330, 7); else XTPCalcTextSize(strCaptText, sizeCaptText, m_font); } CXTPEmptySize sizeNoteText; CString strNoteText = XTPExtractSubString(strButton, 1); if (!strNoteText.IsEmpty()) { sizeNoteText.cx = nMaxWidth; if (nMaxWidth == 0) XTPCalcIdealTextSize(strNoteText, sizeNoteText, m_font, 330, 7); else XTPCalcTextSize(strNoteText, sizeNoteText, m_font); } CXTPEmptySize sizeButton; sizeButton.cx = max(sizeCaptText.cx, sizeNoteText.cx) + (pMarginButton->x * 2); sizeButton.cy = sizeCaptText.cy + sizeNoteText.cy + (pMarginButton->y * 2); return sizeButton; } CSize CXTPTaskDialogClient::CalcCommandButtonSize() { CXTPEmptySize sizeCommon; for (int nIDString = XTP_IDS_TASK_OK; nIDString <= XTP_IDS_TASK_CLOSE; ++nIDString) { CString strButton; XTPResourceManager()->LoadString(&strButton, nIDString); ASSERT(!strButton.IsEmpty()); CSize sizeButton = CalcButtonSize(strButton); sizeCommon.cx = max(sizeCommon.cx, sizeButton.cx); sizeCommon.cy = max(sizeCommon.cy, sizeButton.cy); } return sizeCommon; } int CXTPTaskDialogClient::CalcLinkButtonIdealWidth(CString strButton, int cxWidth) { if (strButton.IsEmpty() || !HasLinkButtons()) return 0; cxWidth -= ((m_ptMargin.x*2) + m_nPadding); if (m_pIconLinkGlyph) cxWidth -= m_pIconLinkGlyph->GetExtent().cx - m_nPadding; CStringMarkup strCaptText; strCaptText.m_pClient = this; strCaptText.SetCaption(XTPExtractSubString(strButton, 0)); int nCaptionWidth = 0; if (strCaptText.m_pUIElement) nCaptionWidth = CalcIdealTextWidth(strCaptText, cxWidth, TRUE); else { CSize sizeText(cxWidth, 0); if (XTPCalcIdealTextSize(strCaptText, sizeText, m_fontLarge, 120, 30)) { nCaptionWidth = sizeText.cx; } } CStringMarkup strNoteText; strNoteText.m_pClient = this; strNoteText.SetCaption(XTPExtractSubString(strButton, 1)); int nNoteWidth = CalcIdealTextWidth(strNoteText, cxWidth, FALSE); cxWidth = max(nCaptionWidth, nNoteWidth); if (m_pIconLinkGlyph) cxWidth += m_pIconLinkGlyph->GetExtent().cx; return cxWidth + m_ptMargin.x * 2 + m_nPadding; } CSize CXTPTaskDialogClient::CalcLinkButtonSize(CXTPButton* pButton, CString strButton, int cxMaxWidth) { if (strButton.IsEmpty() || !HasLinkButtons()) return CXTPEmptySize(); cxMaxWidth -= ((m_ptMargin.x*2) + m_nPadding); if (m_pIconLinkGlyph) cxMaxWidth -= m_pIconLinkGlyph->GetExtent().cx; // get the initial text size. CXTPEmptySize sizeButton; BOOL bWordWrap = FALSE; // extract the title string and determine text size. CString strCaptText = XTPExtractSubString(strButton, 0); CSize sizeCaptText(cxMaxWidth, 0); if (pButton->GetMarkupUIElement()) { XTPMarkupSetDefaultFont(pButton->GetMarkupContext(), (HFONT)m_fontLarge.GetSafeHandle(), COLORREF_NULL); sizeCaptText = XTPMarkupMeasureElement(pButton->GetMarkupUIElement(), cxMaxWidth, INT_MAX); } else if (XTPCalcTextSize(strCaptText, sizeCaptText, m_fontLarge, &bWordWrap)) { // if the string spans multiple rows, set the max width. if (bWordWrap) sizeCaptText.cx = cxMaxWidth; } else { sizeCaptText.cx = 0; } // extract the note string and determine text size. CString strNoteText = XTPExtractSubString(strButton, 1); CSize sizeNoteText(cxMaxWidth, 0); if (XTPCalcTextSize(strNoteText, sizeNoteText, m_font, &bWordWrap)) { // if the string spans multiple rows, set the max width. if (bWordWrap) sizeNoteText.cx = cxMaxWidth; } else { sizeNoteText.cx = 0; } // add padding around text. sizeButton.cx = max(sizeCaptText.cx, sizeNoteText.cx) + m_ptMargin.x * 2 + m_nPadding; sizeButton.cy = sizeCaptText.cy + sizeNoteText.cy + m_ptMargin.y * 2 /*+ m_nPadding*/; return sizeButton; } BOOL CXTPTaskDialogClient::MoveButton(CButton* pButton, int x, int y, int cx, int cy, BOOL bRedraw /*=FALSE*/) { // position the button. if (IsWindow(pButton) && pButton->SetWindowPos(NULL, x, y, cx, cy, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE)) { // invalidate. if (bRedraw) pButton->RedrawWindow(); return TRUE; } return FALSE; } void CXTPTaskDialogClient::SetCommandButtonPos() { int x = m_rcCommandButtons.left, y = m_rcCommandButtons.top + m_ptMargin.y - 1; int i, nCount = (int)m_arrCommandButtons.GetSize(); for (i = 0; i < nCount; i++) { CButton* pButton = m_arrCommandButtons[i]; CXTPEmptySize sizeButton; if (m_mapWndSize.Lookup(pButton, sizeButton)) { // no more room, adjust height. if (x != m_rcCommandButtons.left && x + sizeButton.cx > m_rcCommandButtons.right) { x = m_rcCommandButtons.left; y += sizeButton.cy + m_ptBtnSpacing.y; } MoveButton(pButton, x, y, sizeButton.cx, sizeButton.cy); x += sizeButton.cx + m_ptBtnSpacing.x; } } } void CXTPTaskDialogClient::SetLinkButtonPos() { int nTop = m_rcLinkButtons.top + m_ptMargin.x + m_ptPadding.y / 2 + 2; int nCount = (int)m_arrLinkButtons.GetSize(); for (int i = 0; i < nCount; ++i) { CSize sizeButton; if (m_mapWndSize.Lookup(m_arrLinkButtons[i], sizeButton)) { MoveButton(m_arrLinkButtons[i], m_rcLinkButtons.left, nTop, m_rcLinkButtons.Width(), sizeButton.cy); nTop += sizeButton.cy; } } } void CXTPTaskDialogClient::SetVerifyButtonPos() { CXTPEmptySize sizeVerify; if (IsWindow(m_pBtnVerify) && m_mapWndSize.Lookup(m_pBtnVerify, sizeVerify)) { CXTPEmptyRect rcButton; rcButton.left = m_ptMargin.x + 3; rcButton.right = rcButton.left + sizeVerify.cx; // vertically center. rcButton.top = m_rcCommandButtons.top + (m_rcCommandButtons.Height() - sizeVerify.cy)/2; CXTPEmptySize sizeExpando; if (IsWindow(m_pBtnExpando) && m_mapWndSize.Lookup(m_pBtnExpando, sizeExpando)) { rcButton.top = m_rcCommandButtons.top + m_ptMargin.y + sizeExpando.cy; } rcButton.bottom = rcButton.top + sizeVerify.cy; MoveButton(m_pBtnVerify, rcButton); } } void CXTPTaskDialogClient::SetExpandoButtonPos() { CXTPEmptySize sizeExpando; if (IsWindow(m_pBtnExpando) && m_mapWndSize.Lookup(m_pBtnExpando, sizeExpando)) { CXTPEmptyRect rcButton; rcButton.left = m_ptMargin.x + 3; rcButton.right = rcButton.left + sizeExpando.cx; // vertically center. rcButton.top = m_rcCommandButtons.top + (m_rcCommandButtons.Height()-sizeExpando.cy)/2; CXTPEmptySize sizeVerify; if (IsWindow(m_pBtnVerify) && m_mapWndSize.Lookup(m_pBtnVerify, sizeVerify)) { rcButton.top = m_rcCommandButtons.top + m_ptMargin.y; } rcButton.bottom = rcButton.top + sizeExpando.cy; MoveButton(m_pBtnExpando, rcButton); } } void CXTPTaskDialogClient::SetLinkCtrlPos() { if (IsHyperlinksEnabled()) { if (m_wndContent) m_wndContent.MoveWindow(m_rcContent); if (m_wndExpandedInformation) m_wndExpandedInformation.MoveWindow(m_rcExpandedInformation); if (m_wndFooter) m_wndFooter.MoveWindow(m_rcFooter); if (m_wndExpandedInformation) m_wndExpandedInformation.ShowWindow(m_bExpanded ? SW_SHOWNOACTIVATE : SW_HIDE); } } //--------------------------------------------------------------------------- // Layout //--------------------------------------------------------------------------- int CXTPTaskDialogClient::CalcIdealTextWidth(const CStringMarkup& strItemText, int nMinWidth, BOOL bLargeFont) { if (strItemText.IsEmpty()) return nMinWidth; CSize sizeText(nMinWidth, 0); if (strItemText.m_pUIElement) { if (XTPCalcIdealTextSize(m_pMarkupContext, strItemText.m_pUIElement, sizeText, bLargeFont? m_fontLarge: m_font, bLargeFont? 275: 330, bLargeFont? 14: 7)) { nMinWidth = max(nMinWidth, sizeText.cx); } } else { if (XTPCalcIdealTextSize(strItemText, sizeText, bLargeFont? m_fontLarge: m_font, bLargeFont? 275: 330, bLargeFont? 14: 7)) { nMinWidth = max(nMinWidth, sizeText.cx); } } return nMinWidth; } CRect CXTPTaskDialogClient::CalcTextRect(const CStringMarkup& strItemText, int nWidth, BOOL bLargeFont) { CRect rcItemText(0, 0, 0, 0); if (strItemText.m_pUIElement) { XTPMarkupSetDefaultFont(m_pMarkupContext, bLargeFont? m_fontLarge: m_font, COLORREF_NULL); CSize sizeText = XTPMarkupMeasureElement(strItemText.m_pUIElement, nWidth, INT_MAX); rcItemText.SetRect(0, 0, nWidth, sizeText.cy); } else { CSize sizeText(nWidth, 0); if (XTPCalcTextSize(strItemText, sizeText, bLargeFont? m_fontLarge: m_font)) { rcItemText.SetRect(0, 0, nWidth, sizeText.cy); } } return rcItemText; } CRect CXTPTaskDialogClient::CalcCommandRect(int nWidth) { CRect rcCommand(0, 0, nWidth, 0); if (m_pBtnExpando == 0 && m_pBtnVerify == 0 && m_arrCommandButtons.GetSize() == 0) return rcCommand; int nMinHeight = 0; int nLeftMargin = 0; CXTPEmptySize sizeButton; if (m_pBtnVerify && m_mapWndSize.Lookup(m_pBtnVerify, sizeButton)) { nMinHeight = sizeButton.cy; nLeftMargin = sizeButton.cx; } if (m_pBtnExpando && m_mapWndSize.Lookup(m_pBtnExpando, sizeButton)) { nMinHeight += sizeButton.cy; nLeftMargin = max(nLeftMargin, sizeButton.cx); } if (nLeftMargin) nWidth -= nLeftMargin + m_ptBtnSpacing.x; int i, nCount = (int)m_arrCommandButtons.GetSize(); int x = 0; int nMaxWidth = 0; for (i = 0; i < nCount; i++) { CButton* pButton = m_arrCommandButtons[i]; if (m_mapWndSize.Lookup(pButton, sizeButton)) { // no more room, adjust height. if (x != 0 && x + sizeButton.cx > nWidth) { nMaxWidth = max(nMaxWidth, x - m_ptBtnSpacing.x); x = 0; rcCommand.bottom += m_ptBtnSpacing.y; } // first button in row, adjust height. if (x == 0) rcCommand.bottom += sizeButton.cy; x += sizeButton.cx + m_ptBtnSpacing.x; } } nMaxWidth = max(nMaxWidth, x - m_ptBtnSpacing.x); rcCommand.left = nWidth - nMaxWidth; if (nLeftMargin) rcCommand.left += nLeftMargin + m_ptBtnSpacing.x; if (nMinHeight > rcCommand.Height()) rcCommand.bottom = rcCommand.top + nMinHeight; rcCommand.bottom += m_ptMargin.y * 2 - 2; return rcCommand; } int CXTPTaskDialogClient::CalcClientWidth() { int nIdealWidth = m_nMinClientWidth; if (HasFixedWidth()) { CSize sizeBase = ::GetDialogBaseUnits(); int cxWidth = ::MulDiv(m_pConfig->cxWidth, sizeBase.cx, 4); nIdealWidth = max(cxWidth - m_ptMargin.x * 2, nIdealWidth); return nIdealWidth; } int nCommandButtonWidth = -m_ptBtnSpacing.x + m_ptMargin.x * 2, nCount, i; nCount = (int)m_arrCommandButtons.GetSize(); for (i = 0; i < nCount; ++i) { CSize size; if (m_mapWndSize.Lookup(m_arrCommandButtons[i], size)) nCommandButtonWidth += size.cx + m_ptBtnSpacing.x; } if (!HasLinkButtons()) { nIdealWidth = max(nIdealWidth, nCommandButtonWidth); } if (m_pBtnVerify->GetSafeHwnd()) { CSize size; if (m_mapWndSize.Lookup(m_pBtnVerify, size)) { nIdealWidth = max(nIdealWidth, size.cx + nCommandButtonWidth + m_ptMargin.x); } } if (m_pBtnExpando->GetSafeHwnd()) { CSize size; if (m_mapWndSize.Lookup(m_pBtnExpando , size)) { nIdealWidth = max(nIdealWidth, size.cx + nCommandButtonWidth + m_ptMargin.x); } } int nMainIconMargin = (m_hIconMain ? (m_sizeIconMain.cx + m_ptMargin.x): 0); int nFooterIconMargin = (m_hIconFooter ? (m_sizeIconFooter.cx + m_ptMargin.x): 0); int nExpanIconMargin = IsExpandFooterArea() ? nFooterIconMargin : nMainIconMargin; nCount = (int)m_arrRadioButtons.GetSize(); for (i = 0; i < nCount; ++i) { CSize size; if (m_mapWndSize.Lookup(m_arrRadioButtons[i], size)) nIdealWidth = max(nIdealWidth, size.cx + nMainIconMargin); } CXTPEmptySize size; if (m_mapWndSize.Lookup(m_pBtnVerify, size)) nIdealWidth = max(nIdealWidth, size.cx); if (m_mapWndSize.Lookup(m_pBtnExpando, size)) nIdealWidth = max(nIdealWidth, size.cx); int nWidth = CalcIdealTextWidth(m_strMainInstruction, nIdealWidth - nMainIconMargin, TRUE); nIdealWidth = max(nIdealWidth, nWidth + nMainIconMargin); nWidth = CalcIdealTextWidth(m_strContent, nIdealWidth - nMainIconMargin, FALSE); nIdealWidth = max(nIdealWidth, nWidth + nMainIconMargin); if (HasLinkButtons()) { for (i = 0; i < (int)m_pConfig->cButtons; ++i) { CString strButton = LoadItemString(m_pConfig->pButtons[i].pszButtonText); nWidth = CalcLinkButtonIdealWidth(strButton, nIdealWidth - nMainIconMargin); nIdealWidth = max(nIdealWidth, 2 + nWidth + nMainIconMargin); } } nWidth = CalcIdealTextWidth(m_strExpandedInformation, nIdealWidth - nExpanIconMargin, FALSE); nIdealWidth = max(nIdealWidth, nWidth + nExpanIconMargin); nWidth = CalcIdealTextWidth(m_strFooter, nIdealWidth - nFooterIconMargin, FALSE); nIdealWidth = max(nIdealWidth, nWidth + nFooterIconMargin); nIdealWidth = min(nIdealWidth, m_nMaxClientWidth); return nIdealWidth; } CSize CXTPTaskDialogClient::CalcDynamicLayout(int nIdealWidth) { int nMainIconMargin = m_hIconMain ? (m_sizeIconMain.cx + m_ptMargin.x) : 0; int nFooterIconMargin = m_hIconFooter ? (m_sizeIconFooter.cx + m_ptMargin.x) : 0; m_rcMainInstruction = CalcTextRect(m_strMainInstruction, nIdealWidth - nMainIconMargin, TRUE); if (!m_rcMainInstruction.IsRectEmpty()) m_rcMainInstruction.OffsetRect(m_ptMargin.x + nMainIconMargin, m_ptMargin.y); m_rcContent = CalcTextRect(m_strContent, nIdealWidth - nMainIconMargin, FALSE); m_rcContent.OffsetRect(m_ptMargin.x + nMainIconMargin, m_rcMainInstruction.bottom + m_ptMargin.y + 1); int nLinkTop = m_rcContent.bottom + m_ptPadding.y; if (nLinkTop < m_ptMargin.y * 4 - 3) nLinkTop = m_ptMargin.y * 4 - 3; if (!IsExpandFooterArea()) { if (!m_strExpandedInformation.IsEmpty()) { if (m_bExpanded) { m_rcExpandedInformation = CalcTextRect(m_strExpandedInformation, nIdealWidth - nMainIconMargin, FALSE); m_rcExpandedInformation.OffsetRect(m_ptMargin.x + nMainIconMargin, nLinkTop + m_ptPadding.y); } else { m_rcExpandedInformation.SetRect(m_rcContent.left, nLinkTop, m_rcContent.right, nLinkTop + m_ptPadding.y); } nLinkTop += m_rcExpandedInformation.Height() + m_ptPadding.y; } else { m_rcExpandedInformation.SetRect(m_rcContent.left, nLinkTop, m_rcContent.right, nLinkTop); } } if (m_wndProgressBar.GetSafeHwnd()) { CRect rcProgressBar(m_rcContent.left, nLinkTop + m_ptMargin.y, nIdealWidth + m_ptMargin.x, nLinkTop + m_ptMargin.y * 5/2); m_wndProgressBar.MoveWindow(rcProgressBar); nLinkTop += rcProgressBar.Height() + m_ptMargin.y; } if (m_arrRadioButtons.GetSize() > 0) { nLinkTop += m_ptMargin.y; m_rcRadioButtons = CRect(m_rcContent.left + m_ptMargin.x, nLinkTop, nIdealWidth, nLinkTop); for (int i = 0; i < m_arrRadioButtons.GetSize(); i++) { CButton* pButton = m_arrRadioButtons[i]; CSize sizeButton; if (m_mapWndSize.Lookup(pButton, sizeButton)) { pButton->MoveWindow(m_rcRadioButtons.left, nLinkTop, sizeButton.cx, sizeButton.cy); nLinkTop += sizeButton.cy + 3; } } m_rcRadioButtons.bottom = nLinkTop; } else { m_rcRadioButtons = CRect(m_rcContent.left + 1, nLinkTop, m_rcContent.right, nLinkTop); } if (m_wndInputBox.GetSafeHwnd()) { CRect rcInputBox(m_rcContent.left, nLinkTop + m_ptMargin.y, nIdealWidth + m_ptMargin.x, nLinkTop + m_ptMargin.y + m_ptMargin.y * 2); m_wndInputBox.MoveWindow(rcInputBox); nLinkTop += rcInputBox.Height() + m_ptMargin.y; } m_rcLinkButtons = CRect(m_rcContent.left + 1, nLinkTop + 1, m_ptMargin.y + nIdealWidth - 1, nLinkTop + 1); for (int i = 0; i < (int)m_arrLinkButtons.GetSize(); ++i) { CString strButton = LoadItemString(m_pConfig->pButtons[i].pszButtonText); CButton* pButton = m_arrLinkButtons[i]; CSize sizeButton = CalcLinkButtonSize((CXTPButton*)pButton, strButton, m_rcLinkButtons.Width()); sizeButton.cx = m_rcLinkButtons.Width(); m_mapWndSize[pButton] = sizeButton; m_rcLinkButtons.bottom += sizeButton.cy; } if (m_arrLinkButtons.GetSize() > 0) m_rcLinkButtons.bottom += m_ptMargin.y; m_rcCommandButtons = CalcCommandRect(nIdealWidth); m_rcCommandButtons.OffsetRect(m_ptMargin.x, m_rcLinkButtons.bottom + m_ptMargin.y + m_ptPadding.y); int nBottom = m_rcCommandButtons.bottom; if (!m_strFooter.IsEmpty()) { m_rcFooter = CalcTextRect(m_strFooter, nIdealWidth - nFooterIconMargin, FALSE); m_rcFooter.OffsetRect(m_ptMargin.x + nFooterIconMargin - 1, nBottom + m_ptMargin.y + 1); nBottom += m_rcFooter.Height() + 2 * m_ptMargin.y + 1; } if (IsExpandFooterArea()) { if (!m_strExpandedInformation.IsEmpty() && m_bExpanded) { m_rcExpandedInformation = CalcTextRect(m_strExpandedInformation, nIdealWidth, FALSE); m_rcExpandedInformation.OffsetRect(m_ptMargin.x, nBottom + m_ptMargin.y); nBottom += m_rcExpandedInformation.Height() + 2 * m_ptMargin.y; } else { m_rcExpandedInformation.SetRect(m_rcFooter.left, nBottom, m_rcFooter.right, nBottom); } } return CSize(nIdealWidth + m_ptMargin.x * 2, nBottom); } void CXTPTaskDialogClient::RecalcLayout(BOOL bMoveWindow) { UpdateZOrder(); CSize szClient = CalcDynamicLayout(CalcClientWidth()); SetCommandButtonPos(); SetLinkButtonPos(); SetVerifyButtonPos(); SetExpandoButtonPos(); SetLinkCtrlPos(); m_strContent.SetFinalRect(m_rcContent); m_strMainInstruction.SetFinalRect(m_rcMainInstruction); m_strExpandedInformation.SetFinalRect(m_rcExpandedInformation); m_strFooter.SetFinalRect(m_rcFooter); ResizeParentToFit(szClient, bMoveWindow); RedrawWindow(0, 0, RDW_ALLCHILDREN | RDW_INVALIDATE); } BOOL CXTPTaskDialogClient::ResizeParentToFit(CSize szClient, BOOL bMoveWindow) { CXTPWindowRect rc(this); CRect rcParent = IsPositionRelativeToWindow()? CXTPWindowRect(m_pConfig->hwndParent): XTPMultiMonitor()->GetWorkArea(m_pConfig->hwndParent); CPoint ptPos((rcParent.left + rcParent.right - szClient.cx) / 2 - 3, (rcParent.top + rcParent.bottom - szClient.cy) / 2 - 12); CRect rcWindow(ptPos, szClient); AdjustWindowRectEx(rcWindow, GetStyle(), FALSE, GetExStyle()); //rcWindow.InflateRect(m_ptMargin.x, m_ptMargin.y); if (bMoveWindow) MoveWindow(rcWindow); else SetWindowPos(0, 0, 0, rcWindow.Width(), rcWindow.Height(), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); return TRUE; } //--------------------------------------------------------------------------- // Rendering //--------------------------------------------------------------------------- void CXTPTaskDialogClient::DrawBackground(CDC* pDC, CRect rect) { pDC->FillSolidRect(&rect, m_crFooter); if (m_bThemeReady) { pDC->FillSolidRect(rect.left, rect.top, rect.Width(), m_rcCommandButtons.top, m_crContent); if (m_rcCommandButtons.top != m_rcCommandButtons.bottom) { pDC->FillSolidRect(rect.left, m_rcCommandButtons.top, rect.Width(), 1, m_cr3DLight); } if (!m_rcFooter.IsRectEmpty()) { pDC->FillSolidRect(rect.left, m_rcCommandButtons.bottom, rect.Width(), 1, m_cr3DLight); pDC->FillSolidRect(rect.left, m_rcCommandButtons.bottom + 1, rect.Width(), 1, m_cr3DHighLight); } if (m_bExpanded && !m_strExpandedInformation.IsEmpty() && IsExpandFooterArea() && !m_rcExpandedInformation.IsRectEmpty()) { pDC->FillSolidRect(rect.left, m_rcExpandedInformation.top - m_ptMargin.y, rect.Width(), 1, m_cr3DLight); pDC->FillSolidRect(rect.left, m_rcExpandedInformation.top - m_ptMargin.y + 1, rect.Width(), 1, m_cr3DHighLight); } } else { if (!m_rcFooter.IsRectEmpty()) { pDC->FillSolidRect(rect.left, m_rcCommandButtons.bottom + 1, rect.Width(), 1, m_cr3DShadow); } if (m_bExpanded && !m_strExpandedInformation.IsEmpty() && IsExpandFooterArea() && !m_rcExpandedInformation.IsRectEmpty()) { pDC->FillSolidRect(rect.left, m_rcExpandedInformation.top - m_ptMargin.y, rect.Width(), 1, m_cr3DShadow); } } } void CXTPTaskDialogClient::DrawIcon(CDC* pDC, HICON hIcon, CPoint pt, CSize sz) { DWORD dwLayout = XTPDrawHelpers()->IsContextRTL(pDC); if (dwLayout & LAYOUT_RTL) XTPDrawHelpers()->SetContextRTL(pDC, dwLayout | LAYOUT_BITMAPORIENTATIONPRESERVED); ::DrawIconEx(*pDC, pt.x, pt.y, hIcon, sz.cx, sz.cy, 0, NULL, DI_NORMAL); if (dwLayout & LAYOUT_RTL) XTPDrawHelpers()->SetContextRTL(pDC, dwLayout); } void CXTPTaskDialogClient::DrawText(CDC* pDC, const CStringMarkup& strItemText, CRect rcItem, COLORREF clrText, CFont* pFont) { if (!rcItem.IsRectEmpty() && !strItemText.IsEmpty()) { if (strItemText.m_pUIElement) { XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)pFont->GetSafeHandle(), clrText); XTPMarkupRenderElement(strItemText.m_pUIElement, pDC->GetSafeHdc(), strItemText.m_rcFinalRect); } else { pDC->SetTextColor(clrText); CXTPFontDC fontDC(pDC, pFont); pDC->DrawText(strItemText, rcItem, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_TOP); } } } void CXTPTaskDialogClient::DrawMainInstruction(CDC* pDC) { if (m_hIconMain) { DrawIcon(pDC, m_hIconMain, m_ptMargin, m_sizeIconMain); } DrawText(pDC, m_strMainInstruction, m_rcMainInstruction, m_crMainText, &m_fontLarge); } void CXTPTaskDialogClient::DrawContent(CDC* pDC) { if (m_rcContent.IsRectEmpty()) return; if (!::IsWindow(m_wndContent.m_hWnd)) { DrawText(pDC, m_strContent, m_rcContent, m_crContentText, &m_font); } } void CXTPTaskDialogClient::DrawExpandedInfo(CDC* pDC) { if (m_rcExpandedInformation.IsRectEmpty() || m_strExpandedInformation.IsEmpty() || !m_bExpanded) return; if (!::IsWindow(m_wndExpandedInformation.m_hWnd)) { DrawText(pDC, m_strExpandedInformation, m_rcExpandedInformation, IsExpandFooterArea() ? m_crFooterText : m_crContentText, &m_font); } } void CXTPTaskDialogClient::DrawFootNote(CDC* pDC) { if (m_rcFooter.IsRectEmpty()) return; if (m_hIconFooter) { DrawIcon(pDC, m_hIconFooter, CPoint(m_ptMargin.x + 2, m_rcFooter.top), m_sizeIconFooter); } if (!::IsWindow(m_wndFooter.m_hWnd)) { DrawText(pDC, m_strFooter, m_rcFooter, m_crFooterText, &m_font); } } void CXTPTaskDialogClient::OnExpandExpandoClicked() { if (!m_pBtnExpando) return; CString strButtonText = m_bExpanded ? m_strExpandedControlText: m_strCollapsedControlText; m_pBtnExpando->SetWindowText(strButtonText); m_pBtnExpando->SetChecked(m_bExpanded); RecalcLayout(); } void CXTPTaskDialogClient::OnInputBoxChanged() { SendNotify(TDN_INPUTBOX_CHANGED); }