You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1192 lines
27 KiB
C++

2 years ago
// XTPTaskDialogControls.cpp
//
// 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 "Common/Resource.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPWinThemeWrapper.h"
#include "Common/XTPSystemHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPMarkupRender.h"
#include "../Util/XTPControlTheme.h"
#include "../Button/XTPButton.h"
#include "../Button/XTPButtonTheme.h"
#include "XTPTaskDialogAPI.h"
#include "XTPTaskDialogControls.h"
#ifndef WM_UPDATEUISTATE
#define WM_UPDATEUISTATE 0x0128
#endif
#ifndef WM_QUERYUISTATE
#define WM_QUERYUISTATE 0x0129
#endif
#ifndef UISF_HIDEACCEL
#define UISF_HIDEACCEL 0x2
#endif
#ifndef UISF_HIDEFOCUS
#define UISF_HIDEFOCUS 0x1
#endif
#ifndef ODS_NOACCEL
#define ODS_NOACCEL 0x0100
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CXTPTaskDialogLinkCtrl
CXTPTaskDialogLinkCtrl::CXTPTaskDialogLinkCtrl()
: m_nFocused(-1)
, m_crBack(COLORREF_NULL)
, m_crText(GetXtremeColor(COLOR_WINDOWTEXT))
, m_crTextLink(RGB(0x00, 0x66, 0xcc))
, m_hcurHand(NULL)
, m_bPreSubclassWindow(TRUE)
{
// try loading system hand cursor first.
m_hcurHand = ::LoadCursor(NULL, MAKEINTRESOURCE(32649));
// if this fails load default.
if (m_hcurHand == NULL)
{
m_hcurHand = XTPResourceManager()->LoadCursor(XTP_IDC_HAND);
ASSERT(m_hcurHand != NULL);
}
}
CXTPTaskDialogLinkCtrl::~CXTPTaskDialogLinkCtrl()
{
RemoveAllLinks();
}
void CXTPTaskDialogLinkCtrl::RemoveAllLinks()
{
for (int i = 0; i < m_arrLinks.GetSize(); i++)
{
delete m_arrLinks[i];
}
m_arrLinks.RemoveAll();
}
IMPLEMENT_DYNCREATE(CXTPTaskDialogLinkCtrl, CWnd)
BEGIN_MESSAGE_MAP(CXTPTaskDialogLinkCtrl, CWnd)
//{{AFX_MSG_MAP(CXTPTaskDialogLinkCtrl)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_NCHITTEST_EX()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_GETDLGCODE()
ON_WM_KEYDOWN()
ON_MESSAGE(WM_SETTEXT, OnSetText)
ON_MESSAGE(WM_UPDATEUISTATE, OnUpdateUIState)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPTaskDialogLinkCtrl message handlers
CXTPTaskDialogLinkCtrl::LINKITEM* CXTPTaskDialogLinkCtrl::HitTest(CPoint pt) const
{
for (int i = 0; i < m_arrLinks.GetSize(); i++)
{
LINKITEM* pItem = m_arrLinks[i];
for (int j = 0; j < pItem->arrParts.GetSize(); j++)
{
if (::PtInRect(&pItem->arrParts[j], pt))
return pItem;
}
}
return NULL;
}
void CXTPTaskDialogLinkCtrl::OnPaint()
{
CPaintDC dc(this);
CXTPClientRect rClient(this);
CXTPBufferDC memDC(dc);
if (m_crBack != COLORREF_NULL)
memDC.FillSolidRect(&rClient, m_crBack);
else
{
HBRUSH hBrush = (HBRUSH)GetParent()->SendMessage(WM_CTLCOLORSTATIC, (WPARAM)memDC.GetSafeHdc(), (LPARAM)m_hWnd);
if (hBrush)
{
::FillRect(memDC.GetSafeHdc(), rClient, hBrush);
}
else
{
memDC.FillSolidRect(rClient, GetXtremeColor(COLOR_3DFACE));
}
}
memDC.SetBkMode(TRANSPARENT);
DrawText(&memDC, rClient);
}
int CXTPTaskDialogLinkCtrl::DrawTextPartText(CDC* pDC, CString strBuffer, int x, int y, LINKITEM* pItem)
{
if (strBuffer.IsEmpty())
return 0;
CSize sz = pDC->GetTextExtent(strBuffer);
pDC->DrawText(strBuffer, CRect(x, y, x + sz.cx + 10, y + sz.cy), DT_TOP | DT_LEFT | DT_NOPREFIX | DT_SINGLELINE);
CRect rcItem(x, y, x + sz.cx, y + sz.cy);
if (pItem)
{
if (m_nFocused == pItem->nIndex)
{
COLORREF clr = pDC->SetTextColor(m_crText);
pDC->DrawFocusRect(rcItem);
pDC->SetTextColor(clr);
}
pItem->arrParts.Add(rcItem);
}
return sz.cx;
}
void CXTPTaskDialogLinkCtrl::DrawTextPart(CDC* pDC, int&x, int&y, int nWidth, CString strBuffer, LINKITEM* pItem)
{
CXTPFontDC fontDC(pDC, pItem && m_fontUL.GetSafeHandle() ? &m_fontUL : GetFont(), pItem ? m_crTextLink :m_crText);
int nTextHeight = pDC->GetTextExtent(_T("XXX"), 3).cy;
int nStartPos = 0;
int nGoodPos = 0;
while (nStartPos < strBuffer.GetLength())
{
TCHAR t = strBuffer[nStartPos];
if (t == _T(' ') || t == _T('\t') || t == _T('\n'))
{
CString strPart = strBuffer.Left(nStartPos);
if (x + pDC->GetTextExtent(strPart).cx > nWidth)
{
if (x == 0 && nGoodPos == 0)
nGoodPos = nStartPos - 1;
if (nGoodPos > 0)
{
strPart = strBuffer.Left(nGoodPos);
DrawTextPartText(pDC, strPart, x, y, pItem);
strBuffer.Delete(0, nGoodPos + 1);
nStartPos -= nGoodPos + 1;
}
else
{
if (strBuffer[0] == _T(' '))
{
strBuffer.Delete(0);
nStartPos--;
}
}
x = 0;
y += nTextHeight;
nGoodPos = 0;
if (t != _T('\n')) continue;
}
else
nGoodPos = nStartPos;
}
if (t == _T('\n'))
{
CString strPart = strBuffer.Left(nStartPos);
DrawTextPartText(pDC, strPart, x, y, pItem);
strBuffer.Delete(0, nStartPos + 1);
x = 0;
y += nTextHeight;
nStartPos = nGoodPos = 0;
continue;
}
nStartPos++;
}
CString strPart = strBuffer;
if (x + pDC->GetTextExtent(strPart).cx > nWidth)
{
if (nGoodPos != 0)
{
strPart = strBuffer.Left(nGoodPos);
DrawTextPartText(pDC, strPart, x, y, pItem);
strBuffer.Delete(0, nGoodPos + 1);
}
x = 0;
y += nTextHeight;
}
int nLength = DrawTextPartText(pDC, strBuffer, x, y, pItem);
x += nLength;
}
void CXTPTaskDialogLinkCtrl::DrawText(CDC* pDC, CRect rClient)
{
if (m_arrLinks.GetSize() == 0)
{
CXTPFontDC fontDC(pDC, GetFont(), m_crText);
pDC->DrawText(m_strBuffer, rClient, DT_TOP | DT_WORDBREAK | DT_NOPREFIX);
return;
}
int x = 0, y = 0, nWidth = rClient.Width();
CString strBuffer = m_strBuffer;
int nPos = 0;
for (int i = 0; i < m_arrLinks.GetSize(); i++)
{
LINKITEM* pItem = m_arrLinks.GetAt(i);
int iStart = pItem->nStart;
int iCount = pItem->strLabel.GetLength();
pItem->arrParts.RemoveAll();
DrawTextPart(pDC, x, y, nWidth, m_strBuffer.Mid(nPos, iStart - nPos), NULL);
DrawTextPart(pDC, x, y, nWidth, m_strBuffer.Mid(iStart, iCount), pItem);
nPos = iStart + iCount;
}
DrawTextPart(pDC, x, y, nWidth, m_strBuffer.Mid(nPos, m_strBuffer.GetLength() - nPos), NULL);
}
BOOL CXTPTaskDialogLinkCtrl::OnEraseBkgnd(CDC* pDC)
{
UNREFERENCED_PARAMETER(pDC);
return TRUE;
}
BOOL CXTPTaskDialogLinkCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
//
// PreCreateWindow is called when a control is dynamically
// created. We want to set m_bPreSubclassWindow to FALSE
// here so the control is initialized from CWnd::Create and
// not CWnd::PreSubclassWindow.
//
m_bPreSubclassWindow = FALSE;
return TRUE;
}
void CXTPTaskDialogLinkCtrl::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
if (m_bPreSubclassWindow)
{
RemoveAllLinks();
GetWindowText(m_strBuffer);
ExtractLinks(m_strBuffer);
DefWindowProc(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_strBuffer);
if (m_arrLinks.GetSize() > 0 && GetFont())
{
LOGFONT lf;
GetFont()->GetLogFont(&lf);
lf.lfUnderline = 1;
m_fontUL.DeleteObject();
m_fontUL.CreateFontIndirect(&lf);
}
Invalidate(FALSE);
}
}
LRESULT CXTPTaskDialogLinkCtrl::OnSetText(WPARAM, LPARAM lParam)
{
RemoveAllLinks();
m_strBuffer = (LPCTSTR)lParam;
ExtractLinks(m_strBuffer);
DefWindowProc(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_strBuffer);
Invalidate(FALSE);
return m_strBuffer.GetLength();
}
BOOL CXTPTaskDialogLinkCtrl::Create(const CRect& rect, CString& strBuffer, CFont* pFont, CWnd* pParentWnd)
{
RemoveAllLinks();
if (strBuffer.IsEmpty() || !pFont->GetSafeHandle() || !::IsWindow(pParentWnd->GetSafeHwnd()))
return FALSE;
m_strBuffer = strBuffer;
if (!ExtractLinks(m_strBuffer))
return FALSE;
if (!CStatic::Create(0, WS_CHILD | WS_VISIBLE | WS_TABSTOP, rect, pParentWnd, 0))
return FALSE;
LOGFONT lf;
pFont->GetLogFont(&lf);
lf.lfUnderline = 1;
m_fontUL.DeleteObject();
m_fontUL.CreateFontIndirect(&lf);
SetFont(pFont);
DefWindowProc(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_strBuffer);
strBuffer = m_strBuffer;
return TRUE;
}
DWORD CXTPTaskDialogLinkCtrl::GetLinkPos(CString strBuffer, int iPos /*= 0*/)
{
strBuffer.MakeLower();
int iStart = strBuffer.Find(_T("<a href=\""), iPos);
if (iStart == -1)
return NULL;
int iValid = strBuffer.Find(_T("\""), iStart);
if (iValid == -1)
return NULL;
int iEnd = strBuffer.Find(_T("</a>"), iValid);
if (iEnd == -1)
return NULL;
return MAKELONG(iStart, (iEnd + 4) - iStart);
}
BOOL CXTPTaskDialogLinkCtrl::ExtractLinks(CString& strBuffer)
{
m_arrLinks.RemoveAll();
for (DWORD dwPos = GetLinkPos(strBuffer); dwPos;)
{
int iStart = LOWORD(dwPos);
int iCount = HIWORD(dwPos);
LINKITEM* pItem = new LINKITEM();
CString strLink = strBuffer.Mid(iStart,iCount);
// extract the link and execute strings from the link.
AfxExtractSubString(pItem->strUrl, strLink, 1, '"');
AfxExtractSubString(pItem->strUrl, pItem->strUrl, 0, '"');
AfxExtractSubString(pItem->strLabel, strLink, 1, '>');
AfxExtractSubString(pItem->strLabel, pItem->strLabel, 0, '<');
// reformat text to remove link tags.
CString strTemp = strBuffer.Left(iStart);
strTemp += pItem->strLabel;
strTemp += strBuffer.Right(strBuffer.GetLength()-(iStart + iCount));
strBuffer = strTemp;
pItem->nStart = iStart;
pItem->nIndex = (int)m_arrLinks.Add(pItem);
dwPos = GetLinkPos(strBuffer);
}
return (m_arrLinks.GetSize() > 0);
}
LRESULT CXTPTaskDialogLinkCtrl::OnNcHitTest(CPoint point)
{
ScreenToClient(&point);
if (HitTest(point))
{
return HTCLIENT;
}
return (LRESULT)HTTRANSPARENT;
}
void CXTPTaskDialogLinkCtrl::FocusItem(int iFocusItem)
{
if (m_nFocused != iFocusItem)
{
m_nFocused = iFocusItem;
Invalidate(FALSE);
}
}
UINT CXTPTaskDialogLinkCtrl::OnGetDlgCode()
{
const MSG& msg = AfxGetThreadState()->m_lastSentMsg;
if (!msg.lParam)
return DLGC_UNDEFPUSHBUTTON;
LPMSG lpMsg = (LPMSG)msg.lParam;
if (lpMsg->message == WM_CHAR)
{
if (lpMsg->wParam == VK_TAB)
return DLGC_WANTTAB;
if (lpMsg->wParam == VK_RETURN)
return DLGC_WANTCHARS;
}
if (lpMsg->message == WM_KEYDOWN)
{
UINT nChar = (UINT)lpMsg->wParam;
if ((nChar == VK_RETURN || nChar == VK_SPACE) && (m_nFocused != -1))
return DLGC_WANTALLKEYS;
if (nChar == VK_TAB)
{
if (GetKeyState(VK_SHIFT) >= 0)
{
if (m_nFocused < m_arrLinks.GetSize() - 1)
{
FocusItem(m_nFocused + 1);
return DLGC_WANTTAB;
}
}
else
{
if (m_nFocused > 0)
{
FocusItem(m_nFocused - 1);
return DLGC_WANTTAB;
}
}
}
}
return DLGC_UNDEFPUSHBUTTON;
}
void CXTPTaskDialogLinkCtrl::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
if ((nChar == VK_RETURN || nChar == VK_SPACE) && (m_nFocused != -1))
{
GetOwner()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
}
}
void CXTPTaskDialogLinkCtrl::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
LINKITEM* pItem = HitTest(point);
if (pItem)
{
FocusItem(pItem->nIndex);
SetFocus();
}
else
{
FocusItem(-1);
}
}
void CXTPTaskDialogLinkCtrl::OnSetFocus(CWnd* /*pOldWnd*/)
{
if (m_nFocused == -1)
{
FocusItem(0);
}
}
void CXTPTaskDialogLinkCtrl::OnKillFocus(CWnd* /*pNewWnd*/)
{
FocusItem(-1);
}
CXTPTaskDialogLinkCtrl::LINKITEM* CXTPTaskDialogLinkCtrl::GetFocusedLink() const
{
return m_nFocused >= 0 && m_nFocused < m_arrLinks.GetSize() ? m_arrLinks[m_nFocused] : NULL;
}
void CXTPTaskDialogLinkCtrl::OnLButtonUp(UINT /*nFlags*/, CPoint point)
{
LINKITEM* pItem = HitTest(point);
if (pItem && pItem->nIndex == m_nFocused)
{
GetOwner()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd );
}
}
BOOL CXTPTaskDialogLinkCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT && (m_hcurHand != NULL))
{
::SetCursor(m_hcurHand);
return TRUE;
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
LRESULT CXTPTaskDialogLinkCtrl::OnUpdateUIState(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = ::DefWindowProc(m_hWnd, WM_UPDATEUISTATE, wParam, lParam);
Invalidate(FALSE);
return lResult;
}
//===========================================================================
// CXTPTaskButtonTheme
//===========================================================================
const UINT xtpDluMargin = 5; // non-client margin.
CXTPTaskButtonTheme::CXTPTaskButtonTheme(BOOL bThemeReady)
{
m_bThemeReady = bThemeReady;
m_ptMargin = XTPDlu2Pix(xtpDluMargin, xtpDluMargin);
m_pFontTitle = NULL;
m_bOffsetHiliteText = FALSE;
m_nBorderWidth = 3;
}
CXTPTaskButtonTheme::CXTPTaskButtonTheme()
{
m_themeButton->OpenThemeData(0, L"BUTTON");
m_bThemeReady = m_themeButton->IsAppThemed();
m_ptMargin = XTPDlu2Pix(xtpDluMargin, xtpDluMargin);
m_pFontTitle = NULL;
m_bOffsetHiliteText = FALSE;
m_nBorderWidth = 3;
}
void CXTPTaskButtonTheme::DrawButton(CDC* pDC, CXTPButton* pButton)
{
if (!DrawWinThemeBackground(pDC, pButton))
{
DrawButtonThemeBackground(pDC, pButton);
}
DrawButtonText(pDC, pButton);
DrawButtonIcon(pDC, pButton);
// Draw the focus rect if style is set and we have focus.
if (::GetFocus() == pButton->GetSafeHwnd() && ((pButton->SendMessage(WM_QUERYUISTATE) & UISF_HIDEFOCUS) == 0))
{
DrawFocusRect(pDC, pButton);
}
}
BOOL CXTPTaskButtonTheme::DrawButtonThemeBackground(CDC* pDC, CXTPButton* pButton)
{
CXTPClientRect rcItem(pButton);
if (pButton->GetChecked())
pDC->FillSolidRect(rcItem, m_crBorderHilite);
else if (pButton->IsPushed() || pButton->IsHighlighted())
{
pDC->FillSolidRect(rcItem, m_crBack);
}
else
{
HBRUSH hBrush = (HBRUSH)pButton->GetParent()->SendMessage(WM_CTLCOLORBTN, (WPARAM)pDC->GetSafeHdc(), (LPARAM)pButton->GetSafeHwnd());
if (hBrush)
{
::FillRect(pDC->GetSafeHdc(), rcItem, hBrush);
}
else
{
pDC->FillSolidRect(rcItem, m_crBack);
}
}
if (pButton->IsPushed())
{
pDC->Draw3dRect(rcItem, m_crBorder3DShadow, m_crBorder3DHilite);
rcItem.DeflateRect(1,1);
pDC->Draw3dRect(rcItem, m_crBorderShadow, m_crBorderHilite);
}
else if (pButton->IsHighlighted())
{
pDC->Draw3dRect(rcItem, m_crBorder3DHilite, m_crBorder3DShadow);
rcItem.DeflateRect(1,1);
pDC->Draw3dRect(rcItem, m_crBorderHilite, m_crBorderShadow);
}
if (pButton->GetButtonStyle() == BS_DEFPUSHBUTTON)
{
pDC->Draw3dRect(CXTPClientRect(pButton), m_crBorderActive, m_crBorderActive);
}
return TRUE;
}
BOOL CXTPTaskButtonTheme::DrawWinThemeBackground(CDC* pDC, CXTPButton* pButton)
{
if (m_bThemeReady)
{
CXTPClientRect rcItem(pButton);
HBRUSH hBrush = (HBRUSH)pButton->GetParent()->SendMessage(WM_CTLCOLORBTN, (WPARAM)pDC->GetSafeHdc(), (LPARAM)pButton->GetSafeHwnd());
if (hBrush)
{
::FillRect(pDC->GetSafeHdc(), rcItem, hBrush);
}
else
{
pDC->FillSolidRect(rcItem, m_crBack);
}
if (!m_themeButton->ThemeDataOpen())
m_themeButton->OpenThemeData(0, L"BUTTON");
if (m_themeButton->IsAppThemed() && XTPSystemVersion()->IsWinVistaOrGreater())
{
CRect rcButton(rcItem);
int iStateId = (pButton->IsPushed()) ? PBS_PRESSED :
pButton->IsHighlighted() ? PBS_HOT :
pButton->GetButtonStyle() == BS_DEFPUSHBUTTON ? PBS_DEFAULTED : PBS_NORMAL;
if (!pButton->IsWindowEnabled())
iStateId = PBS_DISABLED;
if (SUCCEEDED(m_themeButton->DrawThemeBackground(pDC->GetSafeHdc(),
6, iStateId, &rcButton, NULL)))
{
return TRUE;
}
}
XTPDrawHelpers()->ExcludeCorners(pDC, rcItem);
BOOL bSelected = pButton->IsPushed();
if (bSelected)
{
pDC->FillSolidRect(rcItem, m_crBackSelected);
pDC->Draw3dRect(rcItem, m_crBorderHilite, m_crBorderHilite);
rcItem.DeflateRect(1,1);
XTPDrawHelpers()->DrawLine(pDC, rcItem.left, rcItem.top, rcItem.Width(), 0, m_crBorder3DShadow);
rcItem.top += 1;
pDC->Draw3dRect(&rcItem, m_crBorder3DHilite, m_crBorder3DHilite);
rcItem.DeflateRect(1,1);
pDC->Draw3dRect(&rcItem, m_crBorderShadow, m_crBorderShadow);
}
else if (pButton->IsHighlighted())
{
XTPDrawHelpers()->GradientFill(pDC, &rcItem, m_crBack, m_crBorderShadow, FALSE);
pDC->Draw3dRect(rcItem, m_crBorderHilite, m_crBorderHilite);
rcItem.DeflateRect(1,1);
pDC->Draw3dRect(&rcItem, m_crBack, m_crBack);
}
if (pButton->GetButtonStyle() == BS_DEFPUSHBUTTON)
{
if (!bSelected && !pButton->IsHighlighted())
pDC->Draw3dRect(rcItem, m_crBorderActive, m_crBorderActive);
}
return TRUE;
}
return FALSE;
}
void CXTPTaskButtonTheme::DrawButtonIcon(CDC* pDC, CXTPButton* pButton)
{
CXTPImageManagerIcon* pIcon = pButton->GetIcon();
if (pIcon != NULL)
{
CXTPFontDC fontDC(pDC, m_pFontTitle ? m_pFontTitle : pButton->GetFont());
CSize size = pDC->GetTextExtent(_T(" "), 1);
CPoint point(7, m_ptMargin.y - pIcon->GetHeight() / 2 + size.cy / 2);
if (!pButton->IsWindowEnabled())
pIcon->Draw(pDC, point, pIcon->GetDisabledIcon(), pButton->GetImageSize());
else if (pButton->IsHighlighted())
pIcon->Draw(pDC, point, pIcon->GetHotIcon(), pButton->GetImageSize());
else
pIcon->Draw(pDC, point, pIcon->GetIcon(), pButton->GetImageSize());
}
}
CPoint CXTPTaskButtonTheme::GetTextPosition(CDC* /*pDC*/, CSize sizeText, CXTPButton* pButton)
{
CXTPClientRect rcItem(pButton);
CPoint point;
point.x = m_ptMargin.x;
point.y = rcItem.top + (rcItem.Height()-sizeText.cy)/2;
if (pButton->GetIcon())
point.x += pButton->GetImageSize().cx;
return point;
}
void CXTPTaskButtonTheme::DrawButtonText(CDC* pDC, CXTPButton* pButton)
{
if (m_strButton.IsEmpty())
GetButtonText(pButton);
CXTPClientRect rcItem(pButton);
CRect rcText = rcItem;
rcText.DeflateRect(m_ptMargin.x, m_ptMargin.y);
if (pButton->GetIcon())
rcText.left += pButton->GetImageSize().cx;
CFont* pFontNote = pButton->GetFont();
CSize sizeNoteText = rcText.Size();
XTPCalcTextSize(m_strNoteText, sizeNoteText, *pFontNote);
CSize sizeCaptText = rcText.Size();
XTPCalcTextSize(m_strCaptText, sizeCaptText, m_pFontTitle ? *m_pFontTitle : *pFontNote);
if (pButton->GetMarkupUIElement())
{
XTPMarkupSetDefaultFont(pButton->GetMarkupContext(), m_pFontTitle ? (HFONT)m_pFontTitle->GetSafeHandle(): (HFONT)pFontNote->GetSafeHandle(), COLORREF_NULL);
sizeCaptText = XTPMarkupMeasureElement(pButton->GetMarkupUIElement(), rcText.Width(), INT_MAX);
}
// get the text size.
CXTPEmptySize sizeText;
sizeText.cy = sizeCaptText.cy + sizeNoteText.cy;
sizeText.cx = __max(sizeCaptText.cx, sizeNoteText.cx);
CPoint point = GetTextPosition(pDC, sizeText, pButton);
BOOL bSelected = pButton->GetChecked() || pButton->IsPushed();
if (bSelected && m_bOffsetHiliteText)
point.Offset(1,1);
// Set the draw state flags.
pDC->SetTextColor(GetTextColor(pButton));
pDC->SetTextAlign(TA_LEFT);
pDC->SetBkMode(TRANSPARENT);
if (!m_strCaptText.IsEmpty())
{
CRect rcButton(point, sizeCaptText);
if (pButton->GetMarkupUIElement())
{
XTPMarkupSetDefaultFont(pButton->GetMarkupContext(), m_pFontTitle ? (HFONT)m_pFontTitle->GetSafeHandle(): (HFONT)pFontNote->GetSafeHandle(), pDC->GetTextColor());
XTPMarkupRenderElement(pButton->GetMarkupUIElement(), pDC->GetSafeHdc(), rcButton);
}
else
{
CString strCaptText = m_strCaptText;
if (pButton->SendMessage(WM_QUERYUISTATE) & UISF_HIDEACCEL)
{
XTPDrawHelpers()->StripMnemonics(strCaptText);
}
CXTPFontDC fontDC(pDC, m_pFontTitle ? m_pFontTitle : pFontNote);
pDC->DrawText(strCaptText, &rcButton, DT_LEFT | DT_TOP | DT_WORDBREAK);
}
point.y += sizeCaptText.cy + 1;
}
if (!m_strNoteText.IsEmpty())
{
CString strNoteText = m_strNoteText;
CXTPFontDC fontDC(pDC, pFontNote);
CRect rcButton(point, sizeNoteText);
pDC->DrawText(strNoteText, &rcButton, DT_LEFT | DT_TOP | DT_WORDBREAK | DT_NOPREFIX);
}
}
void CXTPTaskButtonTheme::GetButtonText(CXTPButton* pButton)
{
if (::IsWindow(pButton->GetSafeHwnd()))
{
pButton->GetWindowText(m_strButton);
m_strCaptText = XTPExtractSubString(m_strButton, 0);
m_strNoteText = XTPExtractSubString(m_strButton, 1);
}
}
void CXTPTaskButtonTheme::SetTitleFont(CFont* pFontTitle)
{
m_pFontTitle = pFontTitle;
}
CFont* CXTPTaskButtonTheme::GetTitleFont()
{
return m_pFontTitle;
}
void CXTPTaskButtonTheme::RefreshMetrics(CXTPButton* pButton)
{
CXTPButtonTheme::RefreshMetrics(pButton);
if (m_bThemeReady)
{
COLORREF crWindow = GetXtremeColor(COLOR_WINDOW);
COLORREF cr3dFace = GetXtremeColor(COLOR_3DFACE);
COLORREF cr3dShad = GetXtremeColor(COLOR_3DSHADOW);
m_crBack = crWindow;
m_crText = RGB(21,28,85);
m_crTextHilite = RGB(0x00, 0x4a, 0xe5);
m_crBorderActive = RGB(0xa3, 0xed, 0xff);
m_crBackSelected = XTPColorManager()->LightColor(crWindow, cr3dFace, 200);
m_crBorder3DShadow = XTPColorManager()->LightColor(cr3dFace, cr3dShad, 775);
m_crBorder3DHilite = XTPColorManager()->LightColor(cr3dFace, cr3dShad, 875);
m_crBorderShadow = XTPColorManager()->LightColor(crWindow, cr3dFace, 0);
m_crBorderHilite = XTPColorManager()->LightColor(cr3dFace, cr3dShad, 175);
}
else
{
m_crBorderActive = m_crBorder3DShadow;
}
}
COLORREF CXTPTaskButtonTheme::GetTextColor(CXTPButton* pButton)
{
if (!pButton->IsWindowEnabled())
return GetXtremeColor(COLOR_GRAYTEXT);
if (pButton->IsHighlighted())
return m_crTextHilite;
return m_crText;
}
/*
CPoint CXTPTaskButtonTheme::CalculateImagePosition(CDC* pDC, UINT nState, CRect& rcItem, bool bHasPushedImage, CXTPButton* pButton)
{
//CPoint point = CXTPButtonTheme::CalculateImagePosition(pDC, nState, rcItem, bHasPushedImage, pButton);
CPoint point = 0;
if (!m_strNoteText.IsEmpty())
point.y = m_ptMargin.y;
point.x += 2;
return point;
}*/
//===========================================================================
// CXTPTaskButtonThemeExpando
//===========================================================================
CXTPTaskButtonThemeExpando::CXTPTaskButtonThemeExpando()
{
m_bOffsetHiliteText = FALSE;
}
void CXTPTaskButtonThemeExpando::DrawButton(CDC* pDC, CXTPButton* pButton)
{
// define some temporary variables.
CXTPClientRect rcItem(pButton);
pDC->FillSolidRect(rcItem, GetXtremeColor(COLOR_3DFACE));
// Set the background mode to transparent.
pDC->SetBkColor(GetXtremeColor(COLOR_3DFACE));
// select font into device context.
CXTPFontDC fontDC(pDC, pButton->GetFont());
CString strText;
pButton->GetWindowText(strText);
// Remove ampersand
if (pButton->SendMessage(WM_QUERYUISTATE) & UISF_HIDEACCEL)
{
XTPDrawHelpers()->StripMnemonics(strText);
}
CRect rcText(rcItem);
rcText.left += 26;
CSize szExtent = pDC->GetTextExtent(strText);
if (szExtent.cx < rcItem.Width())
{
rcText.top = (rcItem.top + rcItem.bottom - szExtent.cy) / 2;
rcText.bottom = rcText.top + szExtent.cy;
}
pDC->SetTextColor(GetXtremeColor(COLOR_BTNTEXT));
pDC->DrawText(strText, rcText, DT_TOP | DT_WORDBREAK);
// Draw the focus rect if style is set and we have focus.
if (::GetFocus() == pButton->GetSafeHwnd() && ((pButton->SendMessage(WM_QUERYUISTATE) & UISF_HIDEFOCUS) == 0))
{
pDC->DrawText(strText, rcText, DT_TOP | DT_WORDBREAK | DT_CALCRECT);
rcText.InflateRect(1, 0);
pDC->DrawFocusRect(rcText);
}
rcItem.right = rcItem.left + 18;
rcItem.bottom = rcItem.top + min(20, rcItem.Height());
CPoint pt(rcItem.right / 2 - 1, rcItem.bottom / 2 - 3);
BOOL bDrawStandard = TRUE;
if (m_themeButton->IsAppThemed())
{
CXTPWinThemeWrapper themeTaskDialog;
themeTaskDialog.OpenTheme(0, L"TASKDIALOG");
if (themeTaskDialog.IsAppThemed())
{
CRect rcButton(0, 0, 19, 21);
int iStateId = pButton->IsPushed() ? 3 : pButton->IsHighlighted() ? 2 : 1;
if (pButton->GetChecked()) iStateId += 3;
if (SUCCEEDED(themeTaskDialog.DrawThemeBackground(pDC->GetSafeHdc(),
13, iStateId, &rcButton, NULL)))
{
return;
}
}
CRect rc(rcItem);
rc.right += 1;
int iStateId = pButton->IsPushed() ? PBS_PRESSED : pButton->IsHighlighted() ? PBS_HOT : PBS_NORMAL;
if (SUCCEEDED(m_themeButton->DrawThemeBackground(pDC->GetSafeHdc(),
BP_PUSHBUTTON, iStateId, &rc, NULL)))
{
bDrawStandard = FALSE;
pt.x += 1;
}
}
if (bDrawStandard)
{
pDC->DrawFrameControl(&rcItem, DFC_BUTTON, (pButton->IsPushed() ? DFCS_PUSHED : 0) | DFCS_BUTTONPUSH);
if (pButton->IsPushed()) pt.Offset(1, 1);
}
if (!pButton->GetChecked())
XTPDrawHelpers()->Triangle(pDC, pt - CPoint(4, 0),
pt + CPoint(4, 0), pt + CPoint(0, 4), GetXtremeColor(COLOR_BTNTEXT));
else
XTPDrawHelpers()->Triangle(pDC, pt - CPoint(4, -4),
pt + CPoint(4, 4), pt + CPoint(0, 0), GetXtremeColor(COLOR_BTNTEXT));
}
//////////////////////////////////////////////////////////////////////////
// CXTPTaskDialogProgressCtrl
#ifndef PBS_MARQUEE
#define PBS_MARQUEE 0x08
#endif
#ifndef PBM_SETMARQUEE
#define PBM_SETMARQUEE (WM_USER+10)
#endif
#ifndef PBM_SETSTATE
#define PBM_SETSTATE (WM_USER+16)
#endif
CXTPTaskDialogProgressCtrl::CXTPTaskDialogProgressCtrl()
{
m_nState = -1;
m_nMarqueePos = 0;
m_bMarquee = FALSE;
m_nMarqueeDelay = 0;
}
BEGIN_MESSAGE_MAP(CXTPTaskDialogProgressCtrl, CProgressCtrl)
//{{AFX_MSG_MAP(CXTPTaskDialogProgressCtrl)
ON_WM_PAINT()
ON_MESSAGE(PBM_SETMARQUEE, OnStartMarquee)
ON_MESSAGE(PBM_SETSTATE, OnSetState)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CXTPTaskDialogProgressCtrl::OnPaint()
{
if (HIWORD(XTPSystemVersion()->GetComCtlVersion()) > 5)
{
Default();
return;
}
if (((GetStyle() & PBS_MARQUEE) == 0) || !m_bMarquee)
{
Default();
return;
}
BOOL bVista = XTPSystemVersion()->IsWinVistaOrGreater();
CPaintDC dcPaint(this);
CXTPBufferDC dc(dcPaint);
CXTPClientRect rcClient(this);
dc.FillSolidRect(rcClient, GetXtremeColor(COLOR_3DFACE));
if (m_nState == PBST_ERROR || m_nState == PBST_PAUSED)
return;
rcClient.DeflateRect(1, 1);
CRect rc(rcClient);
int dxBlock = rc.Height() * 2 / 3;
int nSpace = bVista ? 0 : 2;
rc.left = m_nMarqueePos + 1;
for (int i = 0; i < 5; i++)
{
if (rc.left >= rcClient.right)
rc.left = 1;
rc.right = rc.left + dxBlock;
if (rc.right > rcClient.right)
rc.right = rcClient.right;
dc.FillSolidRect(rc, GetXtremeColor(COLOR_HIGHLIGHT));
rc.left = rc.right + nSpace;
}
}
LRESULT CXTPTaskDialogProgressCtrl::OnSetState(WPARAM wParam, LPARAM /*lParam*/)
{
m_nState = (int)wParam;
Default();
return 1;
}
LRESULT CXTPTaskDialogProgressCtrl::OnStartMarquee(WPARAM wParam, LPARAM lParam)
{
m_bMarquee = FALSE;
m_nMarqueePos = 0;
m_nMarqueeDelay = 0;
if (HIWORD(XTPSystemVersion()->GetComCtlVersion()) > 5)
return Default();
if (((GetStyle() & PBS_MARQUEE) == 0))
return Default();
m_bMarquee = wParam && (lParam > 0);
m_nMarqueePos = 0;
KillTimer(101);
if (m_bMarquee)
{
m_nMarqueeDelay = (UINT)lParam;
SetTimer(101, m_nMarqueeDelay, NULL);
}
return 1;
}
void CXTPTaskDialogProgressCtrl::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 101 && m_bMarquee)
{
CXTPClientRect rcClient(this);
BOOL bVista = XTPSystemVersion()->IsWinVistaOrGreater();
int dxBlock = (rcClient.Height() - 2) * 2 / 3;
int nSpace = bVista ? 0 : 2;
m_nMarqueePos += (dxBlock + nSpace) * (m_nMarqueeDelay > 50 ? 1 : 2);
if (m_nMarqueePos > rcClient.right)
m_nMarqueePos = 0;
Invalidate(FALSE);
return;
}
CWnd::OnTimer(nIDEvent);
}