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

  1. // FireWnd.cpp : Implementation of CFireWnd
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12.  
  13. #include "stdafx.h"
  14. #include "FireWnd.h"
  15. #include "propdlg.h"
  16.  
  17. static RGBQUAD rgbStd256[] =
  18. {
  19.     {   0,  0,  0, 0 }, {   0,  0,128, 0 }, {   0,128,  0, 0 }, {   0,128,128, 0 },
  20.     { 128,  0,  0, 0 }, { 128,  0,128, 0 }, { 128,128,  0, 0 }, { 192,192,192, 0 },
  21.     { 192,220,192, 0 }, { 240,202,166, 0 }, { 238,238,238, 0 }, { 221,221,221, 0 },
  22.     { 204,204,204, 0 }, { 187,187,187, 0 }, { 170,170,170, 0 }, { 153,153,153, 0 },
  23.     { 136,136,136, 0 }, { 119,119,119, 0 }, { 102,102,102, 0 }, {  85, 85, 85, 0 },
  24.     {  68, 68, 68, 0 }, {  51, 51, 51, 0 }, {  34, 34, 34, 0 }, {  17, 17, 17, 0 },
  25.     { 204,255,255, 0 }, { 153,255,255, 0 }, { 102,255,255, 0 }, {  51,255,255, 0 },
  26.     { 255,204,255, 0 }, { 204,204,255, 0 }, { 153,204,255, 0 }, { 102,204,255, 0 },
  27.     {  51,204,255, 0 }, {   0,204,255, 0 }, { 255,153,255, 0 }, { 204,153,255, 0 },
  28.     { 153,153,255, 0 }, { 102,153,255, 0 }, {  51,153,255, 0 }, {   0,153,255, 0 },
  29.     { 255,102,255, 0 }, { 204,102,255, 0 }, { 153,102,255, 0 }, { 102,102,255, 0 },
  30.     {  51,102,255, 0 }, {   0,102,255, 0 }, { 255, 51,255, 0 }, { 204, 51,255, 0 },
  31.     { 153, 51,255, 0 }, { 102, 51,255, 0 }, {  51, 51,255, 0 }, {   0, 51,255, 0 },
  32.     { 204,  0,255, 0 }, { 153,  0,255, 0 }, { 102,  0,255, 0 }, {  51,  0,255, 0 },
  33.     { 255,255,204, 0 }, { 204,255,204, 0 }, { 153,255,204, 0 }, { 102,255,204, 0 },
  34.     {  51,255,204, 0 }, {   0,255,204, 0 }, { 255,204,204, 0 }, { 153,204,204, 0 },
  35.     { 102,204,204, 0 }, {  51,204,204, 0 }, {   0,204,204, 0 }, { 255,153,204, 0 },
  36.     { 204,153,204, 0 }, { 153,153,204, 0 }, { 102,153,204, 0 }, {  51,153,204, 0 },
  37.     {   0,153,204, 0 }, { 255,102,204, 0 }, { 204,102,204, 0 }, { 153,102,204, 0 },
  38.     { 102,102,204, 0 }, {  51,102,204, 0 }, {   0,102,204, 0 }, { 255, 51,204, 0 },
  39.     { 204, 51,204, 0 }, { 153, 51,204, 0 }, { 102, 51,204, 0 }, {  51, 51,204, 0 },
  40.     {   0, 51,204, 0 }, { 255,  0,204, 0 }, { 204,  0,204, 0 }, { 153,  0,204, 0 },
  41.     { 102,  0,204, 0 }, {  51,  0,204, 0 }, { 255,255,153, 0 }, { 204,255,153, 0 },
  42.     { 153,255,153, 0 }, { 102,255,153, 0 }, {  51,255,153, 0 }, {   0,255,153, 0 },
  43.     { 255,204,153, 0 }, { 204,204,153, 0 }, { 153,204,153, 0 }, { 102,204,153, 0 },
  44.     {  51,204,153, 0 }, {   0,204,153, 0 }, { 255,153,153, 0 }, { 204,153,153, 0 },
  45.     { 102,153,153, 0 }, {  51,153,153, 0 }, {   0,153,153, 0 }, { 255,102,153, 0 },
  46.     { 204,102,153, 0 }, { 153,102,153, 0 }, { 102,102,153, 0 }, {  51,102,153, 0 },
  47.     {   0,102,153, 0 }, { 255, 51,153, 0 }, { 204, 51,153, 0 }, { 153, 51,153, 0 },
  48.     { 102, 51,153, 0 }, {  51, 51,153, 0 }, {   0, 51,153, 0 }, { 255,  0,153, 0 },
  49.     { 204,  0,153, 0 }, { 153,  0,153, 0 }, { 102,  0,153, 0 }, {  51,  0,153, 0 },
  50.     { 255,255,102, 0 }, { 204,255,102, 0 }, { 153,255,102, 0 }, { 102,255,102, 0 },
  51.     {  51,255,102, 0 }, {   0,255,102, 0 }, { 255,204,102, 0 }, { 204,204,102, 0 },
  52.     { 153,204,102, 0 }, { 102,204,102, 0 }, {  51,204,102, 0 }, {   0,204,102, 0 },
  53.     { 255,153,102, 0 }, { 204,153,102, 0 }, { 153,153,102, 0 }, { 102,153,102, 0 },
  54.     {  51,153,102, 0 }, {   0,153,102, 0 }, { 255,102,102, 0 }, { 204,102,102, 0 },
  55.     { 153,102,102, 0 }, {  51,102,102, 0 }, {   0,102,102, 0 }, { 255, 51,102, 0 },
  56.     { 204, 51,102, 0 }, { 153, 51,102, 0 }, { 102, 51,102, 0 }, {  51, 51,102, 0 },
  57.     {   0, 51,102, 0 }, { 255,  0,102, 0 }, { 204,  0,102, 0 }, { 153,  0,102, 0 },
  58.     { 102,  0,102, 0 }, {  51,  0,102, 0 }, { 255,255, 51, 0 }, { 204,255, 51, 0 },
  59.     { 153,255, 51, 0 }, { 102,255, 51, 0 }, {  51,255, 51, 0 }, {   0,255, 51, 0 },
  60.     { 255,204, 51, 0 }, { 204,204, 51, 0 }, { 153,204, 51, 0 }, { 102,204, 51, 0 },
  61.     {  51,204, 51, 0 }, {   0,204, 51, 0 }, { 255,153, 51, 0 }, { 204,153, 51, 0 },
  62.     { 153,153, 51, 0 }, { 102,153, 51, 0 }, {  51,153, 51, 0 }, {   0,153, 51, 0 },
  63.     { 255,102, 51, 0 }, { 204,102, 51, 0 }, { 153,102, 51, 0 }, { 102,102, 51, 0 },
  64.     {  51,102, 51, 0 }, {   0,102, 51, 0 }, { 255, 51, 51, 0 }, { 204, 51, 51, 0 },
  65.     { 153, 51, 51, 0 }, { 102, 51, 51, 0 }, {   0, 51, 51, 0 }, { 255,  0, 51, 0 },
  66.     { 204,  0, 51, 0 }, { 153,  0, 51, 0 }, { 102,  0, 51, 0 }, {  51,  0, 51, 0 },
  67.     { 204,255,  0, 0 }, { 153,255,  0, 0 }, { 102,255,  0, 0 }, {  51,255,  0, 0 },
  68.     { 255,204,  0, 0 }, { 204,204,  0, 0 }, { 153,204,  0, 0 }, { 102,204,  0, 0 },
  69.     {  51,204,  0, 0 }, { 255,153,  0, 0 }, { 204,153,  0, 0 }, { 153,153,  0, 0 },
  70.     { 102,153,  0, 0 }, {   0,  0,238, 0 }, {   0,  0,221, 0 }, {   0,  0,204, 0 },
  71.     {   0,  0,187, 0 }, {   0,  0,170, 0 }, {   0,  0,153, 0 }, {   0,  0,136, 0 },
  72.     {   0,  0,119, 0 }, {   0,  0,102, 0 }, {   0,  0, 85, 0 }, {   0,  0, 68, 0 },
  73.     {   0,  0, 51, 0 }, {   0,  0, 34, 0 }, {   0,  0, 17, 0 }, {   0,238,  0, 0 },
  74.     {   0,221,  0, 0 }, {   0,204,  0, 0 }, {   0,187,  0, 0 }, {   0,170,  0, 0 },
  75.     {   0,153,  0, 0 }, {   0,136,  0, 0 }, {   0,119,  0, 0 }, {   0,102,  0, 0 },
  76.     {   0, 85,  0, 0 }, {   0, 68,  0, 0 }, {   0, 51,  0, 0 }, {   0, 34,  0, 0 },
  77.     {   0, 17,  0, 0 }, { 238,  0,  0, 0 }, { 221,  0,  0, 0 }, { 204,  0,  0, 0 },
  78.     { 187,  0,  0, 0 }, { 170,  0,  0, 0 }, { 153,  0,  0, 0 }, { 136,  0,  0, 0 },
  79.     { 119,  0,  0, 0 }, { 102,  0,  0, 0 }, {  85,  0,  0, 0 }, {  68,  0,  0, 0 },
  80.     {  51,  0,  0, 0 }, {  34,  0,  0, 0 }, { 240,251,255, 0 }, { 164,160,160, 0 },
  81.     { 128,128,128, 0 }, {   0,  0,255, 0 }, {   0,255,  0, 0 }, {   0,255,255, 0 },
  82.     { 255,  0,  0, 0 }, { 255,  0,255, 0 }, { 255,255,  0, 0 }, { 255,255,255, 0 }
  83. };
  84.  
  85.  
  86.  
  87. /////////////////////////////////////////////////////////////////////////////
  88. // CFireWnd
  89.  
  90. // Initialize the seed for random number generation.  For a more random
  91. // flame this could be initialized by a call to ::rand().  Declaring it
  92. // this way causes the same flame to be drawn each time the application
  93. // is executed.
  94. unsigned long CFireWnd::m_RandSeed = 0x38549391;
  95.  
  96. CFireWnd::CFireWnd(): m_curColor(0),rcSize(0,0), m_pBits(0)
  97. {
  98.     m_nDecay = 4;
  99.     m_nFlammability = 385;
  100.     m_nMaxHeat = 223;
  101.     m_nSpreadRate = 20;
  102.     m_nSmoothness = 1;
  103.     m_nDistribution = 1;
  104.     m_nChaos = 50;
  105.  
  106.     m_nSize = 0;
  107.     m_MaxBurn = 0;
  108.     m_Fire = NULL;
  109.  
  110.     m_hMemDC = NULL;
  111.     m_hWinDC = NULL;
  112.     m_hBitmap = NULL;
  113.     m_hPalette = NULL;
  114.     m_pOldPalette = NULL;
  115.     m_pOldBitmap = NULL;
  116.     CreatePopup();
  117. }
  118.  
  119. CFireWnd::~CFireWnd()
  120. {
  121.     if (m_hRightMenu != NULL)
  122.         DestroyMenu(m_hRightMenu);
  123.     m_hWnd = 0;
  124. }
  125.  
  126. LRESULT CFireWnd::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  127. {
  128.     m_uTimerID = SetTimer(0x451,33);
  129.     InitFire(m_curColor);
  130.     return 1;  // Let the system set the focus
  131. }
  132.  
  133.  
  134. LRESULT CFireWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  135. {
  136.     ATLTRACE(_T("CFireWnd::OnPaint\n"));
  137.     PAINTSTRUCT ps;
  138.     HDC dc = BeginPaint(&ps);
  139.  
  140.         // A different color brush can be used to fill the rect
  141.         // to test the drawing of the bitmap, but basically this
  142.         // code is not needed. It also helps reduce flicker a bit
  143.         // on slower machines though.
  144.         HBRUSH blackBrush, oldBrush = NULL;
  145.         blackBrush = CreateSolidBrush(RGB(0,0,0));
  146.         oldBrush = (HBRUSH)::SelectObject(dc,&blackBrush);
  147.         RECT rc;
  148.         GetClientRect(&rc);
  149.         ::FillRect(dc,const_cast<const RECT*>(&rc),blackBrush);
  150.         if(oldBrush)
  151.             ::SelectObject(dc,&oldBrush);
  152.  
  153.         // Do the real flame bitmap drawing
  154.         PaintFlame(dc);
  155.  
  156.     EndPaint(&ps);
  157.     return 0;
  158. }
  159.  
  160. /////////////////////////////////////////////////////////////////////////////
  161. // CFireWnd Operations
  162.  
  163. void CFireWnd::InitFire(int nColor)
  164. {
  165.     ATLTRACE(_T("CFireWnd::InitFire()\n"));
  166.     CreatePalette(nColor);
  167.  
  168.     CreateBitmap();
  169.  
  170.     {
  171.         HWND hActiveWnd = GetActiveWindow();
  172.         if (hActiveWnd != NULL)
  173.             ::SendMessage(hActiveWnd, WM_QUERYNEWPALETTE, 0, 0);
  174.     }
  175. }
  176.  
  177. HPALETTE* CFireWnd::GetPalette()
  178. {
  179.     ATLTRACE(_T("CFireWnd::GetPalette()\n"));
  180.     if (m_hPalette != NULL)
  181.         return &m_hPalette;
  182.     else
  183.         return NULL;
  184. }
  185.  
  186. void CFireWnd::CreatePalette(int nColor)
  187. {
  188.     ATLTRACE(_T("CFireWnd::CreatePalette()\n"));
  189.     UINT i;
  190.  
  191.     if (m_hPalette != NULL)
  192.     {
  193.         DeleteObject(m_hPalette);
  194.         m_hPalette = NULL;
  195.     }
  196.  
  197.     memcpy( m_rgbPalette, rgbStd256, sizeof(RGBQUAD) * 256 );
  198.  
  199.     int r,g,b;
  200.  
  201.     switch(nColor)
  202.     {
  203.     case blue:
  204.         b = 256+256+255;
  205.         g = 256+255;
  206.         r = 255;
  207.         break;
  208.     case green:
  209.         g = 256+256+255;
  210.         r = 256+255;
  211.         b = 255;
  212.         break;
  213.     case red:
  214.     default:
  215.         r = 256+256+255;
  216.         g = 256+255;
  217.         b = 255;
  218.         break;
  219.     }
  220.  
  221.     for(i = 239; i > 15; i--)
  222.     {
  223.         m_rgbPalette[i].rgbRed = (r > 255) ? 255 : r;
  224.         m_rgbPalette[i].rgbGreen = (g > 255) ? 255 : g;
  225.         m_rgbPalette[i].rgbBlue = (b > 255) ? 255 : b;
  226.         r = (r > 3) ? (r - 4) : 0;
  227.         g = (g > 3) ? (g - 4) : 0;
  228.         b = (b > 3) ? (b - 4) : 0;
  229.     }
  230.  
  231.     LPLOGPALETTE lpLogPal;
  232.     lpLogPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + ((255) * sizeof(PALETTEENTRY))];
  233.     lpLogPal->palVersion = 0x0300;
  234.     lpLogPal->palNumEntries = 256;
  235.  
  236.     for (i = 0; i < 256; i++)
  237.     {
  238.         lpLogPal->palPalEntry[i].peRed = m_rgbPalette[i].rgbRed;
  239.         lpLogPal->palPalEntry[i].peGreen = m_rgbPalette[i].rgbGreen;
  240.         lpLogPal->palPalEntry[i].peBlue = m_rgbPalette[i].rgbBlue;
  241.         lpLogPal->palPalEntry[i].peFlags = 0;
  242.     }
  243.  
  244.     m_hPalette = ::CreatePalette( lpLogPal );
  245.     _ASSERTE(m_hPalette);
  246.  
  247.     delete [] (BYTE *)lpLogPal;
  248. }
  249.  
  250.  
  251. #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
  252.  
  253. void CFireWnd::CreateBitmap()
  254. {
  255.     if(rcSize.cx == 0 || rcSize.cy == 0)
  256.     {
  257.         // no place to do a bitmap, then get out
  258.         return;
  259.     }
  260.  
  261.     ATLTRACE(_T("CFireWnd::CreateBitmap()\n"));
  262.     if (m_hMemDC != NULL)
  263.     {
  264.         ::SelectObject(m_hMemDC, m_hBitmap);
  265.         DeleteDC(m_hMemDC);
  266.         m_hMemDC = NULL;
  267.         m_pOldBitmap = NULL;
  268.     }
  269.  
  270.     if (m_hWinDC != NULL)
  271.     {
  272.         ::SelectObject(m_hWinDC,m_hPalette);
  273.         DeleteDC(m_hWinDC);
  274.         m_hWinDC = NULL;
  275.         m_pOldPalette = NULL;
  276.     }
  277.  
  278.     if (m_hBitmap != NULL)
  279.         DeleteObject(m_hBitmap);
  280.  
  281.     if (m_Fire != NULL)
  282.     {
  283.         delete m_Fire;
  284.         m_Fire = NULL;
  285.     }
  286.  
  287.     // rcSize is the cached size of the window that was
  288.     // set during the call to IOleInPlaceObject_SetObjectRects
  289.     _ASSERTE(rcSize.cx != 0);
  290.     _ASSERTE(rcSize.cy != 0);
  291.  
  292.  
  293.     // Just make the maximum height be the size of the rect
  294.     m_MaxBurn = (int)(rcSize.cy);
  295.  
  296.     if (m_nSize == 0)
  297.         m_nSize = (int)(rcSize.cx  * 0.66 );
  298.  
  299.     m_Fire = new BYTE[rcSize.cx];
  300.  
  301.     LPBITMAPINFO lpbi;
  302.  
  303.     // Fill in the BITMAPINFOHEADER
  304.     lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];
  305.     lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  306.     lpbi->bmiHeader.biWidth = rcSize.cx;
  307.     lpbi->bmiHeader.biHeight = rcSize.cy;
  308.     lpbi->bmiHeader.biPlanes = 1;
  309.     lpbi->bmiHeader.biBitCount = 8;
  310.     lpbi->bmiHeader.biCompression = BI_RGB;
  311.     lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)rcSize.cx * 8) * rcSize.cy;
  312.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  313.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  314.     lpbi->bmiHeader.biClrUsed = 0;
  315.     lpbi->bmiHeader.biClrImportant = 0;
  316.  
  317.     // Fill in the color table
  318.     UINT uUsage = DIB_RGB_COLORS;
  319.     memcpy( lpbi->bmiColors, m_rgbPalette, sizeof(RGBQUAD) * 256 );
  320.  
  321.     m_hWinDC = GetDC();
  322.     _ASSERTE(m_hWinDC);
  323.  
  324.     HBITMAP hBitmap = CreateDIBSection( m_hWinDC, lpbi, uUsage, (void **)&m_pBits, NULL, 0 );
  325.     _ASSERTE(hBitmap);
  326.  
  327.     delete [] (BYTE *)lpbi;
  328.  
  329.     m_hBitmap = hBitmap;
  330.  
  331.     m_hMemDC = CreateCompatibleDC(m_hWinDC);
  332.     _ASSERTE(m_hMemDC);
  333.  
  334.     m_pOldPalette = (HPALETTE)::SelectPalette( m_hWinDC, m_hPalette, FALSE );
  335.     RealizePalette(m_hWinDC);
  336.     m_pOldBitmap = (HBITMAP)::SelectObject(m_hMemDC, m_hBitmap );
  337.  
  338.     for (int x = 0; x < rcSize.cx; x++ )
  339.         m_Fire[x] = 16;
  340.  
  341.     // cache the bitmap size for later use so we don't
  342.     // have to call GetBitmapSize() for every timer message
  343.     bmSize.cx = rcSize.cx;
  344.     bmSize.cy = rcSize.cy;
  345. }
  346.  
  347.  
  348. //
  349. //  This routine was adapted from a pascal routine written by
  350. //  Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk)
  351. //
  352. //  See AboutBox for a special thank you for all his work.
  353. //
  354. // NOTE: There is a bug in the boundary conditions for the size
  355. //       of the bitmap. For example an object with a size of
  356. //       width 487 to 500 and a height of 300 doesn't work
  357. //       I have a hunch that the WIDTHBYTES macro doesn't account
  358. //       for all possible values for the upper bound.
  359. //       This bug doesn't show up in the MFC Fire sample because
  360. //       the size is hard wired to something that works. Since
  361. //       it has nothing to do with ATL controls, I just left the
  362. //       algorithm as is. MK
  363.  
  364. void CFireWnd::RenderFlame()
  365. {
  366.     int xStart, xEnd, x, y;
  367.     BYTE* pRow = NULL;
  368.     BYTE* pNextRow = NULL;
  369.  
  370.     if(bmSize.cx == 0 || bmSize.cy == 0 || m_pBits == NULL)
  371.     {
  372.         // if we don't have any dimensions or bits for
  373.         //  our bitmap then we aren't ready to paint
  374.         return;
  375.     }
  376.  
  377.     // width of the bitmap
  378.     if(m_nSize > bmSize.cx)
  379.     {
  380.         m_nSize = bmSize.cx - 1;
  381.     }
  382.  
  383.     // height of the bitmap
  384.     if( m_MaxBurn > rcSize.cy )
  385.     {
  386.         m_MaxBurn = rcSize.cy - 1;
  387.     }
  388.  
  389.     xStart = (bmSize.cx - m_nSize) / 2;
  390.     xEnd = xStart + m_nSize + 1;
  391.  
  392.     {
  393.         pRow = m_pBits;
  394.         for (x=0;x<bmSize.cx;x++)
  395.         {
  396.             if (x < (xStart + m_nDistribution) || x >= (xEnd - m_nDistribution))
  397.                 m_Fire[x] = 16;
  398.             *pRow++ = m_Fire[x];
  399.         }
  400.     }
  401.  
  402.  
  403.     for (y = m_MaxBurn; y > 0; y--)
  404.     {
  405.         pRow = (m_pBits + WIDTHBYTES((DWORD)bmSize.cx * 8) * y);
  406.         pNextRow = (m_pBits + WIDTHBYTES((DWORD)bmSize.cx * 8) * (y - 1));
  407.  
  408.         if ((rand() % 2) == 0)
  409.         {
  410.             for (x = 0; x < bmSize.cx; x++)
  411.             {
  412.                 BurnPoint(pRow, pNextRow);
  413.                 pRow++;
  414.                 pNextRow++;
  415.             }
  416.         }
  417.         else
  418.         {
  419.             pRow += bmSize.cx - 1;
  420.             pNextRow += bmSize.cx - 1;
  421.             for (x = 0; x < bmSize.cx; x++)
  422.             {
  423.                 BurnPoint(pRow, pNextRow);
  424.                 pRow--;
  425.                 pNextRow--;
  426.             }
  427.         }
  428.     }
  429.  
  430.     int MaxHeat = m_nMaxHeat + 16;
  431.  
  432.     if ( rand() % (400 - m_nFlammability) == 0)
  433.     {
  434.         int off = m_nSize - 5;
  435.         off = rand() % off;
  436.         off += xStart;
  437.  
  438.         for (x = off; x < off + 5; x++)
  439.             m_Fire[x] = 239;
  440.     }
  441.  
  442.     for (x = xStart; x < xEnd; x++)
  443.     {
  444.         if (m_Fire[x] < MaxHeat)
  445.         {
  446.             int val = rand() % m_nChaos+1;
  447.             val -= m_nChaos / 2;
  448.             val += m_nSpreadRate;
  449.             val += m_Fire[x];
  450.  
  451.             if ( val > MaxHeat)
  452.                 m_Fire[x] = static_cast<BYTE>(MaxHeat);
  453.             else if ( val < 16)
  454.                 m_Fire[x] = 16;
  455.             else
  456.                 m_Fire[x] = static_cast<BYTE>(val);
  457.         }
  458.         else
  459.             m_Fire[x] = static_cast<BYTE>(MaxHeat);
  460.     }
  461.  
  462.     if (m_nSmoothness > 0)
  463.     {
  464.         xStart += m_nSmoothness;
  465.         xEnd -= m_nSmoothness;
  466.         for (x = xStart; x < xEnd; x++)
  467.         {
  468.             int val = 0;
  469.             for (y = x - m_nSmoothness; y < x + 1 + m_nSmoothness; y++)
  470.                 val += m_Fire[y];
  471.  
  472.             m_Fire[x] = val / (2*m_nSmoothness+1);
  473.         }
  474.     }
  475. }
  476.  
  477. void CFireWnd::PaintFlame(HDC hDC)
  478. {
  479.     if (m_hPalette != NULL  && m_hBitmap != NULL)
  480.     {
  481.         if (hDC != NULL)
  482.         {
  483.             HPALETTE pOldPalette;
  484.             pOldPalette = ::SelectPalette(hDC, m_hPalette, FALSE );
  485.             RealizePalette(hDC);
  486.             _ASSERTE(m_hMemDC);
  487.             HBITMAP pOldBitmap = (HBITMAP)::SelectObject(m_hMemDC, m_hBitmap);
  488.             BitBlt(hDC, 0, 0, bmSize.cx, bmSize.cy, m_hMemDC, 0, 0, SRCCOPY );
  489.             ::SelectObject(m_hMemDC, pOldBitmap);
  490.             SelectPalette( hDC, pOldPalette, TRUE );
  491.         }
  492.         else
  493.         {
  494.             ::BitBlt(m_hWinDC, 0, 0, bmSize.cx, bmSize.cy, m_hMemDC, 0, 0, SRCCOPY );
  495.         }
  496.     }
  497. }
  498.  
  499. /////////////////////////////////////////////////////////////////////////////
  500. // CFireWnd message handlers
  501.  
  502. LRESULT CFireWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  503. {
  504.  
  505.     if (m_hMemDC != NULL)
  506.     {
  507.         ::SelectObject(m_hMemDC, m_hBitmap);
  508.         DeleteDC(m_hMemDC);
  509.         m_hMemDC = NULL;
  510.         m_pOldBitmap = NULL;
  511.     }
  512.  
  513.     if (m_hWinDC != NULL)
  514.     {
  515.         ::SelectObject(m_hWinDC,m_hPalette);
  516.         DeleteDC(m_hWinDC);
  517.         m_hWinDC = NULL;
  518.         m_pOldPalette = NULL;
  519.     }
  520.  
  521.     if (m_hBitmap != NULL)
  522.         DeleteObject(m_hBitmap);
  523.  
  524.     if (m_hPalette != NULL)
  525.         DeleteObject(m_hBitmap);
  526.  
  527.     if (m_Fire != NULL)
  528.     {
  529.         delete m_Fire;
  530.         m_Fire = NULL;
  531.     }
  532.  
  533.     KillTimer(m_uTimerID);
  534.  
  535.     return 0;
  536. }
  537.  
  538. LRESULT CFireWnd::OnPaletteChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  539. {
  540.     ATLTRACE(_T("CFireWnd::OnPaletteChanged()\n"));
  541.     HWND pFocusWnd = GetFocus();
  542.     if (pFocusWnd == m_hWnd || IsChild(pFocusWnd))
  543.         return 0;
  544.     return OnQueryNewPalette(uMsg, wParam, lParam, bHandled);
  545. }
  546.  
  547. LRESULT CFireWnd::OnQueryNewPalette(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  548. {
  549.  
  550.     ATLTRACE(_T("CFireWnd::OnQueryNewPalette()\n"));
  551.     if (GetPalette() == NULL)
  552.         return FALSE;
  553.  
  554.     {
  555.         HDC dc = GetDC();
  556.         SelectPalette(dc, m_hPalette, uMsg == WM_PALETTECHANGED);
  557.         UINT nChanged = RealizePalette(dc);
  558.         if (nChanged == 0)  // no change to our mapping
  559.             return FALSE;
  560.         ReleaseDC(dc);
  561.     }
  562.  
  563.     // some changes have been made; invalidate
  564.     Invalidate(FALSE);
  565.     return 0;
  566. }
  567.  
  568. LRESULT CFireWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  569. {
  570.     ATLTRACE(_T("CFireWnd::OnSize()\n"));
  571.     rcSize.cx = LOWORD(lParam);
  572.     rcSize.cy = HIWORD(lParam);
  573.  
  574.     ::SetWindowPos(m_hWnd, NULL, 0,
  575.         0, rcSize.cx, rcSize.cy, SWP_NOZORDER | SWP_NOACTIVATE);
  576.  
  577.     return 0;
  578. }
  579.  
  580. LRESULT CFireWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  581. {
  582.     RenderFlame();
  583.     PaintFlame();
  584.     // Eat spurious WM_TIMER messages
  585.     MSG msg;
  586.     while(::PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));
  587.     return 0;
  588. }
  589.  
  590.  
  591. LRESULT CFireWnd::OnProperties(WORD wNotifyCode, WORD wID, HWND hWndCtlr, BOOL& bHandled)
  592. {
  593.     CPropDlg dlg(this);
  594.     dlg.DoModal(m_hWnd);
  595.     return 0;
  596. }
  597.  
  598. LRESULT CFireWnd::OnRButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  599. {
  600.     ATLTRACE(_T("CFireWnd::OnRButtonDown()\n"));
  601.     POINT ptClick;
  602.     ptClick.x = LOWORD(lParam);
  603.     ptClick.y = HIWORD(lParam);
  604.     ::ClientToScreen(m_hWnd, &ptClick);
  605.     TrackPopupMenuEx(m_hRightMenu, TPM_VERTICAL, ptClick.x, ptClick.y, m_hWnd, NULL);
  606.     return 0;
  607. }
  608.  
  609. void CFireWnd::CreatePopup()
  610. {
  611.     m_hRightMenu = NULL;
  612.     m_hPropMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MENU1));
  613.     if (m_hPropMenu == NULL)
  614.     {
  615.         ATLTRACE(_T("Failed to load right click menu\n"));
  616.         _ASSERTE(FALSE);
  617.         return;
  618.     }
  619.  
  620.     m_hRightMenu = GetSubMenu(m_hPropMenu, 0);
  621.     if (m_hRightMenu == NULL)
  622.     {
  623.         ATLTRACE(_T("Failed to load Popup menu\n"));
  624.         _ASSERTE(FALSE);
  625.         return;
  626.     }
  627. }
  628.