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

  1. // AtlTangramCanvasImpl.cpp : Implementation of CAtlTangramCanvas
  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 "ATLTangramCanvas.h"
  15. #include "AtlTangramCanvasImpl.h"
  16.  
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CAtlTangramCanvas
  19. //
  20.  
  21. ///////////////////////////////////////////////////////////
  22. //
  23. // Initialize
  24. //  
  25. HRESULT CAtlTangramCanvas::Initialize(HWND hWnd, long cx, long cy)
  26. {
  27.     // Hard coded to 8 bits per pixel.
  28.     int ibitcount = 8 ; 
  29.  
  30.     // Preconditions.
  31.     if ( hWnd == NULL || !::IsWindow(hWnd) || cx <= 0 || cy <= 0)
  32.     {
  33.         // Definsive code.
  34.         ASSERT(hWnd != NULL) ;
  35.         ASSERT(::IsWindow(hWnd)) ;
  36.         ASSERT(cx > 0);
  37.         ASSERT(cy > 0);
  38.  
  39.         return E_INVALIDARG ;
  40.     }
  41.  
  42.     // Cache a copy of the window handle.
  43.     m_hWnd = hWnd ; 
  44.  
  45.     // Destroy parts of objects if we are recreating it.
  46.     if ((m_hdc != NULL) || (m_hbmp != NULL))
  47.     {    
  48. //        destroy() ;
  49.     }
  50.  
  51.     // Save size for drawing later.
  52.     m_sizeDIB.cx = cx ;
  53.     m_sizeDIB.cy = cy ;
  54.  
  55.     // Create a BITMAPINFOHEADER structure to describe the DIB
  56.     BITMAPINFOHEADER BIH ;
  57.     int iSize = sizeof(BITMAPINFOHEADER) ;
  58.     memset(&BIH, 0, iSize);
  59.  
  60.     // Fill in the header info.
  61.     BIH.biSize = iSize;
  62.     BIH.biWidth = cx;
  63.     BIH.biHeight = cy;
  64.     BIH.biPlanes = 1;
  65.     BIH.biBitCount = ibitcount;
  66.     BIH.biCompression = BI_RGB;
  67.  
  68.     // Create a new DC.
  69.     m_hdc = ::CreateCompatibleDC(NULL) ;
  70.  
  71.  
  72.     // Create the DIB section.
  73.     m_hbmp = CreateDIBSection(    m_hdc,
  74.                                 (BITMAPINFO*)&BIH,
  75.                                 DIB_PAL_COLORS,
  76.                                 &m_pBits,
  77.                                 NULL,
  78.                                 0);
  79.  
  80.     ASSERT(m_hbmp);
  81.     ASSERT(m_pBits);
  82.  
  83.     // Select the new bitmap into the buffer DC
  84.     if (m_hbmp)
  85.     {
  86.         m_hbmOld = (HBITMAP)::SelectObject(    m_hdc, 
  87.                                             m_hbmp);
  88.     }
  89.  
  90.     return S_OK ;
  91. }
  92.  
  93. ///////////////////////////////////////////////////////////
  94. //
  95. //    Transfer the dib section to a DC. 
  96. //    Called in response to paint and draw messages.
  97. //
  98. HRESULT CAtlTangramCanvas::Paint(HDC hdcDest, RECT rectUpdate)
  99. {
  100.     // Preconditions
  101.     if ( hdcDest == NULL)
  102.     {
  103.         ASSERT(hdcDest != NULL) ;
  104.         return E_INVALIDARG ;
  105.     }
  106.  
  107.     // Select in a palette if we have one.
  108.     HPALETTE hPalOld = NULL;
  109.     if (m_hPal)
  110.     {
  111.         hPalOld = ::SelectPalette(hdcDest, (HPALETTE)m_hPal, 0);
  112.         ::RealizePalette(hdcDest);
  113.     }
  114.  
  115.     // If the rectangle is empty or null, repaint the entire area.
  116.     RECT rect, rectNull ;
  117.     ::SetRectEmpty(&rectNull) ;
  118.     ::CopyRect(&rect, &rectUpdate) ;
  119.     if (::EqualRect(&rect, &rectNull) || ::IsRectEmpty(&rect))
  120.     {
  121.         // Note: you do not need to select the palette into
  122.         // the memory DC because the DIB section is using palette
  123.         // index values not colors
  124.         ::BitBlt(hdcDest, 0, 0,
  125.                     m_sizeDIB.cx, m_sizeDIB.cy,
  126.                     m_hdc, 
  127.                     0,0,
  128.                     SRCCOPY);
  129.     }
  130.     else
  131.     {
  132.         // Just repaint the updated area.
  133.         ::BitBlt(hdcDest,
  134.                 rect.left, rect.top,
  135.                 rect.right - rect.left, rect.bottom - rect.top,
  136.                 m_hdc, 
  137.                 rect.left, rect.top,
  138.                 SRCCOPY);
  139.         }
  140.  
  141.     // We are done with the palette
  142.     if (hPalOld) 
  143.     {
  144.         ::SelectPalette(hdcDest, hPalOld, 0);        
  145.     }
  146.  
  147.     return S_OK ;
  148. }
  149.  
  150. ///////////////////////////////////////////////////////////
  151. //
  152. //    Update
  153. //
  154. HRESULT CAtlTangramCanvas::Update(RECT rectUpdate)
  155. {
  156.  
  157.     HDC hdcDest = ::GetDC(m_hWnd) ;
  158.     Paint(hdcDest, rectUpdate) ;
  159.     ::ReleaseDC(m_hWnd, hdcDest);
  160.  
  161.     return S_OK ;
  162. }
  163.  
  164.  
  165.  
  166. ///////////////////////////////////////////////////////////
  167. //
  168. //    GetHDC
  169. //
  170. HRESULT CAtlTangramCanvas::GetHDC(HDC* phdc)
  171. {
  172.     // Pre conditions.
  173.     if (!IsValidAddress(phdc, sizeof(HDC), TRUE))
  174.     {
  175.         ASSERT(0) ;
  176.         return E_FAIL ;
  177.     }
  178.  
  179.     // Return device context.
  180.     *phdc = m_hdc ;
  181.     return S_OK ;
  182. }
  183.  
  184.  
  185. ///////////////////////////////////////////////////////////
  186. //
  187. // Set the color table in the DIB section.
  188. //
  189. HRESULT __stdcall CAtlTangramCanvas::SetPalette(HPALETTE hPal) 
  190. {
  191.     if (hPal == NULL)
  192.     {
  193.         ASSERT(hPal != NULL);
  194.         return E_INVALIDARG ;
  195.     }
  196.  
  197.     // Keep a copy of the palette around for painting.
  198.     m_hPal = hPal ;
  199.  
  200.     // get the colors from the palette
  201.     int iColors = 0;
  202.     ::GetObject(hPal, sizeof(iColors), &iColors) ;
  203.  
  204.     ASSERT(iColors > 0);
  205.     PALETTEENTRY* pPE = new PALETTEENTRY[iColors];
  206.     ::GetPaletteEntries(hPal, 0, iColors, pPE);
  207.  
  208.     // Build a table of RGBQUADS
  209.     RGBQUAD* pRGB = new RGBQUAD[iColors];
  210.     ASSERT(pRGB);
  211.     for (int i = 0; i < iColors; i++) {
  212.         pRGB[i].rgbRed = pPE[i].peRed;
  213.         pRGB[i].rgbGreen = pPE[i].peGreen;
  214.         pRGB[i].rgbBlue = pPE[i].peBlue;
  215.         pRGB[i].rgbReserved = 0;
  216.     }
  217.     
  218.     ::SetDIBColorTable(m_hdc, 
  219.                        0, iColors,
  220.                        pRGB);
  221.  
  222.     delete [] pRGB;
  223.     delete [] pPE;
  224.  
  225.     return S_OK ;
  226. }
  227.  
  228. ///////////////////////////////////////////////////////////
  229. //
  230. //    Called when the main window gets a QueryNewPalette or a
  231. //    PaletteChanged message.
  232. //
  233. HRESULT __stdcall CAtlTangramCanvas::OnQueryNewPalette(HWND hWndReceived)
  234. {
  235.     if (hWndReceived == NULL)
  236.     {
  237.         return E_FAIL ;
  238.     }
  239.  
  240.     if (m_hPal)
  241.     {
  242.         HDC hdc = ::GetDC(hWndReceived) ;
  243.         ::SelectPalette(hdc, m_hPal, FALSE) ;
  244.         UINT u = ::RealizePalette(hdc) ;
  245.         ::ReleaseDC(hWndReceived, hdc) ;
  246.         if (u != 0)
  247.         {
  248.             ::InvalidateRect(hWndReceived, NULL, TRUE) ;
  249.         }
  250.     }
  251.     return S_OK ;
  252. }