home *** CD-ROM | disk | FTP | other *** search
- // BmpProp.cpp : implementation file
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #include "image.h"
- #include "BmpProp.h"
- #include "ImageCtl.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- IMPLEMENT_DYNAMIC(CBitmapProperty, CDataPathProperty)
-
- /////////////////////////////////////////////////////////////////////////////
- // CBitmapProperty
-
- CBitmapProperty::CBitmapProperty(COleControl* pControl) : CDataPathProperty(pControl),
- m_dlState(dlNone)
- {
- }
-
- CBitmapProperty::~CBitmapProperty()
- {
- }
-
-
- // Do not edit the following lines, which are needed by ClassWizard.
- #if 0
- BEGIN_MESSAGE_MAP(CBitmapProperty, CDataPathProperty)
- //{{AFX_MSG_MAP(CBitmapProperty)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- #endif // 0
-
- /////////////////////////////////////////////////////////////////////////////
- // CBitmapProperty member functions
-
- void CBitmapProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
- {
- if (bscfFlag & BSCF_FIRSTDATANOTIFICATION)
- ResetData();
-
- CDataPathProperty::OnDataAvailable(dwSize, bscfFlag);
-
- if (dwSize <= m_cbRead)
- return;
- else
- dwSize -= m_cbRead;
- m_cbRead += dwSize;
-
- BOOL bContinue = m_dlState != dlDone;
- while (bContinue)
- {
- switch (m_dlState)
- {
- case dlNone:
- // Try to read the bitmapfileheader.
- {
- BITMAPFILEHEADER bmfh;
- if (ReadStruct(dwSize, &bmfh, sizeof(bmfh)))
- {
- ASSERT(bmfh.bfType == 'B' | ('M' << 8));
- m_dlState = dlFileHeader;
- }
- else
- {
- bContinue = FALSE;
- break;
- }
- }
- break;
-
- case dlFileHeader:
- // Try to read the bitmapinfoheader.
- if (ReadStruct(dwSize, &m_bmInfo.bmiHeader, sizeof(m_bmInfo.bmiHeader)))
- {
- // Now we know the image size.
- m_BitmapSize.cx = m_bmInfo.bmiHeader.biWidth;
- m_BitmapSize.cy = m_bmInfo.bmiHeader.biHeight;
- ASSERT_KINDOF(CImageCtrl, GetControl());
- ((CImageCtrl*)GetControl())->InformSize();
-
- m_dlState = dlInfoHeader;
- }
- else
- {
- bContinue = FALSE;
- break;
- }
- break;
-
- case dlInfoHeader:
- // Read the color table.
- if (ReadStruct(dwSize, &m_bmInfo.bmiColors,
- sizeof(RGBQUAD) * (1 << m_bmInfo.bmiHeader.biBitCount)))
- {
- // Create the bitmap.
- CWindowDC screenDC(NULL);
- m_Bitmap.CreateCompatibleBitmap(&screenDC, m_BitmapSize.cx, m_BitmapSize.cy);
-
- m_dlState = dlColorTable;
- }
- else
- {
- bContinue = FALSE;
- break;
- }
- break;
-
- case dlColorTable:
- // Read some pels.
- {
- BYTE* pb = NULL;
- int nLines = ReadArray(dwSize, (void **)&pb,
- ((((m_bmInfo.bmiHeader.biBitCount * m_BitmapSize.cx) + 31) / 32) * 4),
- m_BitmapSize.cy - m_nScanLine);
- if (nLines > 0)
- {
- CWindowDC screenDC(NULL);
- CDC dc;
- dc.CreateCompatibleDC(&screenDC);
- CBitmap* pBitmap = dc.SelectObject(&m_Bitmap);
-
- SetDIBits(dc.m_hDC, (HBITMAP)m_Bitmap.m_hObject, m_nScanLine, nLines,
- pb, &m_bmInfo, DIB_RGB_COLORS);
-
- m_nScanLine += nLines;
- GetControl()->Invalidate(FALSE);
- }
- else
- {
- bContinue = FALSE;
- break;
- }
-
- delete [] pb;
-
- if (m_nScanLine == m_BitmapSize.cy)
- m_dlState = dlDone;
- }
- break;
- }; //switch
-
- bContinue = bContinue && (m_dlState != dlDone);
- } //while
-
- ASSERT_KINDOF(CImageCtrl, GetControl());
- ((CImageCtrl*)GetControl())->InformDlStatus(m_dlState);
- }
-
- void CBitmapProperty::ResetData()
- {
- CDataPathProperty::ResetData();
- m_dlState = dlNone;
- if (m_Bitmap.m_hObject != NULL)
- m_Bitmap.DeleteObject();
-
- m_CacheFile.SetLength(0);
- m_nScanLine = 0;
- m_cbRead = 0;
- }
-
- DWORD AfxTransferFileContent(CFile* pFrom, CFile* pTo, DWORD dwAmount)
- {
- BYTE buff[1024];
- DWORD dwRead = 0;
- DWORD dwActual = 1; // bogus value to enter the loop
- while ((dwAmount > 0) && (dwActual > 0))
- {
- dwActual = pFrom->Read(buff, min(dwAmount, 1024));
- pTo->Write(buff, dwActual);
-
- dwAmount -= dwActual;
- dwRead += dwActual;
- }
- return dwRead;
- }
-
- BOOL CBitmapProperty::ReadStruct(DWORD& rdwSize, void* pb, int cLen)
- {
- // Cache contents.
- AfxTransferFileContent(this, &m_CacheFile, rdwSize);
- rdwSize = 0;
-
- // Do we have enough data yet?
- int cCache = m_CacheFile.GetLength();
- if (cCache >= cLen)
- {
- m_CacheFile.SeekToBegin();
- VERIFY(m_CacheFile.Read(pb, cLen) == (UINT)cLen);
-
- // Is there more?
- if (cCache > cLen)
- {
- CMemFile memFile;
- AfxTransferFileContent(&m_CacheFile, &memFile, cCache - cLen);
- m_CacheFile.SetLength(0);
- memFile.SeekToBegin();
- AfxTransferFileContent(&memFile, &m_CacheFile, cCache - cLen);
- }
- else
- {
- m_CacheFile.SetLength(0);
- }
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
- int CBitmapProperty::ReadArray(DWORD& rdwSize, void** pb, int cElem, int cMax)
- {
- // Cache contents.
- AfxTransferFileContent(this, &m_CacheFile, rdwSize);
- rdwSize = 0;
- int nElems = 0;
-
- // Do we have enough data yet?
- int cCache = m_CacheFile.GetLength();
- if (cCache >= cElem)
- {
- m_CacheFile.SeekToBegin();
-
- nElems = min(cCache / cElem, cMax);
- int cSize = nElems * cElem;
- ASSERT(cSize <= cCache);
-
- *pb = new BYTE[cSize];
- ASSERT(m_CacheFile.Read(*pb, cSize) == (UINT)cSize);
-
- // Is there more?
- if (cCache > cSize)
- {
- CMemFile memFile;
- AfxTransferFileContent(&m_CacheFile, &memFile, cCache - cSize);
- m_CacheFile.SetLength(0);
- memFile.SeekToBegin();
- AfxTransferFileContent(&memFile, &m_CacheFile, cCache - cSize);
- }
- else
- {
- m_CacheFile.SetLength(0);
- }
- }
-
- return nElems;
- }
-