home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / advanced / fire / firewnd.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  15KB  |  541 lines

  1. // firewnd.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 "fire.h"
  15. #include "firewnd.h"
  16.  
  17. #include <math.h> // for HSI conversion
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. static RGBQUAD rgbStd256[] =
  25. {
  26.     {   0,  0,  0, 0 }, {   0,  0,128, 0 }, {   0,128,  0, 0 }, {   0,128,128, 0 },
  27.     { 128,  0,  0, 0 }, { 128,  0,128, 0 }, { 128,128,  0, 0 }, { 192,192,192, 0 },
  28.     { 192,220,192, 0 }, { 240,202,166, 0 }, { 238,238,238, 0 }, { 221,221,221, 0 },
  29.     { 204,204,204, 0 }, { 187,187,187, 0 }, { 170,170,170, 0 }, { 153,153,153, 0 },
  30.     { 136,136,136, 0 }, { 119,119,119, 0 }, { 102,102,102, 0 }, {  85, 85, 85, 0 },
  31.     {  68, 68, 68, 0 }, {  51, 51, 51, 0 }, {  34, 34, 34, 0 }, {  17, 17, 17, 0 },
  32.     { 204,255,255, 0 }, { 153,255,255, 0 }, { 102,255,255, 0 }, {  51,255,255, 0 },
  33.     { 255,204,255, 0 }, { 204,204,255, 0 }, { 153,204,255, 0 }, { 102,204,255, 0 },
  34.     {  51,204,255, 0 }, {   0,204,255, 0 }, { 255,153,255, 0 }, { 204,153,255, 0 },
  35.     { 153,153,255, 0 }, { 102,153,255, 0 }, {  51,153,255, 0 }, {   0,153,255, 0 },
  36.     { 255,102,255, 0 }, { 204,102,255, 0 }, { 153,102,255, 0 }, { 102,102,255, 0 },
  37.     {  51,102,255, 0 }, {   0,102,255, 0 }, { 255, 51,255, 0 }, { 204, 51,255, 0 },
  38.     { 153, 51,255, 0 }, { 102, 51,255, 0 }, {  51, 51,255, 0 }, {   0, 51,255, 0 },
  39.     { 204,  0,255, 0 }, { 153,  0,255, 0 }, { 102,  0,255, 0 }, {  51,  0,255, 0 },
  40.     { 255,255,204, 0 }, { 204,255,204, 0 }, { 153,255,204, 0 }, { 102,255,204, 0 },
  41.     {  51,255,204, 0 }, {   0,255,204, 0 }, { 255,204,204, 0 }, { 153,204,204, 0 },
  42.     { 102,204,204, 0 }, {  51,204,204, 0 }, {   0,204,204, 0 }, { 255,153,204, 0 },
  43.     { 204,153,204, 0 }, { 153,153,204, 0 }, { 102,153,204, 0 }, {  51,153,204, 0 },
  44.     {   0,153,204, 0 }, { 255,102,204, 0 }, { 204,102,204, 0 }, { 153,102,204, 0 },
  45.     { 102,102,204, 0 }, {  51,102,204, 0 }, {   0,102,204, 0 }, { 255, 51,204, 0 },
  46.     { 204, 51,204, 0 }, { 153, 51,204, 0 }, { 102, 51,204, 0 }, {  51, 51,204, 0 },
  47.     {   0, 51,204, 0 }, { 255,  0,204, 0 }, { 204,  0,204, 0 }, { 153,  0,204, 0 },
  48.     { 102,  0,204, 0 }, {  51,  0,204, 0 }, { 255,255,153, 0 }, { 204,255,153, 0 },
  49.     { 153,255,153, 0 }, { 102,255,153, 0 }, {  51,255,153, 0 }, {   0,255,153, 0 },
  50.     { 255,204,153, 0 }, { 204,204,153, 0 }, { 153,204,153, 0 }, { 102,204,153, 0 },
  51.     {  51,204,153, 0 }, {   0,204,153, 0 }, { 255,153,153, 0 }, { 204,153,153, 0 },
  52.     { 102,153,153, 0 }, {  51,153,153, 0 }, {   0,153,153, 0 }, { 255,102,153, 0 },
  53.     { 204,102,153, 0 }, { 153,102,153, 0 }, { 102,102,153, 0 }, {  51,102,153, 0 },
  54.     {   0,102,153, 0 }, { 255, 51,153, 0 }, { 204, 51,153, 0 }, { 153, 51,153, 0 },
  55.     { 102, 51,153, 0 }, {  51, 51,153, 0 }, {   0, 51,153, 0 }, { 255,  0,153, 0 },
  56.     { 204,  0,153, 0 }, { 153,  0,153, 0 }, { 102,  0,153, 0 }, {  51,  0,153, 0 },
  57.     { 255,255,102, 0 }, { 204,255,102, 0 }, { 153,255,102, 0 }, { 102,255,102, 0 },
  58.     {  51,255,102, 0 }, {   0,255,102, 0 }, { 255,204,102, 0 }, { 204,204,102, 0 },
  59.     { 153,204,102, 0 }, { 102,204,102, 0 }, {  51,204,102, 0 }, {   0,204,102, 0 },
  60.     { 255,153,102, 0 }, { 204,153,102, 0 }, { 153,153,102, 0 }, { 102,153,102, 0 },
  61.     {  51,153,102, 0 }, {   0,153,102, 0 }, { 255,102,102, 0 }, { 204,102,102, 0 },
  62.     { 153,102,102, 0 }, {  51,102,102, 0 }, {   0,102,102, 0 }, { 255, 51,102, 0 },
  63.     { 204, 51,102, 0 }, { 153, 51,102, 0 }, { 102, 51,102, 0 }, {  51, 51,102, 0 },
  64.     {   0, 51,102, 0 }, { 255,  0,102, 0 }, { 204,  0,102, 0 }, { 153,  0,102, 0 },
  65.     { 102,  0,102, 0 }, {  51,  0,102, 0 }, { 255,255, 51, 0 }, { 204,255, 51, 0 },
  66.     { 153,255, 51, 0 }, { 102,255, 51, 0 }, {  51,255, 51, 0 }, {   0,255, 51, 0 },
  67.     { 255,204, 51, 0 }, { 204,204, 51, 0 }, { 153,204, 51, 0 }, { 102,204, 51, 0 },
  68.     {  51,204, 51, 0 }, {   0,204, 51, 0 }, { 255,153, 51, 0 }, { 204,153, 51, 0 },
  69.     { 153,153, 51, 0 }, { 102,153, 51, 0 }, {  51,153, 51, 0 }, {   0,153, 51, 0 },
  70.     { 255,102, 51, 0 }, { 204,102, 51, 0 }, { 153,102, 51, 0 }, { 102,102, 51, 0 },
  71.     {  51,102, 51, 0 }, {   0,102, 51, 0 }, { 255, 51, 51, 0 }, { 204, 51, 51, 0 },
  72.     { 153, 51, 51, 0 }, { 102, 51, 51, 0 }, {   0, 51, 51, 0 }, { 255,  0, 51, 0 },
  73.     { 204,  0, 51, 0 }, { 153,  0, 51, 0 }, { 102,  0, 51, 0 }, {  51,  0, 51, 0 },
  74.     { 204,255,  0, 0 }, { 153,255,  0, 0 }, { 102,255,  0, 0 }, {  51,255,  0, 0 },
  75.     { 255,204,  0, 0 }, { 204,204,  0, 0 }, { 153,204,  0, 0 }, { 102,204,  0, 0 },
  76.     {  51,204,  0, 0 }, { 255,153,  0, 0 }, { 204,153,  0, 0 }, { 153,153,  0, 0 },
  77.     { 102,153,  0, 0 }, {   0,  0,238, 0 }, {   0,  0,221, 0 }, {   0,  0,204, 0 },
  78.     {   0,  0,187, 0 }, {   0,  0,170, 0 }, {   0,  0,153, 0 }, {   0,  0,136, 0 },
  79.     {   0,  0,119, 0 }, {   0,  0,102, 0 }, {   0,  0, 85, 0 }, {   0,  0, 68, 0 },
  80.     {   0,  0, 51, 0 }, {   0,  0, 34, 0 }, {   0,  0, 17, 0 }, {   0,238,  0, 0 },
  81.     {   0,221,  0, 0 }, {   0,204,  0, 0 }, {   0,187,  0, 0 }, {   0,170,  0, 0 },
  82.     {   0,153,  0, 0 }, {   0,136,  0, 0 }, {   0,119,  0, 0 }, {   0,102,  0, 0 },
  83.     {   0, 85,  0, 0 }, {   0, 68,  0, 0 }, {   0, 51,  0, 0 }, {   0, 34,  0, 0 },
  84.     {   0, 17,  0, 0 }, { 238,  0,  0, 0 }, { 221,  0,  0, 0 }, { 204,  0,  0, 0 },
  85.     { 187,  0,  0, 0 }, { 170,  0,  0, 0 }, { 153,  0,  0, 0 }, { 136,  0,  0, 0 },
  86.     { 119,  0,  0, 0 }, { 102,  0,  0, 0 }, {  85,  0,  0, 0 }, {  68,  0,  0, 0 },
  87.     {  51,  0,  0, 0 }, {  34,  0,  0, 0 }, { 240,251,255, 0 }, { 164,160,160, 0 },
  88.     { 128,128,128, 0 }, {   0,  0,255, 0 }, {   0,255,  0, 0 }, {   0,255,255, 0 },
  89.     { 255,  0,  0, 0 }, { 255,  0,255, 0 }, { 255,255,  0, 0 }, { 255,255,255, 0 }
  90. };
  91.  
  92.  
  93. /////////////////////////////////////////////////////////////////////////////
  94. // CFireWnd
  95.  
  96. // Initialize the seed for random number generation.  For a more random
  97. // flame this could be initialized by a call to ::rand().  Declaring it
  98. // this way causes the same flame to be drawn each time the application
  99. // is executed.
  100. unsigned long CFireWnd::m_RandSeed = 0x38549391;
  101.  
  102. CFireWnd::CFireWnd()
  103. {
  104.     m_nDecay = 5;
  105.     m_nFlammability = 385;
  106.     m_nMaxHeat = 223;
  107.     m_nSpreadRate = 20;
  108.     m_nSmoothness = 1;
  109.     m_nDistribution = 1;
  110.     m_nChaos = 50;
  111.  
  112.     m_nSize = 0;
  113.     m_MaxBurn = 0;
  114.     m_Fire = NULL;
  115.  
  116.     m_pMemDC = NULL;
  117.     m_pWinDC = NULL;
  118.     m_pOldPalette = NULL;
  119.     m_pOldBitmap = NULL;
  120. }
  121.  
  122. CFireWnd::~CFireWnd()
  123. {
  124. }
  125.  
  126. BEGIN_MESSAGE_MAP(CFireWnd, CStatic)
  127.     //{{AFX_MSG_MAP(CFireWnd)
  128.     ON_WM_PAINT()
  129.     ON_WM_DESTROY()
  130.     ON_WM_PALETTECHANGED()
  131.     ON_WM_QUERYNEWPALETTE()
  132.     //}}AFX_MSG_MAP
  133. END_MESSAGE_MAP()
  134.  
  135. /////////////////////////////////////////////////////////////////////////////
  136. // CFireWnd Operations
  137.  
  138. void CFireWnd::InitFire(int nColor)
  139. {
  140.     CreatePalette(nColor);
  141.  
  142.     CreateBitmap();
  143.  
  144.     {
  145.         CWnd* pActiveWnd = CWnd::GetActiveWindow();
  146.         if (pActiveWnd != NULL)
  147.             pActiveWnd->SendMessage(WM_QUERYNEWPALETTE);
  148.     }
  149. }
  150.  
  151. CPalette* CFireWnd::GetPalette()
  152. {
  153.     if (m_Palette.m_hObject != NULL)
  154.         return &m_Palette;
  155.     else
  156.         return NULL;
  157. }
  158.  
  159. void CFireWnd::CreatePalette(int nColor)
  160. {
  161.     UINT i;
  162.  
  163.     if (m_Palette.m_hObject != NULL)
  164.         m_Palette.DeleteObject();
  165.  
  166.     memcpy( m_rgbPalette, rgbStd256, sizeof(RGBQUAD) * 256 );
  167.  
  168.     int r,g,b;
  169.  
  170.     switch(nColor)
  171.     {
  172.     case blue:
  173.         b = 256+256+255;
  174.         g = 256+255;
  175.         r = 255;
  176.         break;
  177.     case green:
  178.         g = 256+256+255;
  179.         r = 256+255;
  180.         b = 255;
  181.         break;
  182.     case red:
  183.     default:
  184.         r = 256+256+255;
  185.         g = 256+255;
  186.         b = 255;
  187.         break;
  188.     }
  189.  
  190.     for(i = 239; i > 15; i--)
  191.     {
  192.         m_rgbPalette[i].rgbRed = (r > 255) ? 255 : r;
  193.         m_rgbPalette[i].rgbGreen = (g > 255) ? 255 : g;
  194.         m_rgbPalette[i].rgbBlue = (b > 255) ? 255 : b;
  195.         r = (r > 3) ? (r - 4) : 0;
  196.         g = (g > 3) ? (g - 4) : 0;
  197.         b = (b > 3) ? (b - 4) : 0;
  198.     }
  199.  
  200.     LPLOGPALETTE lpLogPal;
  201.     lpLogPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + ((255) * sizeof(PALETTEENTRY))];
  202.     lpLogPal->palVersion = 0x0300;
  203.     lpLogPal->palNumEntries = 256;
  204.  
  205.     for (i = 0; i < 256; i++)
  206.     {
  207.         lpLogPal->palPalEntry[i].peRed = m_rgbPalette[i].rgbRed;
  208.         lpLogPal->palPalEntry[i].peGreen = m_rgbPalette[i].rgbGreen;
  209.         lpLogPal->palPalEntry[i].peBlue = m_rgbPalette[i].rgbBlue;
  210.         lpLogPal->palPalEntry[i].peFlags = 0;
  211.     }
  212.  
  213.     VERIFY( m_Palette.CreatePalette( lpLogPal ) );
  214.     delete [] (BYTE *)lpLogPal;
  215. }
  216.  
  217. CSize CFireWnd::GetBitmapSize()
  218. {
  219.     if (m_Bitmap.m_hObject == NULL)
  220.         return CSize(0,0);
  221.  
  222.     BITMAP bm;
  223.     m_Bitmap.GetObject( sizeof(BITMAP), &bm );
  224.     return CSize(bm.bmWidth, bm.bmHeight);
  225. }
  226.  
  227. #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
  228.  
  229. void CFireWnd::CreateBitmap()
  230. {
  231.     if (m_pMemDC != NULL)
  232.     {
  233.         m_pMemDC->SelectObject(m_pOldBitmap);
  234.         delete m_pMemDC;
  235.         m_pMemDC = NULL;
  236.         m_pOldBitmap = NULL;
  237.     }
  238.  
  239.     if (m_pWinDC != NULL)
  240.     {
  241.         m_pWinDC->SelectObject(m_pOldPalette);
  242.         delete m_pWinDC;
  243.         m_pWinDC = NULL;
  244.         m_pOldPalette = NULL;
  245.     }
  246.  
  247.     if (m_Bitmap.m_hObject != NULL)
  248.         m_Bitmap.DeleteObject();
  249.  
  250.     if (m_Fire != NULL)
  251.     {
  252.         delete m_Fire;
  253.         m_Fire = NULL;
  254.     }
  255.  
  256.     CRect rect;
  257.     CSize size;
  258.  
  259.     GetClientRect(&rect);
  260.     size = rect.Size();
  261.  
  262.     if (m_MaxBurn == 0)
  263.         m_MaxBurn = (int)(size.cy * 0.75);
  264.  
  265.     if (m_nSize == 0)
  266.         m_nSize = (int)(size.cx / 2);
  267.  
  268.     m_Fire = new BYTE[size.cx];
  269.  
  270.     LPBITMAPINFO lpbi;
  271.  
  272.     // Fill in the BITMAPINFOHEADER
  273.     lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
  274.     lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  275.     lpbi->bmiHeader.biWidth = size.cx;
  276.     lpbi->bmiHeader.biHeight = size.cy;
  277.     lpbi->bmiHeader.biPlanes = 1;
  278.     lpbi->bmiHeader.biBitCount = 8;
  279.     lpbi->bmiHeader.biCompression = BI_RGB;
  280.     lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)size.cx * 8) * size.cy;
  281.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  282.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  283.     lpbi->bmiHeader.biClrUsed = 0;
  284.     lpbi->bmiHeader.biClrImportant = 0;
  285.  
  286.     // Fill in the color table
  287.     UINT uUsage = DIB_RGB_COLORS;
  288.     memcpy( lpbi->bmiColors, m_rgbPalette, sizeof(RGBQUAD) * 256 );
  289.  
  290.     m_pWinDC = new CWindowDC(this);
  291.  
  292.     HBITMAP hBitmap = CreateDIBSection( m_pWinDC->m_hDC, lpbi, uUsage, (void **)&m_pBits, NULL, 0 );
  293.  
  294.     delete [] (BYTE *)lpbi;
  295.  
  296.     ASSERT(hBitmap != NULL);
  297.  
  298.     m_Bitmap.Attach( hBitmap );
  299.  
  300.     for (int y = 0; y < size.cy; y++ )
  301.     {
  302.         BYTE* pRow = (m_pBits + WIDTHBYTES((DWORD)size.cx * 8) * y);
  303.         for (int x = 0; x < size.cx; x++ )
  304.             *pRow++ = 16;
  305.     }
  306.  
  307.     m_pMemDC = new CDC;
  308.  
  309.     VERIFY( m_pMemDC->CreateCompatibleDC(m_pWinDC) );
  310.  
  311.     m_pOldPalette = m_pWinDC->SelectPalette( &m_Palette, FALSE );
  312.     m_pWinDC->RealizePalette();
  313.     m_pOldBitmap = m_pMemDC->SelectObject( &m_Bitmap );
  314.  
  315.     for (int x = 0; x < size.cx; x++ )
  316.         m_Fire[x] = 16;
  317. }
  318.  
  319. //
  320. //  This routine was adapted from a pascal routine written by
  321. //  Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk)
  322. //
  323. //  See AboutBox for a special thank you for all his work.
  324. //
  325.  
  326. void CFireWnd::RenderFlame()
  327. {
  328.     CSize size = GetBitmapSize();
  329.     int xStart, xEnd, x, y;
  330.     BYTE* pRow;
  331.     BYTE* pNextRow;
  332.  
  333.     xStart = (size.cx - m_nSize) / 2;
  334.     xEnd = xStart + m_nSize + 1;
  335.  
  336.     {
  337.         pRow = m_pBits;
  338.         for (x=0;x<size.cx;x++)
  339.         {
  340.             if (x < (xStart + m_nDistribution) || x >= (xEnd - m_nDistribution))
  341.                 m_Fire[x] = 16;
  342.             *pRow++ = m_Fire[x];
  343.         }
  344.     }
  345.  
  346.     for (y = m_MaxBurn; y > 0; y--)
  347.     {
  348.         pRow = (m_pBits + WIDTHBYTES((DWORD)size.cx * 8) * y);
  349.         pNextRow = (m_pBits + WIDTHBYTES((DWORD)size.cx * 8) * (y - 1));
  350.  
  351.         if ((rand() % 2) == 0)
  352.         {
  353.             for (x = 0; x < size.cx; x++)
  354.             {
  355.                 BurnPoint(pRow, pNextRow);
  356.                 pRow++;
  357.                 pNextRow++;
  358.             }
  359.         }
  360.         else
  361.         {
  362.             pRow += size.cx - 1;
  363.             pNextRow += size.cx - 1;
  364.             for (x = 0; x < size.cx; x++)
  365.             {
  366.                 BurnPoint(pRow, pNextRow);
  367.                 pRow--;
  368.                 pNextRow--;
  369.             }
  370.         }
  371.     }
  372.  
  373.     int MaxHeat = m_nMaxHeat + 16;
  374.  
  375.     if ( rand() % (400 - m_nFlammability) == 0)
  376.     {
  377.         int off = m_nSize - 5;
  378.         off = rand() % off;
  379.         off += xStart;
  380.  
  381.         for (x = off; x < off + 5; x++)
  382.             m_Fire[x] = 239;
  383.     }
  384.  
  385.     for (x = xStart; x < xEnd; x++)
  386.     {
  387.         if (m_Fire[x] < MaxHeat)
  388.         {
  389.             int val = rand() % m_nChaos+1;
  390.             val -= m_nChaos / 2;
  391.             val += m_nSpreadRate;
  392.             val += m_Fire[x];
  393.  
  394.             if ( val > MaxHeat)
  395.                 m_Fire[x] = MaxHeat;
  396.             else if ( val < 16)
  397.                 m_Fire[x] = 16;
  398.             else
  399.                 m_Fire[x] = val;
  400.         }
  401.         else
  402.             m_Fire[x] = MaxHeat;
  403.     }
  404.  
  405.     if (m_nSmoothness > 0)
  406.     {
  407.         xStart += m_nSmoothness;
  408.         xEnd -= m_nSmoothness;
  409.         for (x = xStart; x < xEnd; x++)
  410.         {
  411.             int val = 0;
  412.             for (y = x - m_nSmoothness; y < x + 1 + m_nSmoothness; y++)
  413.                 val += m_Fire[y];
  414.  
  415.             m_Fire[x] = val / (2*m_nSmoothness+1);
  416.         }
  417.     }
  418. }
  419.  
  420. void CFireWnd::PaintFlame(CDC* pDC)
  421. {
  422.     if (m_Palette.m_hObject != NULL  && m_Bitmap.m_hObject != NULL)
  423.     {
  424.         CSize size = GetBitmapSize();
  425.  
  426.         if (pDC != NULL)
  427.         {
  428.             CDC dc;
  429.             CPalette *pOldPalette;
  430.  
  431.             pOldPalette = pDC->SelectPalette( &m_Palette, FALSE );
  432.             pDC->RealizePalette();
  433.             VERIFY( dc.CreateCompatibleDC(pDC) );
  434.             CBitmap* pOldBitmap = dc.SelectObject( &m_Bitmap );
  435.             pDC->BitBlt( 0, 0, size.cx, size.cy, &dc, 0, 0, SRCCOPY );
  436.             dc.SelectObject(pOldBitmap);
  437.             pDC->SelectPalette( pOldPalette, TRUE );
  438.         }
  439.         else
  440.         {
  441.             m_pWinDC->BitBlt( 0, 0, size.cx, size.cy, m_pMemDC, 0, 0, SRCCOPY );
  442.         }
  443.     }
  444. }
  445.  
  446. void CFireWnd::SetMaxBurn(int nMax)
  447. {
  448.     if (m_Palette.m_hObject != NULL  && m_Bitmap.m_hObject != NULL)
  449.     {
  450.         CSize size = GetBitmapSize();
  451.  
  452.         m_MaxBurn = (int)(size.cy * (nMax/100.0));
  453.  
  454.         int y;
  455.         for (y = (size.cy - 1); y > m_MaxBurn; y--)
  456.         {
  457.             BYTE* pRow = (m_pBits + WIDTHBYTES((DWORD)size.cx * 8) * y);
  458.             for (int x = 0; x < size.cx; x++)
  459.                 *pRow++ = 16;
  460.         }
  461.     }
  462. }
  463.  
  464. int CFireWnd::GetMaxBurn()
  465. {
  466.     return m_MaxBurn;
  467. }
  468.  
  469. /////////////////////////////////////////////////////////////////////////////
  470. // CFireWnd message handlers
  471.  
  472. void CFireWnd::OnDestroy()
  473. {
  474.     CStatic::OnDestroy();
  475.  
  476.     if (m_pMemDC != NULL)
  477.     {
  478.         m_pMemDC->SelectObject(m_pOldBitmap);
  479.         delete m_pMemDC;
  480.         m_pMemDC = NULL;
  481.         m_pOldBitmap = NULL;
  482.     }
  483.  
  484.     if (m_pWinDC != NULL)
  485.     {
  486.         m_pWinDC->SelectObject(m_pOldPalette);
  487.         delete m_pWinDC;
  488.         m_pWinDC = NULL;
  489.         m_pOldPalette = NULL;
  490.     }
  491.  
  492.     if (m_Bitmap.m_hObject != NULL)
  493.         m_Bitmap.DeleteObject();
  494.  
  495.     if (m_Palette.m_hObject != NULL)
  496.         m_Palette.DeleteObject();
  497.  
  498.     if (m_Fire != NULL)
  499.     {
  500.         delete m_Fire;
  501.         m_Fire = NULL;
  502.     }
  503. }
  504.  
  505. void CFireWnd::OnPaint()
  506. {
  507.     CPaintDC dc(this); // device context for painting
  508.  
  509.     PaintFlame(&dc);
  510. }
  511.  
  512. void CFireWnd::OnPaletteChanged(CWnd* pFocusWnd)
  513. {
  514.     if (pFocusWnd == this || IsChild(pFocusWnd))
  515.         return;
  516.  
  517.     OnQueryNewPalette();
  518. }
  519.  
  520. BOOL CFireWnd::OnQueryNewPalette()
  521. {
  522.     if (GetPalette() == NULL)
  523.         return FALSE;
  524.  
  525.     {
  526.         CClientDC dc(this);
  527.         CPalette* pOldPalette = dc.SelectPalette(&m_Palette,
  528.             GetCurrentMessage()->message == WM_PALETTECHANGED);
  529.         UINT nChanged = dc.RealizePalette();
  530.         dc.SelectPalette(pOldPalette, TRUE);
  531.  
  532.         if (nChanged == 0)  // no change to our mapping
  533.             return FALSE;
  534.     }
  535.  
  536.     // some changes have been made; invalidate
  537.     Invalidate(FALSE);
  538.  
  539.     return TRUE;
  540. }
  541.