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.

277 lines
7.4 KiB
C++

// XTPAnimationDC.cpp : implementation file
//
// 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/XTPColorManager.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPVC80Helpers.h"
#include "XTPAnimationDC.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
CXTPAnimationDC::LPFNANIMATION CXTPAnimationDC::m_pCustomAnimation = 0;
//===========================================================================
// CXTPAnimationDC class
//===========================================================================
CXTPAnimationDC::CXTPAnimationDC(HDC hDestDC, const CRect& rcPaint)
: m_hDestDC (hDestDC)
{
m_rect = rcPaint;
Attach (::CreateCompatibleDC (m_hDestDC));
if (!m_hDC)
return;
m_bitmap.Attach (::CreateCompatibleBitmap(
m_hDestDC, m_rect.Width(), m_rect.Height()));
m_hOldBitmap = ::SelectObject (m_hDC, m_bitmap);
}
CXTPAnimationDC::CXTPAnimationDC(HDC hDestDC, const CRect& rcPaint, const CXTPPaintManagerColorGradient& clrBack, const BOOL bHorz /*=FALSE*/)
: m_hDestDC (hDestDC)
{
m_rect = rcPaint;
Attach (::CreateCompatibleDC (m_hDestDC));
if (!m_hDC)
return;
m_bitmap.Attach (::CreateCompatibleBitmap(
m_hDestDC, m_rect.Width(), m_rect.Height()));
m_hOldBitmap = ::SelectObject (m_hDC, m_bitmap);
if (!clrBack.IsNull())
{
XTPDrawHelpers()->GradientFill(this, CRect(0, 0, m_rect.Width(), m_rect.Height()), clrBack, bHorz);
}
}
CXTPAnimationDC::~CXTPAnimationDC()
{
if (!m_hDC)
return;
if (m_hDestDC)
{
::BitBlt (m_hDestDC, m_rect.left, m_rect.top, m_rect.Width(),
m_rect.Height(), m_hDC, 0, 0, SRCCOPY);
}
::SelectObject (m_hDC, m_hOldBitmap);
}
#define BIT(a, b) (a & (1 << b))
void CXTPAnimationDC::Animate(int nType, int nSteps, int nAnimationTime)
{
//
// lets say the animation is done in m_nSteps and it should not take longer
// then m_nAnimationTime then we calculate as follows
//
switch (nType)
{
case xtpAniDefault:
{
//
// This registry entry is defined and explained under the
// following URLs
//
// http://www.microsoft.com/WINDOWS2000/techinfo/reskit/en/Regentry/55198.htm
// http://msdn.microsoft.com/library/en-us/regentry/55198.asp
// http://msdn.microsoft.com/library/default.asp ?url=/library/en-us/regentry/regazbd.asp
HKEY hKey = NULL;
DWORD dwType = 0, dwValue = 0, dwSize = sizeof(dwValue);
::RegOpenKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), &hKey);
::RegQueryValueEx(hKey, _T("UserPreferencesMask"), NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
::RegCloseKey(hKey);
if (BIT(dwValue, 1)) // is Menu animation enabled ?
{
if (BIT(dwValue, 9)) // if so, which animation ?
{
nType = xtpAniFade;
}
else
{
nType = xtpAniSlide;
}
// windows doesn't support more settings (currently)
}
}
break;
// choose any animation based on a random number
case xtpAniRandom:
{
switch (RAND_S() % 3)
{
case 0:
nType = xtpAniFade;
break;
case 1:
nType = xtpAniSlide;
break;
default:
nType = xtpAniUnfold;
break;
}
}
break;
}
LPFNANIMATION Animate = m_pCustomAnimation ? m_pCustomAnimation : DefaultAnimation;
Animate(m_rect, CDC::FromHandle(m_hDestDC), this, nType, nSteps, nAnimationTime);
}
void CXTPAnimationDC::DefaultAnimation(CRect rc, CDC* pDestDC, CDC* pSrcDC, int nType, int nSteps, int nAnimationTime)
{
CRect r;
switch (nType)
{
case xtpAniSlide:
{
const int bottom = rc.bottom - rc.top;
int i;
for (i = 0; i < rc.Height();
i += (1 + (rc.Height() / nSteps)))
{
pDestDC->BitBlt(rc.left, rc.top, rc.Width(), i, pSrcDC,
0, bottom - i, SRCCOPY);
Sleep(nAnimationTime / nSteps);
}
}
break;
case xtpAniUnfold:
{
r = rc;
int i;
for (i = 0; i < nSteps; ++i)
{
r.bottom = r.top + rc.Height() * (i + 1) / nSteps;
r.right = r.left + rc.Width() * (i + 1) / nSteps;
pDestDC->BitBlt(r.left, r.top, r.Width(), r.Height(), pSrcDC,
0, 0, SRCCOPY);
Sleep(nAnimationTime / nSteps);
}
}
break;
case xtpAniFade:
{
const int cx = rc.Width();
const int cy = rc.Height();
BITMAPINFOHEADER BMI;
// Fill in the header info.
ZeroMemory (&BMI, sizeof(BMI));
BMI.biSize = sizeof(BITMAPINFOHEADER);
BMI.biWidth = cx;
BMI.biHeight = cy;
BMI.biPlanes = 1;
BMI.biBitCount = 32;
BMI.biCompression = BI_RGB; // No compression
BYTE * pSrcBits = NULL;
HBITMAP hbmSrc = CreateDIBSection (NULL, (BITMAPINFO *)&BMI, DIB_RGB_COLORS, (void **)&pSrcBits, 0, 0l);
BYTE * pSrcBackBits = NULL;
HBITMAP hbmSrcBack = CreateDIBSection (NULL, (BITMAPINFO *)&BMI, DIB_RGB_COLORS, (void **)&pSrcBackBits, 0, 0l);
BYTE * pDestBits = NULL;
HBITMAP hbmDest = CreateDIBSection (NULL, (BITMAPINFO *)&BMI, DIB_RGB_COLORS, (void **)&pDestBits, 0, 0l);
// Copy our source and destination bitmaps onto our DIBSections,
// so we can get access to their bits using the BYTE *'s we passed into CreateDIBSection
CDC dc;
dc.CreateCompatibleDC(NULL);
HBITMAP hbmpOld = (HBITMAP) ::SelectObject(dc, hbmSrc);
::BitBlt(dc, 0, 0, cx, cy, pSrcDC->GetSafeHdc(), 0, 0, SRCCOPY);
::SelectObject(dc, hbmSrcBack);
::BitBlt(dc, 0, 0, cx, cy, pDestDC->GetSafeHdc (), rc.left, rc.top, SRCCOPY);
::SelectObject(dc, hbmDest);
DWORD dwTimePer = nAnimationTime / nSteps;
::SelectObject(dc, hbmDest);
for (int i = 1; i < nSteps; ++i)
{
DWORD dwTime = GetTickCount ();
AlphaBlendU(pDestBits, pSrcBackBits, cx, cy, pSrcBits, (BYTE)((255*i) / nSteps));
pDestDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY);
dwTime = GetTickCount () - dwTime;
if (dwTime < dwTimePer)
{
Sleep(dwTimePer - dwTime);
}
}
::SelectObject(dc, hbmpOld);
DeleteObject(hbmSrc);
DeleteObject(hbmSrcBack);
DeleteObject(hbmDest);
}
break;
}
}
void CXTPAnimationDC::AlphaBlendU(PBYTE pDest, PBYTE pSrcBack, int cx, int cy, PBYTE pSrc, BYTE byAlpha)
{
BYTE byDiff = (BYTE)(255 - byAlpha);
int iRowOffset = 0, j = cy;
while (j > 0)
{
--j;
LPBYTE pbSrcRGB = (LPBYTE)&((DWORD*)pSrc)[iRowOffset];
LPBYTE pbSrcBackRGB = (LPBYTE)&((DWORD*)pSrcBack)[iRowOffset];
LPBYTE pbDestRGB = (LPBYTE)&((DWORD*)pDest)[iRowOffset];
iRowOffset += cx;
int i = cx;
while (i > 0)
{
--i;
pbDestRGB[0] = (BYTE)((pbSrcBackRGB[0] * byDiff + pbSrcRGB[0] * byAlpha) >> 8);
pbDestRGB[1] = (BYTE)((pbSrcBackRGB[1] * byDiff + pbSrcRGB[1] * byAlpha) >> 8);
pbDestRGB[2] = (BYTE)((pbSrcBackRGB[2] * byDiff + pbSrcRGB[2] * byAlpha) >> 8);
pbSrcRGB += 4;
pbSrcBackRGB += 4;
pbDestRGB += 4;
}
}
}
void CXTPAnimationDC::SetCustomAnimation(LPFNANIMATION pCustom)
{
m_pCustomAnimation = pCustom;
}