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 / misc / ddutil2.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  8KB  |  331 lines

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