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.

605 lines
12 KiB
C++

2 years ago
// XTPProgressCtrl.cpp : implementation of the CXTPProgressCtrl 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 "Common/XTPDrawHelpers.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPResourceImage.h"
#include "Common/XTPWinThemeWrapper.h"
#include "Common/XTPSystemHelpers.h"
#include "../Util/XTPControlTheme.h"
#include "XTPProgressCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TID_TIMER 101
IMPLEMENT_DYNAMIC(CXTPProgressCtrl, CProgressCtrl)
/////////////////////////////////////////////////////////////////////////////
// CXTPScrollBar
/////////////////////////////////////////////////////////////////////////////
CXTPProgressCtrl::CXTPProgressCtrl()
{
m_bPreSubclassInit = TRUE;
m_nMarqueePos = 0;
m_nMarqueeDelay = 0;
m_nTheme = xtpControlThemeDefault;
m_bFlatStyle = FALSE;
m_bUseVisualStyle = TRUE;
m_themeProgress = new CXTPWinThemeWrapper();
}
CXTPProgressCtrl::~CXTPProgressCtrl()
{
SAFE_DELETE(m_themeProgress);
}
BEGIN_MESSAGE_MAP(CXTPProgressCtrl, CProgressCtrl)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SYSCOLORCHANGE()
ON_MESSAGE(PBM_SETMARQUEE, OnStartMarquee)
ON_MESSAGE(PBM_STEPIT, OnStepIt)
ON_MESSAGE(PBM_SETPOS, OnSetPos)
ON_WM_TIMER()
END_MESSAGE_MAP()
void CXTPProgressCtrl::Init()
{
RefreshMetrics();
ModifyStyleEx(WS_EX_STATICEDGE | WS_EX_CLIENTEDGE, 0);
SetWindowPos(NULL, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
SetWindowText(_T(""));
m_nMarqueePos = 0;
SendMessage(WM_NCPAINT);
Invalidate(FALSE);
}
void CXTPProgressCtrl::PreSubclassWindow()
{
CProgressCtrl::PreSubclassWindow();
if (m_bPreSubclassInit)
{
// Initialize the control.
Init();
}
}
int CXTPProgressCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CProgressCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
// Initialize the control.
Init();
return 0;
}
BOOL CXTPProgressCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CProgressCtrl::PreCreateWindow(cs))
return FALSE;
// When creating controls dynamically Init() must
// be called from OnCreate() and not from
// PreSubclassWindow().
m_bPreSubclassInit = FALSE;
return TRUE;
}
void CXTPProgressCtrl::RefreshMetrics()
{
RefreshXtremeColors();
m_clrBorderNormal.SetStandardValue(GetSysColor(COLOR_3DSHADOW));
if (m_nTheme == xtpControlThemeFlat)
{
m_clrBorderNormal.SetStandardValue(GetSysColor(COLOR_WINDOWFRAME));
}
if (m_nTheme == xtpControlThemeOffice2003)
{
XTPCurrentSystemTheme systemTheme = XTPColorManager()->GetCurrentSystemTheme();
switch (systemTheme)
{
case xtpSystemThemeBlue:
case xtpSystemThemeRoyale:
case xtpSystemThemeAero:
m_clrBorderNormal.SetStandardValue(RGB(127, 157, 185));
break;
case xtpSystemThemeOlive:
m_clrBorderNormal.SetStandardValue(RGB(164, 185, 127));
break;
case xtpSystemThemeSilver:
m_clrBorderNormal.SetStandardValue(RGB(165, 172, 178));
break;
}
}
m_themeProgress->OpenTheme(0, L"PROGRESS");
m_clrBarColor.SetStandardValue(GetXtremeColor(COLOR_HIGHLIGHT));
m_clrTextColor.SetStandardValue(GetXtremeColor(COLOR_HIGHLIGHTTEXT));
m_clrBackColor.SetStandardValue(GetXtremeColor(COLOR_3DFACE));
}
COLORREF CXTPProgressCtrl::GetBackColor()
{
return m_clrBackColor;
}
void CXTPProgressCtrl::DrawNcBorders(CDC* pDC, CRect rc)
{
COLORREF clrBack = GetBackColor();
if (m_bUseVisualStyle && m_themeProgress->IsAppThemed())
return;
if (m_bFlatStyle)
return;
if (m_nTheme == xtpControlThemeDefault)
{
pDC->DrawEdge(rc, EDGE_SUNKEN, BF_RECT);
return;
}
if (m_nTheme == xtpControlThemeOffice2000)
{
pDC->Draw3dRect(rc, m_clrBorderNormal, GetXtremeColor(COLOR_BTNHIGHLIGHT));
}
else
{
COLORREF clrBorder = m_clrBorderNormal;
pDC->Draw3dRect(rc, clrBorder, clrBorder);
}
rc.DeflateRect(1, 1);
pDC->Draw3dRect(rc, clrBack, clrBack);
}
void CXTPProgressCtrl::OnSysColorChange()
{
CProgressCtrl::OnSysColorChange();
RefreshMetrics();
Invalidate(FALSE);
}
void CXTPProgressCtrl::SetBarColor(COLORREF clrBarColor)
{
m_clrBarColor.SetCustomValue(clrBarColor);
Invalidate(FALSE);
}
COLORREF CXTPProgressCtrl::SetBkColor(COLORREF clrNew)
{
m_clrBackColor.SetCustomValue(clrNew);
Invalidate(FALSE);
return m_clrBackColor;
}
COLORREF CXTPProgressCtrl::SetTextColor(COLORREF clrNew)
{
m_clrTextColor.SetCustomValue(clrNew);
Invalidate(FALSE);
return m_clrTextColor;
}
void CXTPProgressCtrl::DoPaint(CDC* pDC)
{
CRect rcClient;
GetClientRect(rcClient);
BOOL bThemed = m_bUseVisualStyle && m_themeProgress->IsAppThemed();
BOOL bVertical = GetStyle() & PBS_VERTICAL;
if (!bThemed && m_nTheme == xtpControlThemeResource && !bVertical)
{
PaintOffice2007(pDC);
return;
}
if (!bThemed && !m_bFlatStyle)
{
DrawNcBorders(pDC, rcClient);
rcClient.DeflateRect(2, 2);
}
pDC->FillSolidRect(rcClient, GetBackColor());
if (bThemed)
{
m_themeProgress->DrawThemeBackground(*pDC, bVertical ? PP_BARVERT : PP_BAR, 0, rcClient, NULL);
}
BOOL bVista = XTPSystemVersion()->IsWinVistaOrGreater();
int x, dxSpace, dxBlock, nBlocks;
int iStart, iEnd;
BOOL bSmooth = GetStyle() & PBS_SMOOTH;
BOOL bMarquee = GetStyle() & PBS_MARQUEE;
if (bThemed)
{
if (bVertical)
rcClient.DeflateRect(3, 4);
else
rcClient.DeflateRect(4, 3);
}
else if (!m_bFlatStyle && m_nTheme == xtpControlThemeDefault)
{
// give 1 pixel around the bar
rcClient.DeflateRect(1, 1);
}
else if (!m_bFlatStyle && (m_nTheme == xtpControlThemeFlat) && bSmooth)
{
// give 1 pixel around the bar
rcClient.InflateRect(1, 1);
}
CRect rc = rcClient;
if (bMarquee)
{
dxBlock = rc.Height() * 2 / 3;
dxSpace = bVista ? 0 : 2;
if (bThemed)
{
m_themeProgress->GetThemeInt(0, 0, TMT_PROGRESSCHUNKSIZE, &dxBlock);
m_themeProgress->GetThemeInt(0, 0, TMT_PROGRESSSPACESIZE, &dxSpace);
}
rc.left = m_nMarqueePos + rcClient.left;
for (int i = 0; i < 5; i++)
{
if (rc.left >= rcClient.right)
rc.left = rcClient.left;
rc.right = rc.left + dxBlock;
if (rc.right > rcClient.right)
rc.right = rcClient.right;
if (bThemed)
{
m_themeProgress->DrawThemeBackground(*pDC, PP_CHUNK, 0, rc, NULL);
}
else
{
pDC->FillSolidRect(rc, m_clrBarColor);
}
rc.left = rc.right + dxSpace;
}
}
else
{
PBRANGE range;
SendMessage(PBM_GETRANGE, (WPARAM) FALSE, (LPARAM) &range);
int iLow = range.iLow;
int iHigh = range.iHigh;
int iPos = (int)SendMessage(PBM_GETPOS);
if (bVertical)
{
iStart = rc.top;
iEnd = rc.bottom;
dxBlock = (rc.right - rc.left) * 2 / 3;
}
else
{
iStart = rc.left;
iEnd = rc.right;
dxBlock = (rc.bottom - rc.top) * 2 / 3;
}
x = MulDiv(iEnd - iStart, iPos - iLow, iHigh - iLow);
dxSpace = 2;
if (bThemed)
{
m_themeProgress->GetThemeInt(0, 0, TMT_PROGRESSCHUNKSIZE, &dxBlock);
m_themeProgress->GetThemeInt(0, 0, TMT_PROGRESSSPACESIZE, &dxSpace);
}
if (dxBlock == 0)
dxBlock = 1; // avoid div by zero
if (!bThemed && bSmooth)
{
dxBlock = 1;
dxSpace = 0;
}
nBlocks = (x + (dxBlock + dxSpace) - 1) / (dxBlock + dxSpace); // round up
for (int i = 0; i < nBlocks; i++)
{
if (bVertical)
{
rc.top = rc.bottom - dxBlock;
// are we past the end?
if (rc.bottom <= rcClient.top)
break;
if (rc.top <= rcClient.top)
rc.top = rcClient.top + 1;
}
else
{
rc.right = rc.left + dxBlock;
// are we past the end?
if (rc.left >= rcClient.right)
break;
if (rc.right >= rcClient.right)
rc.right = rcClient.right - 1;
}
if (bThemed)
{
m_themeProgress->DrawThemeBackground(*pDC, bVertical ? PP_CHUNKVERT : PP_CHUNK, 0, rc, NULL);
}
else
{
pDC->FillSolidRect(&rc, m_clrBarColor);
}
if (bVertical)
{
rc.bottom = rc.top - dxSpace;
}
else
{
rc.left = rc.right + dxSpace;
}
}
}
if (bThemed)
return;
CString strText;
GetWindowText(strText);
if (!strText.IsEmpty())
{
CRect rcText(rcClient);
rcText.DeflateRect(2, 0);
pDC->SetTextColor(m_clrTextColor);
pDC->SetBkMode(TRANSPARENT);
CXTPFontDC font(pDC, CWnd::GetFont());
pDC->DrawText(strText, rcText, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | DT_VCENTER);
}
}
BOOL CXTPProgressCtrl::OnEraseBkgnd(CDC* /*pDC*/)
{
if (m_bUseVisualStyle && m_themeProgress->IsAppThemed() && m_themeProgress->IsAppThemeReady())
{
return (BOOL)Default();
}
return TRUE;
}
void CXTPProgressCtrl::OnPaint()
{
if (m_bUseVisualStyle && m_themeProgress->IsAppThemed() && m_themeProgress->IsAppThemeReady())
{
Default();
}
else
{
CPaintDC dcPaint(this);
CXTPBufferDC dc(dcPaint);
DoPaint(&dc);
}
}
void CXTPProgressCtrl::PaintOffice2007(CDC* pDC)
{
CXTPResourceImages* pImages = XTPResourceImages();
CXTPResourceImage* pImage = pImages->LoadFile(_T("PROGRESSTRACK"));
ASSERT(pImage);
if (!pImage)
return;
CRect rc;
GetClientRect(rc);
pDC->FillSolidRect(rc, GetBackColor());
pImage->DrawImage(pDC, rc, pImage->GetSource(), CRect(2, 2, 2, 2), 0xFF00FF);
PBRANGE range;
SendMessage(PBM_GETRANGE, (WPARAM) FALSE, (LPARAM) &range);
int nLower = range.iLow;
int nUpper = range.iHigh;
int nPos = (int)SendMessage(PBM_GETPOS);
rc.DeflateRect(2, 2);
int nWidth = rc.Width();
int x = MulDiv(nWidth, nPos - nLower, nUpper - nLower);
pImage = pImages->LoadFile(_T("PROGRESSCHUNK"));
ASSERT(pImage);
if (!pImage)
return;
CRect rcSrc(pImage->GetSource());
rcSrc.right -= 4;
CRect rcDest(rc.left, rc.top, rc.left + x, rc.bottom);
if (rcDest.Width() < rcSrc.Width())
rcSrc.left = rcSrc.right - rcDest.Width();
pImage->DrawImage(pDC, rcDest, rcSrc, CRect(2, 2, 2, 2), 0xFF00FF);
if (rc.left + x < rc.right - 1)
{
int nShadow = min(4, rc.right - rc.left - x);
rcSrc = CRect(rcSrc.right, rcSrc.top, rcSrc.right + nShadow, rcSrc.bottom);
rcDest = CRect(rcDest.right, rcDest.top, rcDest.right + nShadow, rcDest.bottom);
pImage->DrawImage(pDC, rcDest, rcSrc, CRect(0, 2, 0, 2), 0xFF00FF);
return;
}
}
LRESULT CXTPProgressCtrl::OnStartMarquee(WPARAM wParam, LPARAM lParam)
{
m_nMarqueePos = 0;
m_nMarqueeDelay = 0;
if (((GetStyle() & PBS_MARQUEE) == 0))
return Default();
if (m_bUseVisualStyle && m_themeProgress->IsAppThemed() && m_themeProgress->IsAppThemeReady())
return Default();
BOOL bMarquee = wParam && (lParam > 0);
m_nMarqueePos = 0;
KillTimer(TID_TIMER);
if (bMarquee)
{
m_nMarqueeDelay = (UINT)lParam;
SetTimer(TID_TIMER, m_nMarqueeDelay, NULL);
}
return 1;
}
void CXTPProgressCtrl::DoStep(int nStep)
{
CXTPClientRect rcClient(this);
BOOL bVista = XTPSystemVersion()->IsWinVistaOrGreater();
int dxBlock = (rcClient.Height() - 2) * 2 / 3;
int nSpace = bVista ? 0 : 2;
m_nMarqueePos += (dxBlock + nSpace) * nStep;
if (m_nMarqueePos > rcClient.right)
m_nMarqueePos = 0;
Invalidate(FALSE);
}
void CXTPProgressCtrl::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == TID_TIMER && (GetStyle() & PBS_MARQUEE))
{
DoStep(m_nMarqueeDelay > 50 ? 1 : 2);
return;
}
CWnd::OnTimer(nIDEvent);
}
LRESULT CXTPProgressCtrl::OnStepIt(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
if (((GetStyle() & PBS_MARQUEE) == 0))
return Default();
if (m_bUseVisualStyle && m_themeProgress->IsAppThemed() && m_themeProgress->IsAppThemeReady())
return Default();
DoStep(1);
return 1;
}
LRESULT CXTPProgressCtrl::OnSetPos(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
LRESULT lResult = Default();
Invalidate(FALSE);
return lResult;
}
void CXTPProgressCtrl::SetUseVisualStyle(BOOL bUseVisualStyle/* = TRUE*/)
{
m_bUseVisualStyle = bUseVisualStyle;
RefreshMetrics();
if (m_hWnd) Invalidate(FALSE);
}
void CXTPProgressCtrl::SetTheme(XTPControlTheme nTheme)
{
m_nTheme = nTheme;
m_bUseVisualStyle = (m_nTheme == xtpControlThemeDefault);
RefreshMetrics();
if (m_hWnd) Invalidate(FALSE);
}