home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / duel / ddutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  8.1 KB  |  324 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       ddutil.cpp
  6.  *  Content:    Routines for loading bitmap and palettes from resources
  7.  *
  8.  ***************************************************************************/
  9. #undef WIN32_LEAN_AND_MEAN
  10. #define WIN32_LEAN_AND_MEAN
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <ddraw.h>
  14. #include "ddutil.h"
  15.  
  16. /*
  17.  *  DDLoadBitmap
  18.  *
  19.  *  create a DirectDrawSurface from a bitmap resource.
  20.  *
  21.  */
  22. extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd, LPCTSTR tszBitmap, int dx, int dy)
  23. {
  24.     HBITMAP             hbm;
  25.     BITMAP              bm;
  26.     DDSURFACEDESC       ddsd;
  27.     IDirectDrawSurface *pdds;
  28.  
  29.     //
  30.     //  try to load the bitmap as a resource, if that fails, try it as a file
  31.     //
  32.     hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), tszBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
  33.  
  34.     if (hbm == NULL)
  35.     hbm = (HBITMAP)LoadImage(NULL, tszBitmap, IMAGE_BITMAP, dx, dy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  36.  
  37.     if (hbm == NULL)
  38.     return NULL;
  39.  
  40.     //
  41.     // get size of the bitmap
  42.     //
  43.     GetObject(hbm, sizeof(bm), &bm);      // get size of bitmap
  44.  
  45.     //
  46.     // create a DirectDrawSurface for this bitmap
  47.     //
  48.     ZeroMemory(&ddsd, sizeof(ddsd));
  49.     ddsd.dwSize = sizeof(ddsd);
  50.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  51.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  52.     ddsd.dwWidth = bm.bmWidth;
  53.     ddsd.dwHeight = bm.bmHeight;
  54.  
  55.     if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
  56.     return NULL;
  57.  
  58.     DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
  59.  
  60.     DeleteObject(hbm);
  61.  
  62.     return pdds;
  63. }
  64.  
  65. /*
  66.  *  DDReLoadBitmap
  67.  *
  68.  *  load a bitmap from a file or resource into a directdraw surface.
  69.  *  normaly used to re-load a surface after a restore.
  70.  *
  71.  */
  72. HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds, LPCTSTR tszBitmap)
  73. {
  74.     HBITMAP             hbm;
  75.     HRESULT             hr;
  76.  
  77.     //
  78.     //  try to load the bitmap as a resource, if that fails, try it as a file
  79.     //
  80.     hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), tszBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  81.  
  82.     if (hbm == NULL)
  83.     hbm = (HBITMAP)LoadImage(NULL, tszBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  84.  
  85.     if (hbm == NULL)
  86.     {
  87.     OutputDebugString(TEXT("handle is null\n"));
  88.     return E_FAIL;
  89.     }
  90.  
  91.     hr = DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
  92.     if (hr != DD_OK)
  93.     {
  94.     OutputDebugString(TEXT("ddcopybitmap failed\n"));
  95.     }
  96.  
  97.  
  98.     DeleteObject(hbm);
  99.     return hr;
  100. }
  101.  
  102. /*
  103.  *  DDCopyBitmap
  104.  *
  105.  *  draw a bitmap into a DirectDrawSurface
  106.  *
  107.  */
  108. extern "C" HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm, int x, int y, int dx, int dy)
  109. {
  110.     HDC                 hdcImage;
  111.     HDC                 hdc;
  112.     BITMAP              bm;
  113.     DDSURFACEDESC       ddsd;
  114.     HRESULT             hr;
  115.  
  116.     if (hbm == NULL || pdds == NULL)
  117.     return E_FAIL;
  118.  
  119.     //
  120.     // make sure this surface is restored.
  121.     //
  122.     pdds->Restore();
  123.  
  124.     //
  125.     //  select bitmap into a memoryDC so we can use it.
  126.     //
  127.     hdcImage = CreateCompatibleDC(NULL);
  128.     if (!hdcImage)
  129.     OutputDebugString(TEXT("createcompatible dc failed\n"));
  130.     SelectObject(hdcImage, hbm);
  131.  
  132.     //
  133.     // get size of the bitmap
  134.     //
  135.     GetObject(hbm, sizeof(bm), &bm);    // get size of bitmap
  136.     dx = dx == 0 ? bm.bmWidth  : dx;    // use the passed size, unless zero
  137.     dy = dy == 0 ? bm.bmHeight : dy;
  138.  
  139.     //
  140.     // get size of surface.
  141.     //
  142.     ddsd.dwSize = sizeof(ddsd);
  143.     ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
  144.     pdds->GetSurfaceDesc(&ddsd);
  145.  
  146.     if ((hr = pdds->GetDC(&hdc)) == DD_OK)
  147.     {
  148.     StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y, dx, dy, SRCCOPY);
  149.     pdds->ReleaseDC(hdc);
  150.     }
  151.  
  152.     DeleteDC(hdcImage);
  153.  
  154.     return hr;
  155. }
  156.  
  157. //
  158. //  DDLoadPalette
  159. //
  160. //  Create a DirectDraw palette object from a bitmap resoure
  161. //
  162. //  if the resource does not exist or NULL is passed create a
  163. //  default 332 palette.
  164. //
  165. extern "C" IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd, LPCTSTR tszBitmap)
  166. {
  167.     IDirectDrawPalette* ddpal;
  168.     int                 i;
  169.     int                 n;
  170.     HANDLE              fh;
  171.     HRSRC               h;
  172.     LPBITMAPINFOHEADER  lpbi;
  173.     PALETTEENTRY        ape[256];
  174.     RGBQUAD *           prgb;
  175.     DWORD                dwRead;
  176.  
  177.     //
  178.     // build a 332 palette as the default.
  179.     //
  180.     for (i=0; i<256; i++)
  181.     {
  182.     ape[i].peRed   = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
  183.     ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
  184.     ape[i].peBlue  = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
  185.     ape[i].peFlags = (BYTE)0;
  186.     }
  187.  
  188.     //
  189.     // get a pointer to the bitmap resource.
  190.     //
  191.     if (tszBitmap && (h = FindResource(NULL, tszBitmap, RT_BITMAP)))
  192.     {
  193.     lpbi = (LPBITMAPINFOHEADER)LockResource(LoadResource(NULL, h));
  194.     if (!lpbi)
  195.         OutputDebugString(TEXT("lock resource failed\n"));
  196.     prgb = (RGBQUAD*)((BYTE*)lpbi + lpbi->biSize);
  197.  
  198.     if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER))
  199.         n = 0;
  200.     else if (lpbi->biBitCount > 8)
  201.         n = 0;
  202.     else if (lpbi->biClrUsed == 0)
  203.         n = 1 << lpbi->biBitCount;
  204.     else
  205.         n = lpbi->biClrUsed;
  206.  
  207.     //
  208.     //  a DIB color table has its colors stored BGR not RGB
  209.     //  so flip them around.
  210.     //
  211.     for(i=0; i<n; i++ )
  212.     {
  213.         ape[i].peRed   = prgb[i].rgbRed;
  214.         ape[i].peGreen = prgb[i].rgbGreen;
  215.         ape[i].peBlue  = prgb[i].rgbBlue;
  216.         ape[i].peFlags = 0;
  217.     }
  218.     }
  219.     else if (tszBitmap && (fh = CreateFile(tszBitmap, GENERIC_READ, FILE_SHARE_READ, 
  220.                                             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 
  221.                                             NULL)) != INVALID_HANDLE_VALUE)
  222.     {
  223.     BITMAPFILEHEADER bf;
  224.     BITMAPINFOHEADER bi;
  225.  
  226.     ReadFile(fh, &bf, sizeof(bf), &dwRead, NULL);
  227.     ReadFile(fh, &bi, sizeof(bi), &dwRead, NULL);
  228.     ReadFile(fh, ape, sizeof(ape), &dwRead, NULL);
  229.     CloseHandle(fh);
  230.  
  231.     if (bi.biSize != sizeof(BITMAPINFOHEADER))
  232.         n = 0;
  233.     else if (bi.biBitCount > 8)
  234.         n = 0;
  235.     else if (bi.biClrUsed == 0)
  236.         n = 1 << bi.biBitCount;
  237.     else
  238.         n = bi.biClrUsed;
  239.  
  240.     //
  241.     //  a DIB color table has its colors stored BGR not RGB
  242.     //  so flip them around.
  243.     //
  244.     for(i=0; i<n; i++ )
  245.     {
  246.         BYTE r = ape[i].peRed;
  247.         ape[i].peRed  = ape[i].peBlue;
  248.         ape[i].peBlue = r;
  249.     }
  250.     }
  251.  
  252.     pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
  253.  
  254.     return ddpal;
  255. }
  256.  
  257. /*
  258.  * DDColorMatch
  259.  *
  260.  * convert a RGB color to a pysical color.
  261.  *
  262.  * we do this by leting GDI SetPixel() do the color matching
  263.  * then we lock the memory and see what it got mapped to.
  264.  */
  265. extern "C" DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
  266. {
  267.     COLORREF rgbT;
  268.     HDC hdc;
  269.     DWORD dw = CLR_INVALID;
  270.     DDSURFACEDESC ddsd;
  271.     HRESULT hres;
  272.  
  273.     //
  274.     //  use GDI SetPixel to color match for us
  275.     //
  276.     if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  277.     {
  278.     rgbT = GetPixel(hdc, 0, 0);             // save current pixel value
  279.     SetPixel(hdc, 0, 0, rgb);               // set our value
  280.     pdds->ReleaseDC(hdc);
  281.     }
  282.  
  283.     //
  284.     // now lock the surface so we can read back the converted color
  285.     //
  286.     ddsd.dwSize = sizeof(ddsd);
  287.     while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
  288.     ;
  289.  
  290.     if (hres == DD_OK)
  291.     {
  292.     dw  = *(DWORD *)ddsd.lpSurface;                     // get DWORD
  293.     dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;  // mask it to bpp
  294.     pdds->Unlock(NULL);
  295.     }
  296.  
  297.     //
  298.     //  now put the color that was there back.
  299.     //
  300.     if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  301.     {
  302.     SetPixel(hdc, 0, 0, rgbT);
  303.     pdds->ReleaseDC(hdc);
  304.     }
  305.  
  306.     return dw;
  307. }
  308.  
  309. /*
  310.  * DDSetColorKey
  311.  *
  312.  * set a color key for a surface, given a RGB.
  313.  * if you pass CLR_INVALID as the color key, the pixel
  314.  * in the upper-left corner will be used.
  315.  */
  316. extern "C" HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb)
  317. {
  318.     DDCOLORKEY          ddck;
  319.  
  320.     ddck.dwColorSpaceLowValue  = DDColorMatch(pdds, rgb);
  321.     ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
  322.     return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
  323. }
  324.