home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / controls / image / bmpprop.cpp next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  5.9 KB  |  263 lines

  1. // BmpProp.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "image.h"
  15. #include "BmpProp.h"
  16. #include "ImageCtl.h"
  17.  
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. IMPLEMENT_DYNAMIC(CBitmapProperty, CDataPathProperty)
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CBitmapProperty
  28.  
  29. CBitmapProperty::CBitmapProperty(COleControl* pControl) : CDataPathProperty(pControl),
  30.     m_dlState(dlNone)
  31. {
  32. }
  33.  
  34. CBitmapProperty::~CBitmapProperty()
  35. {
  36. }
  37.  
  38.  
  39. // Do not edit the following lines, which are needed by ClassWizard.
  40. #if 0
  41. BEGIN_MESSAGE_MAP(CBitmapProperty, CDataPathProperty)
  42.     //{{AFX_MSG_MAP(CBitmapProperty)
  43.     //}}AFX_MSG_MAP
  44. END_MESSAGE_MAP()
  45. #endif  // 0
  46.  
  47. /////////////////////////////////////////////////////////////////////////////
  48. // CBitmapProperty member functions
  49.  
  50. void CBitmapProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
  51. {
  52.     if (bscfFlag & BSCF_FIRSTDATANOTIFICATION)
  53.         ResetData();
  54.  
  55.     CDataPathProperty::OnDataAvailable(dwSize, bscfFlag);
  56.  
  57.     if (dwSize <= m_cbRead)
  58.         return;
  59.     else
  60.         dwSize -= m_cbRead;
  61.     m_cbRead += dwSize;
  62.  
  63.     BOOL bContinue = m_dlState != dlDone;
  64.     while (bContinue)
  65.     {
  66.         switch (m_dlState)
  67.         {
  68.         case dlNone:
  69.             // Try to read the bitmapfileheader.
  70.             {
  71.                 BITMAPFILEHEADER bmfh;
  72.                 if (ReadStruct(dwSize, &bmfh, sizeof(bmfh)))
  73.                 {
  74.                     ASSERT(bmfh.bfType == 'B' | ('M' << 8));
  75.                     m_dlState = dlFileHeader;
  76.                 }
  77.                 else
  78.                 {
  79.                     bContinue = FALSE;
  80.                     break;
  81.                 }
  82.             }
  83.             break;
  84.  
  85.         case dlFileHeader:
  86.             // Try to read the bitmapinfoheader.
  87.             if (ReadStruct(dwSize, &m_bmInfo.bmiHeader, sizeof(m_bmInfo.bmiHeader)))
  88.             {
  89.                 // Now we know the image size.
  90.                 m_BitmapSize.cx = m_bmInfo.bmiHeader.biWidth;
  91.                 m_BitmapSize.cy = m_bmInfo.bmiHeader.biHeight;
  92.                 ASSERT_KINDOF(CImageCtrl, GetControl());
  93.                 ((CImageCtrl*)GetControl())->InformSize();
  94.  
  95.                 m_dlState = dlInfoHeader;
  96.             }
  97.             else
  98.             {
  99.                 bContinue = FALSE;
  100.                 break;
  101.             }
  102.             break;
  103.  
  104.         case dlInfoHeader:
  105.             // Read the color table.
  106.             if (ReadStruct(dwSize, &m_bmInfo.bmiColors,
  107.                 sizeof(RGBQUAD) * (1 << m_bmInfo.bmiHeader.biBitCount)))
  108.             {
  109.                 // Create the bitmap.
  110.                 CWindowDC screenDC(NULL);
  111.                 m_Bitmap.CreateCompatibleBitmap(&screenDC, m_BitmapSize.cx, m_BitmapSize.cy);
  112.  
  113.                 m_dlState =  dlColorTable;
  114.             }
  115.             else
  116.             {
  117.                 bContinue = FALSE;
  118.                 break;
  119.             }
  120.             break;
  121.  
  122.         case dlColorTable:
  123.             // Read some pels.
  124.             {
  125.                 BYTE* pb = NULL;
  126.                 int nLines = ReadArray(dwSize, (void **)&pb,
  127.                     ((((m_bmInfo.bmiHeader.biBitCount * m_BitmapSize.cx) + 31) / 32) * 4),
  128.                         m_BitmapSize.cy - m_nScanLine);
  129.                 if (nLines > 0)
  130.                 {
  131.                     CWindowDC screenDC(NULL);
  132.                     CDC dc;
  133.                     dc.CreateCompatibleDC(&screenDC);
  134.                     CBitmap* pBitmap = dc.SelectObject(&m_Bitmap);
  135.  
  136.                     SetDIBits(dc.m_hDC, (HBITMAP)m_Bitmap.m_hObject, m_nScanLine, nLines,
  137.                                  pb, &m_bmInfo, DIB_RGB_COLORS);
  138.  
  139.                     m_nScanLine += nLines;
  140.                     GetControl()->Invalidate(FALSE);
  141.                 }
  142.                 else
  143.                 {
  144.                     bContinue = FALSE;
  145.                     break;
  146.                 }
  147.  
  148.                 delete [] pb;
  149.  
  150.                 if (m_nScanLine == m_BitmapSize.cy)
  151.                     m_dlState = dlDone;
  152.             }
  153.             break;
  154.         }; //switch
  155.  
  156.         bContinue = bContinue && (m_dlState != dlDone);
  157.     } //while
  158.  
  159.     ASSERT_KINDOF(CImageCtrl, GetControl());
  160.     ((CImageCtrl*)GetControl())->InformDlStatus(m_dlState);
  161. }
  162.  
  163. void CBitmapProperty::ResetData()
  164. {
  165.     CDataPathProperty::ResetData();
  166.     m_dlState = dlNone;
  167.     if (m_Bitmap.m_hObject != NULL)
  168.         m_Bitmap.DeleteObject();
  169.  
  170.     m_CacheFile.SetLength(0);
  171.     m_nScanLine = 0;
  172.     m_cbRead = 0;
  173. }
  174.  
  175. DWORD AfxTransferFileContent(CFile* pFrom, CFile* pTo, DWORD dwAmount)
  176. {
  177.     BYTE buff[1024];
  178.     DWORD dwRead = 0;
  179.     DWORD dwActual = 1; // bogus value to enter the loop
  180.     while ((dwAmount > 0) && (dwActual > 0))
  181.     {
  182.         dwActual = pFrom->Read(buff, min(dwAmount, 1024));
  183.         pTo->Write(buff, dwActual);
  184.  
  185.         dwAmount -= dwActual;
  186.         dwRead += dwActual;
  187.     }
  188.     return dwRead;
  189. }
  190.  
  191. BOOL CBitmapProperty::ReadStruct(DWORD& rdwSize, void* pb, int cLen)
  192. {
  193.     // Cache contents.
  194.     AfxTransferFileContent(this, &m_CacheFile, rdwSize);
  195.     rdwSize = 0;
  196.  
  197.     // Do we have enough data yet?
  198.     int cCache = m_CacheFile.GetLength();
  199.     if (cCache >= cLen)
  200.     {
  201.         m_CacheFile.SeekToBegin();
  202.         VERIFY(m_CacheFile.Read(pb, cLen) == (UINT)cLen);
  203.  
  204.         // Is there more?
  205.         if (cCache > cLen)
  206.         {
  207.             CMemFile memFile;
  208.             AfxTransferFileContent(&m_CacheFile, &memFile, cCache - cLen);
  209.             m_CacheFile.SetLength(0);
  210.             memFile.SeekToBegin();
  211.             AfxTransferFileContent(&memFile, &m_CacheFile, cCache - cLen);
  212.         }
  213.         else
  214.         {
  215.             m_CacheFile.SetLength(0);
  216.         }
  217.  
  218.         return TRUE;
  219.     }
  220.     else
  221.     {
  222.         return FALSE;
  223.     }
  224. }
  225.  
  226. int CBitmapProperty::ReadArray(DWORD& rdwSize, void** pb, int cElem, int cMax)
  227. {
  228.     // Cache contents.
  229.     AfxTransferFileContent(this, &m_CacheFile, rdwSize);
  230.     rdwSize = 0;
  231.     int nElems = 0;
  232.  
  233.     // Do we have enough data yet?
  234.     int cCache = m_CacheFile.GetLength();
  235.     if (cCache >= cElem)
  236.     {
  237.         m_CacheFile.SeekToBegin();
  238.  
  239.         nElems = min(cCache / cElem, cMax);
  240.         int cSize = nElems * cElem;
  241.         ASSERT(cSize <= cCache);
  242.  
  243.         *pb = new BYTE[cSize];
  244.         ASSERT(m_CacheFile.Read(*pb, cSize) == (UINT)cSize);
  245.  
  246.         // Is there more?
  247.         if (cCache > cSize)
  248.         {
  249.             CMemFile memFile;
  250.             AfxTransferFileContent(&m_CacheFile, &memFile, cCache - cSize);
  251.             m_CacheFile.SetLength(0);
  252.             memFile.SeekToBegin();
  253.             AfxTransferFileContent(&memFile, &m_CacheFile, cCache - cSize);
  254.         }
  255.         else
  256.         {
  257.             m_CacheFile.SetLength(0);
  258.         }
  259.     }
  260.  
  261.     return nElems;
  262. }
  263.