548 lines
13 KiB
C++
548 lines
13 KiB
C++
// =============================================================================
|
|
// Class Implementation : COXSplashWnd
|
|
// =============================================================================
|
|
//
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "OXSplashWnd.h"
|
|
|
|
#ifdef OX_SPLASHWND_JPEG
|
|
#include "OXDIB.h"
|
|
#endif
|
|
#include <afxtempl.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// helper class COXSplashWndDIB
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// DDB members:
|
|
|
|
// CBitmap* m_pBitmap;
|
|
// --- The loaded DDB bitmap
|
|
|
|
// CPalette* m_pPalette;
|
|
// --- The palette to use with the bitmap
|
|
|
|
// DIB members:
|
|
|
|
// BITMAPINFOHEADER m_bmih;
|
|
// --- The original bitmap header
|
|
// CByteArray m_bits;
|
|
// --- The original bitmap bits
|
|
// DWORD m_nWidthBits;
|
|
// --- Bits per scan line
|
|
|
|
// The following members are used for quick access
|
|
|
|
// int m_xMax;
|
|
// --- Maximum x value in bitmap (zero-based)
|
|
|
|
// int m_yMax;
|
|
// --- Maximum y value in bitmap (zero-based)
|
|
|
|
// int m_nBitCount;
|
|
// --- Bitmap bitcount
|
|
|
|
// int m_nRightShift;
|
|
// --- 8 - m_nBitCount
|
|
|
|
// BOOL m_bTopdown;
|
|
// --- Whether the bits are organized top-down or not
|
|
|
|
// BYTE* m_pBits0;
|
|
// ---- Pointer to the actual bits
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
COXSplashWndDIB::COXSplashWndDIB()
|
|
:
|
|
m_pBitmap(NULL),
|
|
m_pPalette(NULL),
|
|
m_nWidthBits(0),
|
|
m_xMax(0),
|
|
m_yMax(0),
|
|
m_nBitCount(0),
|
|
m_nRightShift(0),
|
|
m_bTopdown(FALSE),
|
|
m_pBits0(NULL)
|
|
{
|
|
::ZeroMemory(&m_bmih, sizeof(m_bmih));
|
|
}
|
|
|
|
COXSplashWndDIB::~COXSplashWndDIB()
|
|
{
|
|
delete m_pBitmap;
|
|
delete m_pPalette;
|
|
}
|
|
|
|
CBitmap* COXSplashWndDIB::GetBitmap()
|
|
{
|
|
return m_pBitmap;
|
|
}
|
|
|
|
BOOL COXSplashWndDIB::GetBitmapInfo(BITMAP& bm)
|
|
{
|
|
if (m_pBitmap == NULL)
|
|
return FALSE;
|
|
|
|
m_pBitmap->GetBitmap(&bm);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXSplashWndDIB::LoadResource(LPCTSTR lpszResourceName, BOOL bPrepareGetPixel)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
HINSTANCE hInstance = NULL;
|
|
HRSRC hRsrc = NULL;
|
|
HGLOBAL hGlobal = NULL;
|
|
HBITMAP hBitmapFinal = NULL;
|
|
HPALETTE hPal = NULL;
|
|
LPBITMAPINFOHEADER lpbi = NULL;
|
|
HDC hdc = NULL;
|
|
int iNumColors = 0;
|
|
|
|
if (m_pBitmap != NULL)
|
|
{
|
|
delete m_pBitmap;
|
|
m_pBitmap = NULL;
|
|
}
|
|
if (m_pPalette != NULL)
|
|
{
|
|
delete m_pPalette;
|
|
m_pPalette = NULL;
|
|
}
|
|
|
|
hInstance = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
|
|
if (hInstance != NULL)
|
|
hRsrc = ::FindResource(hInstance, lpszResourceName, RT_BITMAP);
|
|
if (hRsrc != NULL)
|
|
hGlobal = ::LoadResource(hInstance, hRsrc);
|
|
|
|
if (hGlobal != NULL)
|
|
{
|
|
lpbi = (LPBITMAPINFOHEADER)::LockResource(hGlobal);
|
|
if (lpbi != NULL)
|
|
{
|
|
hdc = ::GetDC(NULL);
|
|
if (hdc != NULL)
|
|
{
|
|
hPal = CreateDIBPalette ((LPBITMAPINFO)lpbi, iNumColors);
|
|
if ((hPal == NULL) && (::GetDeviceCaps(hdc, SIZEPALETTE) == 256))
|
|
{
|
|
// .... Trying to show bitmap without palette on 256-color display
|
|
// so let's use halftone palette (better than nothing)
|
|
hPal = ::CreateHalftonePalette(hdc);
|
|
}
|
|
if (hPal != NULL)
|
|
{
|
|
::SelectPalette(hdc, hPal, FALSE);
|
|
::RealizePalette(hdc);
|
|
}
|
|
|
|
hBitmapFinal = ::CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi,
|
|
(LONG)CBM_INIT, (LPSTR)lpbi + lpbi->biSize +
|
|
iNumColors * sizeof(RGBQUAD), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
|
|
if (hBitmapFinal != NULL)
|
|
{
|
|
m_pBitmap = new CBitmap;
|
|
m_pBitmap->Attach(hBitmapFinal);
|
|
if (hPal != NULL)
|
|
{
|
|
m_pPalette = new CPalette;
|
|
m_pPalette->Attach(hPal);
|
|
}
|
|
if (bPrepareGetPixel)
|
|
PrepareGetPixel(*lpbi, iNumColors);
|
|
bResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(hPal!=NULL)
|
|
::DeleteObject((HGDIOBJ)hPal);
|
|
}
|
|
|
|
::ReleaseDC(NULL,hdc);
|
|
}
|
|
::UnlockResource(hGlobal);
|
|
}
|
|
::FreeResource(hGlobal);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
#ifdef OX_SPLASHWND_JPEG
|
|
BOOL COXSplashWndDIB::LoadJPEGFile(LPCTSTR lpszFileName, BOOL bPrepareGetPixel)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
HBITMAP hBitmapFinal = NULL;
|
|
HPALETTE hPal = NULL;
|
|
LPBITMAPINFOHEADER lpbi = NULL;
|
|
HDC hdc = NULL;
|
|
int iNumColors = 0;
|
|
|
|
COXDIB dib;
|
|
if(!dib.ReadJPEG(lpszFileName))
|
|
return FALSE;
|
|
CMemFile memFile;
|
|
if (!dib.Write(&memFile,FALSE))
|
|
{
|
|
memFile.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
if (m_pBitmap != NULL)
|
|
{
|
|
delete m_pBitmap;
|
|
m_pBitmap = NULL;
|
|
}
|
|
if (m_pPalette != NULL)
|
|
{
|
|
delete m_pPalette;
|
|
m_pPalette = NULL;
|
|
}
|
|
|
|
if(memFile.GetLength()>0)
|
|
{
|
|
BYTE* pBuffer=(BYTE*)memFile.Detach();
|
|
if(pBuffer!=NULL)
|
|
{
|
|
pBuffer=pBuffer+14;
|
|
lpbi=(LPBITMAPINFOHEADER)pBuffer;
|
|
|
|
hdc=::GetDC(NULL);
|
|
if(hdc!=NULL)
|
|
{
|
|
hPal=CreateDIBPalette((LPBITMAPINFO)lpbi,iNumColors);
|
|
if((hPal==NULL) && (::GetDeviceCaps(hdc,SIZEPALETTE)==256))
|
|
{
|
|
// .... Trying to show bitmap without palette on 256-color display
|
|
// so let's use halftone palette (better than nothing)
|
|
hPal=::CreateHalftonePalette(hdc);
|
|
}
|
|
if(hPal!=NULL)
|
|
{
|
|
SelectPalette(hdc,hPal,FALSE);
|
|
RealizePalette(hdc);
|
|
}
|
|
|
|
hBitmapFinal=::CreateDIBitmap(hdc,(LPBITMAPINFOHEADER)lpbi,
|
|
(LONG)CBM_INIT,(LPSTR)lpbi+lpbi->biSize+
|
|
iNumColors * sizeof(RGBQUAD),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);
|
|
if(hBitmapFinal!=NULL)
|
|
{
|
|
m_pBitmap=new CBitmap;
|
|
m_pBitmap->Attach(hBitmapFinal);
|
|
if(hPal!=NULL)
|
|
{
|
|
m_pPalette=new CPalette;
|
|
m_pPalette->Attach(hPal);
|
|
}
|
|
if (bPrepareGetPixel)
|
|
PrepareGetPixel(*lpbi, iNumColors);
|
|
bResult=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(hPal!=NULL)
|
|
::DeleteObject((HGDIOBJ)hPal);
|
|
}
|
|
|
|
::ReleaseDC(NULL,hdc);
|
|
}
|
|
::free(pBuffer-14);
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
|
|
|
|
}
|
|
#endif
|
|
BOOL COXSplashWndDIB::LoadFile(LPCTSTR lpszFileName, BOOL bPrepareGetPixel)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
HBITMAP hBitmapFinal = NULL;
|
|
HPALETTE hPal = NULL;
|
|
LPBITMAPINFOHEADER lpbi = NULL;
|
|
HDC hdc = NULL;
|
|
int iNumColors = 0;
|
|
|
|
CFile file;
|
|
CMemFile memFile;
|
|
CFileException fileException;
|
|
if(!file.Open(lpszFileName,CFile::modeRead|CFile::shareDenyWrite,&fileException))
|
|
{
|
|
TRACE(_T("COXSplashWndDIB::LoadFile : Could not open DIB file : %s\n"),
|
|
lpszFileName);
|
|
return FALSE;
|
|
}
|
|
if(!CopyFile(&memFile,&file))
|
|
{
|
|
TRACE(_T("COXSplashWndDIB::LoadFile : Could not copy DIB file : %s\n"),
|
|
lpszFileName);
|
|
return FALSE;
|
|
}
|
|
file.Close();
|
|
|
|
if (m_pBitmap != NULL)
|
|
{
|
|
delete m_pBitmap;
|
|
m_pBitmap = NULL;
|
|
}
|
|
if (m_pPalette != NULL)
|
|
{
|
|
delete m_pPalette;
|
|
m_pPalette = NULL;
|
|
}
|
|
|
|
if(memFile.GetLength()>0)
|
|
{
|
|
BYTE* pBuffer=(BYTE*)memFile.Detach();
|
|
if(pBuffer!=NULL)
|
|
{
|
|
pBuffer=pBuffer+14;
|
|
lpbi=(LPBITMAPINFOHEADER)pBuffer;
|
|
|
|
hdc=::GetDC(NULL);
|
|
if(hdc!=NULL)
|
|
{
|
|
hPal=CreateDIBPalette((LPBITMAPINFO)lpbi,iNumColors);
|
|
if((hPal==NULL) && (::GetDeviceCaps(hdc,SIZEPALETTE)==256))
|
|
{
|
|
// .... Trying to show bitmap without palette on 256-color display
|
|
// so let's use halftone palette (better than nothing)
|
|
hPal=::CreateHalftonePalette(hdc);
|
|
}
|
|
if(hPal!=NULL)
|
|
{
|
|
SelectPalette(hdc,hPal,FALSE);
|
|
RealizePalette(hdc);
|
|
}
|
|
|
|
hBitmapFinal=::CreateDIBitmap(hdc,(LPBITMAPINFOHEADER)lpbi,
|
|
(LONG)CBM_INIT,(LPSTR)lpbi+lpbi->biSize+
|
|
iNumColors * sizeof(RGBQUAD),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);
|
|
if(hBitmapFinal!=NULL)
|
|
{
|
|
m_pBitmap=new CBitmap;
|
|
m_pBitmap->Attach(hBitmapFinal);
|
|
if(hPal!=NULL)
|
|
{
|
|
m_pPalette=new CPalette;
|
|
m_pPalette->Attach(hPal);
|
|
}
|
|
if (bPrepareGetPixel)
|
|
PrepareGetPixel(*lpbi, iNumColors);
|
|
bResult=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(hPal!=NULL)
|
|
::DeleteObject((HGDIOBJ)hPal);
|
|
}
|
|
|
|
::ReleaseDC(NULL,hdc);
|
|
}
|
|
::free(pBuffer-14);
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
HPALETTE COXSplashWndDIB::CreateDIBPalette (LPBITMAPINFO lpbmi, int& nNumColors)
|
|
{
|
|
LPBITMAPINFOHEADER lpbi = NULL;
|
|
LPLOGPALETTE lpPal = NULL;
|
|
HANDLE hLogPal = NULL;
|
|
HPALETTE hPal = NULL;
|
|
int i = 0;
|
|
|
|
// ... Initialize return variable
|
|
nNumColors = 0;
|
|
|
|
lpbi = (LPBITMAPINFOHEADER)lpbmi;
|
|
if (lpbi->biBitCount <= 8)
|
|
nNumColors = (1 << lpbi->biBitCount);
|
|
else
|
|
nNumColors = 0; // No palette needed for 24 BPP DIB
|
|
|
|
if (lpbi->biClrUsed > 0)
|
|
nNumColors = lpbi->biClrUsed; // Use biClrUsed
|
|
|
|
if (nNumColors != 0)
|
|
{
|
|
hLogPal = ::GlobalAlloc (GHND, sizeof (LOGPALETTE) +
|
|
sizeof (PALETTEENTRY) * nNumColors);
|
|
lpPal = (LPLOGPALETTE) ::GlobalLock (hLogPal);
|
|
lpPal->palVersion = (WORD)0x300;
|
|
lpPal->palNumEntries = (WORD)nNumColors;
|
|
|
|
for (i = 0; i < nNumColors; i++)
|
|
{
|
|
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
|
|
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
|
|
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
|
|
lpPal->palPalEntry[i].peFlags = 0;
|
|
}
|
|
hPal = ::CreatePalette (lpPal);
|
|
::GlobalUnlock (hLogPal);
|
|
::GlobalFree (hLogPal);
|
|
}
|
|
return hPal;
|
|
}
|
|
|
|
BOOL COXSplashWndDIB::Draw(CDC* pDC)
|
|
{
|
|
if (m_pBitmap == NULL)
|
|
return FALSE;
|
|
|
|
CDC dcImage;
|
|
if (!dcImage.CreateCompatibleDC(pDC))
|
|
return FALSE;
|
|
|
|
if (m_pPalette != NULL)
|
|
{
|
|
dcImage.SelectPalette(m_pPalette, FALSE);
|
|
dcImage.RealizePalette();
|
|
pDC->SelectPalette(m_pPalette, FALSE);
|
|
pDC->RealizePalette();
|
|
}
|
|
|
|
BITMAP bm;
|
|
m_pBitmap->GetBitmap(&bm);
|
|
CBitmap* pOldBitmap = dcImage.SelectObject(m_pBitmap);
|
|
pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY);
|
|
dcImage.SelectObject(pOldBitmap);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
COLORREF COXSplashWndDIB::GetPixel(POINT pt)
|
|
{
|
|
return GetPixel(pt.x, pt.y);
|
|
}
|
|
|
|
COLORREF COXSplashWndDIB::GetPixel(int x, int y)
|
|
{
|
|
UINT nBitStart = 0;
|
|
BYTE* pPixel = NULL;
|
|
|
|
if (x < 0 || m_xMax < x || y < 0 || m_yMax < y)
|
|
return CLR_INVALID;
|
|
|
|
// retrieve bit data
|
|
nBitStart = m_nBitCount * x + m_nWidthBits * (m_bTopdown ? y : (m_yMax - y));
|
|
pPixel = m_pBits0 + (nBitStart >> 3);
|
|
|
|
if (m_nBitCount == 24)
|
|
return RGB(*(pPixel+2), *(pPixel+1), *pPixel);
|
|
|
|
ASSERT(m_pPalette && (m_nBitCount == 1 ||
|
|
m_nBitCount == 4 ||
|
|
m_nBitCount == 8));
|
|
BYTE nIndex = 0;
|
|
nIndex = *pPixel;
|
|
if (m_nBitCount < 8)
|
|
{
|
|
nIndex <<= (nBitStart & 7);
|
|
nIndex >>= m_nRightShift;
|
|
}
|
|
|
|
PALETTEENTRY pe;
|
|
if (m_pPalette->GetPaletteEntries(nIndex, 1, &pe))
|
|
return RGB(pe.peRed, pe.peGreen, pe.peBlue);
|
|
|
|
return CLR_INVALID;
|
|
}
|
|
|
|
// protected:
|
|
void COXSplashWndDIB::PrepareGetPixel(BITMAPINFOHEADER& bmih, int iNumColors)
|
|
// --- In : bmih: The DIB
|
|
// nNumColors : Number of colors in palette
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Prepares some internal variables for future GetPixel() calls.
|
|
{
|
|
// ... others are not supported
|
|
ASSERT(bmih.biCompression == BI_RGB);
|
|
|
|
::CopyMemory(&m_bmih, &bmih, bmih.biSize);
|
|
|
|
// DWROD aligned
|
|
DWORD nWidthDWORD = (bmih.biWidth * bmih.biBitCount + 31) >> 5;
|
|
m_nWidthBits = nWidthDWORD << 5;
|
|
|
|
DWORD nSizeImage = (nWidthDWORD << 2) * abs(bmih.biHeight);
|
|
m_bits.SetSize(nSizeImage);
|
|
::CopyMemory(m_bits.GetData(),
|
|
(BYTE*)&bmih + bmih.biSize + iNumColors * sizeof(RGBQUAD), nSizeImage);
|
|
|
|
// fill up cache values for GetPixel()
|
|
m_xMax = m_bmih.biWidth - 1;
|
|
m_yMax = abs(m_bmih.biHeight) - 1;
|
|
m_bTopdown = (m_bmih.biHeight < 0);
|
|
m_pBits0 = m_bits.GetData();
|
|
m_nBitCount = m_bmih.biBitCount;
|
|
m_nRightShift = 8 - m_bmih.biBitCount;
|
|
}
|
|
|
|
|
|
BOOL COXSplashWndDIB::CopyFile(CFile* pDestFile, CFile* pSourceFile)
|
|
{
|
|
ASSERT(pDestFile!=NULL);
|
|
ASSERT(pSourceFile!=NULL);
|
|
|
|
// use buffers
|
|
const int nBufferLength = 1024;
|
|
BYTE pBuffer[nBufferLength + 1];
|
|
int nLengthRead(0);
|
|
BOOL bSuccess = TRUE;
|
|
|
|
TRY
|
|
{
|
|
do
|
|
{
|
|
nLengthRead = pSourceFile->Read(pBuffer, nBufferLength);
|
|
pDestFile->Write(pBuffer, nLengthRead);
|
|
}
|
|
while (nLengthRead == nBufferLength); // So while not EOF
|
|
}
|
|
CATCH(CFileException, pxFile)
|
|
{
|
|
TRACE(_T("COXSplashWndDIB::CopyFile : Catching FileException (%XH)\n"),
|
|
pxFile->m_cause);
|
|
bSuccess = FALSE;
|
|
}
|
|
END_CATCH
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|