home *** CD-ROM | disk | FTP | other *** search
/ Mastering Visual Basic 6 / mastvb6.iso / numega / sc501.exe / data1.cab / Examples / CSTATBMP.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-25  |  18.6 KB  |  583 lines

  1. /*
  2.  * CStatBmp.cpp
  3.  * $Header: /bcsample/BUGBNCHX/CSTATBMP.CPP 1     5/28/96 1:11p Dave $
  4.  *
  5.  * Description:
  6.  *  The routines that implement a Bitmap display control.  Just
  7.  * subclass an existing static control and a bitmap will be displayed.
  8.  * The name assigned to the control is the bitmap that will be loaded.
  9.  *
  10.  * Notes:
  11.  *  <implementation notes go here>
  12.  *
  13.  ***********************************************************************
  14.  *
  15.  * Nu-Mega Technologies, Inc.
  16.  * P.O. Box 7780
  17.  * Nashua, NH 03060
  18.  *
  19.  * (c) Copyright 1994, 1995 Nu-Mega Technologies, Inc.
  20.  * ALL RIGHTS RESERVED.
  21.  *
  22.  ***********************************************************************
  23.  *
  24.  **********************************************************************/
  25. #include "stdafx.h"
  26. #include "BugBench.h"
  27. #include "CStatBmp.h"
  28.  
  29.  
  30. /*----------------------------------------------------------------------
  31.    The declarations and constants for the DIB drawing functions.  The
  32. functions themselves come from the treasure trove of VC++ samples.
  33. ----------------------------------------------------------------------*/
  34.  
  35. // DIB constants
  36. #define PALVERSION   0x300
  37.  
  38. // DIB Macros
  39.  
  40. #define IS_WIN30_DIB(lpbi) ( ( * ( LPDWORD )( lpbi ) ) == \
  41.                               sizeof ( BITMAPINFOHEADER ) )
  42.  
  43. // WIDTHBYTES performs DWORD-aligning of DIB scanlines.  The "bits"
  44. // parameter is the bit count for the scanline (biWidth * biBitCount),
  45. // and this macro returns the number of DWORD-aligned bytes needed
  46. // to hold those bits.
  47.  
  48. #define WIDTHBYTES(bits)    ( ( ( bits ) + 31 ) / 32 * 4 )
  49.  
  50. // Function declarations.
  51. BOOL  WINAPI  PaintDIB ( HDC        hDC       ,
  52.                          LPRECT     lpDCRect  ,
  53.                          LPSTR      lpDIBHdr  ,
  54.                          LPRECT     lpDIBRect ,
  55.                          HPALETTE   hpalIn     ) ;
  56. BOOL  WINAPI  CreateDIBPalette ( LPSTR lpbi , HPALETTE* hPal ) ;
  57. DWORD WINAPI  DIBWidth  ( LPSTR lpDIB ) ;
  58. DWORD WINAPI  DIBHeight ( LPSTR lpDIB ) ;
  59. WORD  WINAPI  PaletteSize  ( LPSTR lpbi ) ;
  60. WORD  WINAPI  DIBNumColors ( LPSTR lpbi ) ;
  61.  
  62. #ifdef STRICT
  63.   WNDPROC m_lpPrevWndProc ;
  64. #else
  65.   FARPROC m_lpPrevWndProc ;
  66. #endif
  67.  
  68.  
  69. BOOL StaticBitmap_OnQueryNewPalette ( HWND hWnd ) ;
  70. void StaticBitmap_OnPaint ( HWND hWnd ) ; 
  71.  
  72. HRSRC m_hRSC = NULL ;
  73. LPTSTR m_szLockedRSC ;
  74.  
  75. RECT m_rectDIB ;
  76. RECT m_rectHDC ;
  77.  
  78. HPALETTE m_palette ; 
  79.  
  80. void StaticBitmap_CleanUp ( HWND hStatic ) 
  81. {
  82.    ASSERT ( IsWindow ( hStatic ) ) ;
  83.  
  84.    // Unlock the resource and free the palette.
  85.    if ( NULL != m_hRSC )
  86.    {
  87.       // This isn't necessary anymore under
  88.       // 32-bit development.
  89.       UnlockResource ( m_hRSC ) ;
  90.       FreeResource ( m_hRSC ) ;
  91.    }
  92.  
  93.    if ( NULL != m_palette )
  94.       DeleteObject ( m_palette ) ;
  95. }
  96.  
  97. ////////////////////////////////////////////////////////////////////////
  98. // The message pump for the StaticBitmap control.
  99. ////////////////////////////////////////////////////////////////////////
  100. LRESULT CALLBACK StaticBitmap_WndProc ( HWND    hStatic   ,
  101.                                         UINT    uMsg   ,
  102.                                         WPARAM  wParam ,
  103.                                         LPARAM  lParam  )
  104. {
  105.    switch ( uMsg )
  106.    {
  107.      HANDLE_MSG ( hStatic , WM_PAINT           , StaticBitmap_OnPaint           ) ;
  108.      HANDLE_MSG ( hStatic , WM_QUERYNEWPALETTE , StaticBitmap_OnQueryNewPalette ) ;
  109.  
  110.       default  :
  111.          return ( CallWindowProc( m_lpPrevWndProc , hStatic , uMsg , wParam , lParam ) ) ;
  112.          break ;
  113.    }
  114.    
  115.    return ( LRESULT ) 0 ;
  116. }
  117.  
  118. ////////////////////////////////////////////////////////////////////////
  119. // The message handlers for the StaticBitmap.
  120. ////////////////////////////////////////////////////////////////////////
  121. BOOL StaticBitmap_Init ( HWND hwndStatic )
  122. {
  123.    TCHAR szBuff[ MAX_PATH ] ;
  124.  
  125.    // Get the name of the window, because this will be the name of
  126.    //  the bitmap we will load.
  127.    GetWindowText ( hwndStatic , szBuff , sizeof ( szBuff ) ) ;
  128.  
  129.    ASSERT ( _T ( '\0' ) != szBuff[ 0 ] ) ;
  130.    if ( _T ( '\0' ) == szBuff[ 0 ] )
  131.       return ( FALSE ) ;
  132.  
  133.    // Load the resource.
  134.    HRSRC hRSRC = ::FindResource (  GetModuleHandle ( NULL ) ,
  135.                                    szBuff                   ,
  136.                                    RT_BITMAP                 ) ;
  137.  
  138.    m_hRSC = (HRSRC)::LoadResource ( 0 , hRSRC ) ;
  139.    ASSERT ( NULL != m_hRSC ) ;
  140.    if ( NULL == m_hRSC )
  141.       return ( FALSE ) ;
  142.  
  143.    m_szLockedRSC = (LPSTR)::LockResource ( m_hRSC ) ;
  144.  
  145.    // Get the rect of the bitmap and store it so that we don't have
  146.    //  to calculate it each time.
  147.    BITMAP m_bmInfo ;
  148.    memcpy ( &m_bmInfo, m_szLockedRSC , sizeof ( BITMAP ) ) ;
  149.  
  150.    m_rectDIB.top    = 0 ;
  151.    m_rectDIB.left   = 0 ;
  152.    m_rectDIB.right  = m_bmInfo.bmWidth  ;
  153.    m_rectDIB.bottom = m_bmInfo.bmHeight ;
  154.  
  155.  
  156.    // Get the client rect and calculate the center area.
  157.    GetClientRect ( hwndStatic , &m_rectHDC ) ;
  158.  
  159.    LONG lHeightDiff = 0 ;
  160.    LONG lWidthDiff  = 0 ;
  161.    if ( RECTWIDTH ( &m_rectDIB )  < RECTWIDTH ( &m_rectHDC ) )
  162.       lWidthDiff = ( RECTWIDTH ( &m_rectHDC ) - RECTWIDTH ( &m_rectDIB ) ) / 2 ;
  163.    if ( RECTHEIGHT ( &m_rectDIB ) < RECTHEIGHT ( &m_rectHDC ) )
  164.       lHeightDiff = ( RECTHEIGHT ( &m_rectHDC ) - RECTHEIGHT ( &m_rectDIB ) ) / 2 ;
  165.  
  166.    // Decrease the rect of the HDC we will paint on accordingly.
  167.    m_rectHDC.top    += lHeightDiff ;
  168.    m_rectHDC.bottom -= lHeightDiff ;
  169.    m_rectHDC.left   += lWidthDiff  ;
  170.    m_rectHDC.right  -= lWidthDiff  ;
  171.  
  172.    // Create the pallette.
  173.    ::CreateDIBPalette ( m_szLockedRSC , &m_palette ) ;
  174.  
  175. #ifdef STRICT
  176.    m_lpPrevWndProc = ( WNDPROC ) SetWindowLong ( hwndStatic , GWL_WNDPROC, ( LONG ) StaticBitmap_WndProc ) ;
  177. #else
  178.    m_lpPrevWndProc = ( FARPROC ) SetWindowLong ( hwndStatic , GWL_WNDPROC, ( LONG ) StaticBitmap_WndProc ) ;
  179. #endif 
  180.  
  181.    return ( TRUE ) ;
  182. }
  183.  
  184.  
  185.  
  186. UINT StaticBitmap_RealizeDIBPalette ( HWND hStatic )
  187. {
  188.    // Get the device context for this window.
  189.    HDC hDC = GetDC ( hStatic ) ;
  190.    ASSERT ( NULL != hDC ) ;
  191.    if ( NULL == hDC )
  192.       return ( 0 ) ;
  193.  
  194.    // Make the DIB palette current as the foreground palette.
  195.    HPALETTE hOldPal = ::SelectPalette ( hDC , m_palette , FALSE ) ;
  196.    // Realize it.
  197.    UINT uiRet = RealizePalette ( hDC ) ;
  198.    // Make the old palette the background palette.
  199.    ::SelectPalette ( hDC , hOldPal , TRUE ) ;
  200.  
  201.    // Get rid of the device context.
  202.    ::ReleaseDC ( hStatic , hDC ) ;
  203.  
  204.    // If the realization changed, then we need to repaint the DIB.
  205.    if ( uiRet > 0 )
  206.    {
  207.       InvalidateRect ( hStatic , NULL , TRUE ) ;
  208.    }
  209.    return ( uiRet ) ;
  210. }
  211.  
  212. BOOL StaticBitmap_OnQueryNewPalette ( HWND hWnd ) 
  213. {   
  214.    return ( 0 != StaticBitmap_RealizeDIBPalette ( hWnd ) ) ;
  215. }
  216.  
  217. void StaticBitmap_OnPaint ( HWND hWnd )
  218. {
  219.    HDC hDC = NULL ;
  220.    PAINTSTRUCT ps ;
  221.  
  222.    hDC = ::BeginPaint ( hWnd , &ps ) ;
  223.    ASSERT ( NULL != hDC ) ;
  224.    ASSERT ( NULL != m_hRSC ) ;
  225.  
  226.    ::PaintDIB ( hDC           ,
  227.                 &m_rectHDC     ,
  228.                 m_szLockedRSC ,
  229.                 &m_rectDIB     ,
  230.                 m_palette     ) ;
  231.  
  232.    ::EndPaint ( hWnd , &ps ) ;
  233. }
  234.  
  235.  
  236. /***********************************************************************
  237.  *
  238.  * PaintDIB()
  239.  *
  240.  * Return Value:
  241.  *
  242.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  243.  *
  244.  * Description:
  245.  *   Painting routine for a DIB.  Calls StretchDIBits() or
  246.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  247.  *   output to the specified DC, at the coordinates given
  248.  *   in lpDCRect.  The area of the DIB to be output is
  249.  *   given by lpDIBRect.
  250.  *
  251.  **********************************************************************/
  252. BOOL WINAPI PaintDIB ( HDC        hDC        ,
  253.                        LPRECT     lpDCRect   ,
  254.                        LPSTR      lpDIBHdr   ,
  255.                        LPRECT     lpDIBRect  ,
  256.                        HPALETTE   hpalIn      )
  257. {
  258.    LPSTR    lpDIBBits         ;     // Pointer to DIB bits
  259.    BOOL     bSuccess = FALSE  ;     // Success/fail flag
  260.    HPALETTE hPal     = NULL   ;     // Our DIB's palette
  261.    HPALETTE hOldPal  = NULL   ;     // Previous palette
  262.  
  263.    // Get a pointer to the beginning of the bit buffer.
  264.  
  265.    lpDIBBits = ( lpDIBHdr + *(LPDWORD)lpDIBHdr +
  266.                 ::PaletteSize ( lpDIBHdr ) ) ;
  267.  
  268.    // Get the DIB's palette, then select it into DC
  269.    if ( NULL != hpalIn )
  270.    {
  271.       hPal = (HPALETTE) hpalIn ;
  272.  
  273.     // Select as background since we have
  274.     // already realized in foreground if needed
  275.     hOldPal = ::SelectPalette ( hDC , hPal , FALSE ) ;
  276.     ::RealizePalette ( hDC ) ;
  277.    }
  278.  
  279.    // Make sure to use the stretching mode best for color pictures.
  280.    ::SetStretchBltMode ( hDC , COLORONCOLOR ) ;
  281.  
  282.    // Determine whether to call StretchDIBits() or SetDIBitsToDevice().
  283.    if ( ( RECTWIDTH ( lpDCRect )  == RECTWIDTH ( lpDIBRect ) ) &&
  284.         ( RECTHEIGHT ( lpDCRect ) == RECTHEIGHT ( lpDIBRect ) )  )
  285.    {
  286.  
  287.       bSuccess =
  288.          ::SetDIBitsToDevice ( hDC                    , // hDC
  289.                                lpDCRect->left         , // DestX
  290.                                lpDCRect->top          , // DestY
  291.                                RECTWIDTH ( lpDCRect ) , // nDestWidth
  292.                                RECTHEIGHT( lpDCRect ) , // nDestHeight
  293.                                lpDIBRect->left        , // SrcX
  294.                                // SrcY
  295.                                (int)DIBHeight(lpDIBHdr) -
  296.                                  lpDIBRect->top - RECTHEIGHT(lpDIBRect),
  297.                                0                      , // nStartScan
  298.                                (WORD)DIBHeight ( lpDIBHdr ),// nNumScans
  299.                                lpDIBBits              , // lpBits
  300.                                (LPBITMAPINFO)lpDIBHdr , // lpBitsInfo
  301.                                DIB_RGB_COLORS       ) ; // wUsage
  302.    }
  303.    else
  304.    {
  305.       bSuccess =
  306.          ::StretchDIBits ( hDC                     , // hDC
  307.                            lpDCRect->left          , // DestX
  308.                            lpDCRect->top           , // DestY
  309.                            RECTWIDTH ( lpDCRect )  , // nDestWidth
  310.                            RECTHEIGHT ( lpDCRect ) , // nDestHeight
  311.                            lpDIBRect->left         , // SrcX
  312.                            lpDIBRect->top          , // SrcY
  313.                            RECTWIDTH ( lpDIBRect ) , // wSrcWidth
  314.                            RECTHEIGHT ( lpDIBRect ), // wSrcHeight
  315.                            lpDIBBits               , // lpBits
  316.                            (LPBITMAPINFO)lpDIBHdr  , // lpBitsInfo
  317.                            DIB_RGB_COLORS          , // wUsage
  318.                            SRCCOPY               ) ; // dwROP
  319.    }
  320.  
  321.    // Reselect old palette.
  322.    if ( NULL != hOldPal )
  323.    {
  324.       ::SelectPalette ( hDC , hOldPal , TRUE ) ;
  325.    }
  326.    return ( bSuccess ) ;
  327. }
  328.  
  329. /***********************************************************************
  330.  *
  331.  * CreateDIBPalette()
  332.  *
  333.  * This function creates a palette from a DIB by allocating memory for
  334.  * the logical palette, reading and storing the colors from the DIB's
  335.  * color table into the logical palette, creating a palette from this
  336.  * logical palette, and then returning the palette's handle. This allows
  337.  * the DIB to be displayed using the best possible colors (important for
  338.  * DIBs with 256 or more colors).
  339.  *
  340.  **********************************************************************/
  341. BOOL WINAPI CreateDIBPalette ( LPSTR lpbi , HPALETTE* hPal )
  342. {
  343.    // Pointer to a logical palette
  344.    LPLOGPALETTE      lpPal          ;
  345.    // Loop index
  346.    int               i              ;
  347.    // Number of colors in color table
  348.    WORD              wNumColors     ;
  349.    // Pointer to BITMAPINFO structure (Win3.0)
  350.    LPBITMAPINFO      lpbmi          ;
  351.    // Pointer to BITMAPCOREINFO structure (old)
  352.    LPBITMAPCOREINFO  lpbmc          ;
  353.    // Flag which signifies whether this is a Win3.0 DIB
  354.    BOOL              bWinStyleDIB   ;
  355.    BOOL              bResult = FALSE;
  356.  
  357.    // Get pointer to BITMAPINFO (Win 3.0)
  358.    lpbmi = (LPBITMAPINFO)lpbi ;
  359.  
  360.    // Get pointer to BITMAPCOREINFO (old 1.x)
  361.    lpbmc = (LPBITMAPCOREINFO)lpbi ;
  362.  
  363.    // Get the number of colors in the DIB
  364.    wNumColors = ::DIBNumColors ( lpbi ) ;
  365.  
  366.    if ( 0 != wNumColors )
  367.    {
  368.       // Allocate memory block for logical palette.
  369.       lpPal =
  370.          (LPLOGPALETTE) new char [ sizeof ( LOGPALETTE ) +
  371.                                ( sizeof(PALETTEENTRY) * wNumColors ) ] ;
  372.  
  373.       // If not enough memory, clean up and return NULL.
  374.       if ( 0 == lpPal )
  375.       {
  376.          return ( FALSE ) ;
  377.       }
  378.  
  379.       // Set version and number of palette entries.
  380.       lpPal->palVersion = PALVERSION ;
  381.       lpPal->palNumEntries = (WORD)wNumColors ;
  382.  
  383.       // Is this a Win 3.0 DIB?
  384.       bWinStyleDIB = IS_WIN30_DIB( lpbi ) ;
  385.       for ( i = 0 ; i < (int)wNumColors ; i++ )
  386.       {
  387.          if ( bWinStyleDIB )
  388.          {
  389.             lpPal->palPalEntry[ i ].peRed   =
  390.                                           lpbmi->bmiColors[ i ].rgbRed ;
  391.             lpPal->palPalEntry[ i ].peGreen =
  392.                                         lpbmi->bmiColors[ i ].rgbGreen ;
  393.             lpPal->palPalEntry[ i ].peBlue  =
  394.                                          lpbmi->bmiColors[ i ].rgbBlue ;
  395.             lpPal->palPalEntry[ i ].peFlags = 0 ;
  396.          }
  397.          else
  398.          {
  399.             lpPal->palPalEntry[ i ].peRed    =
  400.                                         lpbmc->bmciColors[ i ].rgbtRed ;
  401.             lpPal->palPalEntry[ i ].peGreen  =
  402.                                       lpbmc->bmciColors[ i ].rgbtGreen ;
  403.             lpPal->palPalEntry[ i ].peBlue   =
  404.                                        lpbmc->bmciColors[ i ].rgbtBlue ;
  405.             lpPal->palPalEntry[ i ].peFlags  = 0 ;
  406.          }
  407.       }
  408.  
  409.       // Create the palette and get handle to it.
  410.      *hPal = ::CreatePalette ( lpPal ) ;
  411.       if ( NULL != hPal )
  412.           bResult = TRUE ;
  413.  
  414.       delete [] lpPal ;
  415.    }
  416.    return ( bResult ) ;
  417. }
  418.  
  419. /***********************************************************************
  420.  *
  421.  * DIBWidth()
  422.  *
  423.  * Parameter:
  424.  *
  425.  * LPSTR lpbi       - pointer to packed-DIB memory block
  426.  *
  427.  * Return Value:
  428.  *
  429.  * DWORD            - width of the DIB
  430.  *
  431.  * Description:
  432.  *
  433.  * This function gets the width of the DIB from the BITMAPINFOHEADER
  434.  * width field if it is a Windows 3.0-style DIB or from the
  435.  * BITMAPCOREHEADER width field if it is an other-style DIB.
  436.  *
  437.  **********************************************************************/
  438. DWORD WINAPI DIBWidth ( LPSTR lpDIB )
  439. {
  440.    LPBITMAPINFOHEADER lpbmi ;  // Pointer to a Win 3.0-style DIB
  441.    LPBITMAPCOREHEADER lpbmc ;  // Pointer to an other-style DIB
  442.  
  443.    // Point to the header (whether Win 3.0 and old)
  444.  
  445.    lpbmi = (LPBITMAPINFOHEADER)lpDIB ;
  446.    lpbmc = (LPBITMAPCOREHEADER)lpDIB ;
  447.  
  448.    // Return the DIB width if it is a Win 3.0 DIB.
  449.    if ( IS_WIN30_DIB ( lpDIB ) )
  450.       return ( lpbmi->biWidth ) ;
  451.    else  // It is an other-style DIB, so return its width.
  452.       return ( (DWORD)lpbmc->bcWidth ) ;
  453. }
  454.  
  455. /***********************************************************************
  456.  *
  457.  * DIBHeight()
  458.  *
  459.  * Parameter:
  460.  *
  461.  * LPSTR lpbi       - pointer to packed-DIB memory block
  462.  *
  463.  * Return Value:
  464.  *
  465.  * DWORD            - height of the DIB
  466.  *
  467.  * Description:
  468.  *
  469.  * This function gets the height of the DIB from the BITMAPINFOHEADER
  470.  * height field if it is a Windows 3.0-style DIB or from the
  471.  * BITMAPCOREHEADER height field if it is an other-style DIB.
  472.  *
  473.  **********************************************************************/
  474. DWORD WINAPI DIBHeight ( LPSTR lpDIB )
  475. {
  476.    LPBITMAPINFOHEADER lpbmi ; // Pointer to a Win 3.0-style DIB.
  477.    LPBITMAPCOREHEADER lpbmc ; // Pointer to an other-style DIB.
  478.  
  479.    // Point to the header (whether old or Win 3.0.
  480.  
  481.    lpbmi = (LPBITMAPINFOHEADER)lpDIB ;
  482.    lpbmc = (LPBITMAPCOREHEADER)lpDIB ;
  483.  
  484.    // Return the DIB height if it is a Win 3.0 DIB.
  485.    if ( IS_WIN30_DIB ( lpDIB ) )
  486.       return ( lpbmi->biHeight ) ;
  487.    else  // It is an other-style DIB, so return its height.
  488.       return ( (DWORD)lpbmc->bcHeight ) ;
  489. }
  490.  
  491.  
  492. /***********************************************************************
  493.  *
  494.  * PaletteSize()
  495.  *
  496.  * Parameter:
  497.  *
  498.  * LPSTR lpbi       - pointer to packed-DIB memory block
  499.  *
  500.  * Return Value:
  501.  *
  502.  * WORD             - size of the color palette of the DIB
  503.  *
  504.  * Description:
  505.  *
  506.  * This function gets the size required to store the DIB's palette by
  507.  * multiplying the number of colors by the size of an RGBQUAD (for a
  508.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
  509.  * style DIB).
  510.  *
  511.  **********************************************************************/
  512. WORD WINAPI PaletteSize ( LPSTR lpbi )
  513. {
  514.    // Calculate the size required by the palette.
  515.    if ( IS_WIN30_DIB ( lpbi ) )
  516.      return ( (WORD)( ::DIBNumColors ( lpbi ) * sizeof ( RGBQUAD ) ) ) ;
  517.    else
  518.      return ( (WORD)( ::DIBNumColors ( lpbi ) * sizeof ( RGBTRIPLE ) ));
  519. }
  520.  
  521.  
  522. /***********************************************************************
  523.  *
  524.  * DIBNumColors()
  525.  *
  526.  * Parameter:
  527.  *
  528.  * LPSTR lpbi       - pointer to packed-DIB memory block
  529.  *
  530.  * Return Value:
  531.  *
  532.  * WORD             - number of colors in the color table
  533.  *
  534.  * Description:
  535.  *
  536.  * This function calculates the number of colors in the DIB's color
  537.  * table by finding the bits per pixel for the DIB (whether Win3.0 or
  538.  * other-style DIB). If bits per pixel is 1: colors=2, if 4: colors=16,
  539.  * if 8: colors=256, if 24, no colors in color table.
  540.  *
  541.  **********************************************************************/
  542. WORD WINAPI DIBNumColors ( LPSTR lpbi )
  543. {
  544.    WORD wBitCount ;  // DIB bit count
  545.  
  546.    // If this is a Windows-style DIB, the number of colors in the
  547.    //  color table can be less than the number of bits per pixel
  548.    //  allows for (i.e. lpbi->biClrUsed can be set to some value).
  549.    //  If this is the case, return the appropriate value.
  550.  
  551.    if ( IS_WIN30_DIB ( lpbi ) )
  552.    {
  553.       DWORD dwClrUsed ;
  554.  
  555.       dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed ;
  556.       if ( 0 != dwClrUsed )
  557.          return ( (WORD)dwClrUsed ) ;
  558.    }
  559.  
  560.    // Calculate the number of colors in the color table based on
  561.    //  the number of bits per pixel for the DIB.
  562.    if ( IS_WIN30_DIB ( lpbi ) )
  563.       wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount ;
  564.    else
  565.       wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount ;
  566.  
  567.    // Return number of colors based on bits per pixel.
  568.    switch ( wBitCount )
  569.    {
  570.       case 1   :
  571.          return ( 2 ) ;
  572.       case 4   :
  573.          return ( 16 ) ;
  574.       case 8   :
  575.          return ( 256 ) ;
  576.       default  :
  577.          return ( 0 ) ;
  578.    }
  579. }
  580.  
  581.  
  582.  
  583.