home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / mcipuzzl / puzzproc.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  15KB  |  455 lines

  1. /****************************************************************************
  2.  *
  3.  *  PUZZPROC.C
  4.  *
  5.  *  Modification of standard AVI drawing handler.
  6.  *
  7.  ***************************************************************************/
  8. /**************************************************************************
  9.  *
  10.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13.  *  PURPOSE.
  14.  *
  15.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  16.  *
  17.  **************************************************************************/
  18.  
  19. #define  STRICT
  20. #define  INC_OLE2
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <mmsystem.h>
  24. #include <stdlib.h>
  25. #include <vfw.h>
  26.  
  27. #include "puzzproc.h"
  28. #include "puzzle.h"
  29.  
  30. #define LOCAL  __stdcall
  31. #define SZCODE char
  32.  
  33. static SZCODE szDescription[] = "Microsoft Puzzle Draw handler";
  34. static SZCODE szName[]        = "MS Puzzle";
  35.  
  36. #define FOURCC_AVIDraw          mmioFOURCC('P','U','Z','Z')
  37. #define VERSION_AVIDraw         0x00010000      // 1.00
  38.  
  39. extern PUZZLE   gPuzzle;
  40.  
  41. /***************************************************************************
  42.  ***************************************************************************/
  43.  
  44. typedef struct {
  45.     HDRAWDIB            hdd;
  46.     HDC                 hdc;            // HDC to draw to
  47.     int                 xDst;           // destination rectangle
  48.     int                 yDst;
  49.     int                 dxDst;
  50.     int                 dyDst;
  51.     int                 xSrc;           // source rectangle
  52.     int                 ySrc;
  53.     int                 dxSrc;
  54.     int                 dySrc;
  55.     LPBYTE              lpBuffer;
  56. } INSTINFO;
  57.  
  58.  
  59. /***************************************************************************
  60.  ***************************************************************************/
  61.  
  62. typedef ICOPEN *                LPICOPEN;
  63. typedef ICINFO *                LPICINFO;
  64. typedef ICDRAW *                LPICDRAW;
  65. typedef ICDRAWSUGGEST *         LPICDRAWSUGGEST;
  66. typedef ICDRAWBEGIN *           LPICDRAWBEGIN;
  67. typedef INSTINFO *              LPINSTINFO;
  68.  
  69. /***************************************************************************
  70.  ***************************************************************************/
  71.  
  72. // static stuff in this file.
  73. static LONG LOCAL AVIDrawOpen(LPICOPEN);
  74. static LONG LOCAL AVIDrawClose(LPINSTINFO);
  75. static LONG LOCAL AVIDrawGetInfo(LPICINFO, LONG);
  76. static LONG LOCAL AVIDrawQuery(LPINSTINFO, LPBITMAPINFOHEADER);
  77. static LONG LOCAL AVIDrawSuggestFormat(LPINSTINFO, LPICDRAWSUGGEST, LONG);
  78. static LONG LOCAL AVIDrawBegin(LPINSTINFO, LPICDRAWBEGIN, LONG);
  79. static LONG LOCAL AVIDraw(LPINSTINFO, LPICDRAW, LONG);
  80. static LONG LOCAL AVIDrawEnd(LPINSTINFO);
  81. static LONG LOCAL AVIDrawChangePalette(LPINSTINFO, LPBITMAPINFOHEADER);
  82.  
  83. /***************************************************************************
  84.  ***************************************************************************/
  85.  
  86. LONG CALLBACK ICAVIDrawProc(
  87. DWORD id,
  88. HDRVR hDriver,
  89. UINT uiMessage,
  90. LPARAM lParam1,
  91. LPARAM lParam2)
  92. {
  93.         LPINSTINFO pi = (LPINSTINFO)id;
  94.  
  95.         switch (uiMessage) {
  96.  
  97.                 case DRV_LOAD:
  98.                 case DRV_FREE:
  99.                         return 1L;
  100.  
  101.                 //open
  102.                 case DRV_OPEN:
  103.                         if (lParam2 == 0L)
  104.                                 return 1L;
  105.                         else
  106.                                 return AVIDrawOpen((LPICOPEN)lParam2);
  107.  
  108.                 //close
  109.                 case DRV_CLOSE:
  110.                         return AVIDrawClose(pi);
  111.  
  112.                 //Configure and Info messages
  113.                 case DRV_QUERYCONFIGURE:    // configuration from drivers applet
  114.                         return 0;
  115.  
  116.                 case DRV_CONFIGURE:
  117.                         return 1;
  118.  
  119.                 case ICM_CONFIGURE:
  120.                 case ICM_ABOUT:
  121.                         return ICERR_UNSUPPORTED;
  122.  
  123.                 case ICM_GETINFO:
  124.                         return AVIDrawGetInfo((LPICINFO)lParam1, lParam2);
  125.  
  126.                 //state messages
  127.                 case ICM_GETSTATE:
  128.                 case ICM_SETSTATE:
  129.                         return 0L;
  130.  
  131.                 //draw messages
  132.                 case ICM_DRAW_QUERY:
  133.                         return AVIDrawQuery(pi, (LPBITMAPINFOHEADER)lParam1);
  134.  
  135.                 case ICM_DRAW_SUGGESTFORMAT:
  136.                         return AVIDrawSuggestFormat(pi, (LPICDRAWSUGGEST) lParam1, lParam2);
  137.  
  138.                 case ICM_DRAW_BEGIN:
  139.                         return AVIDrawBegin(pi, (LPICDRAWBEGIN) lParam1, lParam2);
  140.  
  141.                 case ICM_DRAW_REALIZE:
  142.                         pi->hdc = (HDC) lParam1;
  143.                         if (!pi->hdc || !pi->hdd)
  144.                                 break;
  145.                         return DrawDibRealize(pi->hdd, pi->hdc, (BOOL) lParam2);
  146.  
  147.                 case ICM_DRAW_GET_PALETTE:
  148.                         if (!pi->hdd)
  149.                                 break;
  150.                         return (LONG) (UINT) DrawDibGetPalette(pi->hdd);
  151.  
  152.                 case ICM_DRAW:
  153.                         return AVIDraw(pi, (LPICDRAW)lParam1, lParam2);
  154.  
  155.                 case ICM_DRAW_CHANGEPALETTE:
  156.                         return AVIDrawChangePalette(pi, (LPBITMAPINFOHEADER) lParam1);
  157.  
  158.                 case ICM_DRAW_END:
  159.                         return AVIDrawEnd(pi);
  160.  
  161.                 //standard driver messages
  162.                 case DRV_DISABLE:
  163.                 case DRV_ENABLE:
  164.                         return 1L;
  165.  
  166.                 case DRV_INSTALL:
  167.                 case DRV_REMOVE:
  168.                         return 1L;
  169.         }
  170.         if (uiMessage < DRV_USER)
  171.                 return DefDriverProc(id,hDriver,uiMessage,lParam1,lParam2);
  172.         else
  173.                 return ICERR_UNSUPPORTED;
  174. }
  175. /*****************************************************************************
  176.  *
  177.  * AVIDrawOpen() is called from the DRV_OPEN message
  178.  *
  179.  ****************************************************************************/
  180.  
  181. static LONG LOCAL AVIDrawOpen(
  182. LPICOPEN icopen)
  183. {
  184.         LPINSTINFO pinst;
  185.  
  186.         // refuse to open if we are not being opened as a video draw device
  187.         if (icopen->fccType != streamtypeVIDEO)
  188.                 return 0L;
  189.  
  190.         if (icopen->dwFlags == ICMODE_COMPRESS)
  191.                 return 0L;
  192.  
  193.         if (icopen->dwFlags == ICMODE_DECOMPRESS)
  194.                 return 0L;
  195.  
  196.         pinst = (LPINSTINFO)GlobalAllocPtr(GHND, sizeof(INSTINFO));
  197.  
  198.         if (!pinst) {
  199.                 icopen->dwError = ICERR_MEMORY;
  200.                 return 0L;
  201.         }
  202.  
  203.         // init structure
  204.         pinst->hdd = DrawDibOpen();
  205.  
  206.         // return success.
  207.         icopen->dwError = ICERR_OK;
  208.  
  209.         return (LONG)pinst;
  210. }
  211. /*****************************************************************************
  212.  *
  213.  * AVIDrawClose() is called on the DRV_CLOSE message.
  214.  *
  215.  ****************************************************************************/
  216. static LONG LOCAL AVIDrawClose(
  217. LPINSTINFO pi)
  218. {
  219.         if (pi->hdd)
  220.                 DrawDibClose(pi->hdd);
  221.  
  222.         if (pi->lpBuffer)
  223.                 GlobalFreePtr(pi->lpBuffer);
  224.  
  225.         GlobalFreePtr(pi);
  226.         return 1L;
  227. }
  228. /*****************************************************************************
  229.  *
  230.  * AVIDrawGetInfo() implements the ICM_GETINFO message
  231.  *
  232.  ****************************************************************************/
  233. static LONG LOCAL AVIDrawGetInfo(
  234. LPICINFO icinfo,
  235. LONG lSize)
  236. {
  237.         if (icinfo == NULL)
  238.                 return sizeof(ICINFO);
  239.  
  240.         if (lSize < sizeof(ICINFO))
  241.                 return 0L;
  242.  
  243.         icinfo->dwSize          = sizeof(ICINFO);
  244.         icinfo->fccType         = ICTYPE_VIDEO;
  245.         icinfo->fccHandler      = FOURCC_AVIDraw;
  246.         icinfo->dwFlags         = VIDCF_DRAW;
  247.         icinfo->dwVersion       = VERSION_AVIDraw;
  248.         icinfo->dwVersionICM    = ICVERSION;
  249.         MultiByteToWideChar(CP_ACP, 0, szDescription, -1, icinfo->szDescription, sizeof(icinfo->szDescription));
  250.         MultiByteToWideChar(CP_ACP, 0, szName, -1, icinfo->szDescription, sizeof(icinfo->szDescription));
  251.         return sizeof(ICINFO);
  252. }
  253. /*****************************************************************************
  254.  *
  255.  * AVIDrawQuery() implements ICM_DRAW_QUERY
  256.  *
  257.  ****************************************************************************/
  258. static LONG LOCAL AVIDrawQuery(
  259. LPINSTINFO pi,
  260. LPBITMAPINFOHEADER lpbiIn)
  261. {
  262.         // determine if the input DIB data is in a format we like.
  263.         if (lpbiIn == NULL)
  264.                 return ICERR_BADFORMAT;
  265.  
  266.         // determine if the input DIB data is in a format we like.
  267.         if (lpbiIn->biCompression != BI_RGB)
  268.                 return ICERR_BADFORMAT;
  269.  
  270.         return ICERR_OK;
  271. }
  272. /*****************************************************************************
  273.  *
  274.  * AVIDrawSuggestFormat() implements ICM_DRAW_SUGGESTFORMAT
  275.  *
  276.  ****************************************************************************/
  277.  
  278. static LONG LOCAL AVIDrawSuggestFormat(
  279. LPINSTINFO pi,
  280. LPICDRAWSUGGEST lpicd,
  281. LONG cbicd)
  282. {
  283.         HIC hic;
  284.         LONG l;
  285.  
  286.         if (lpicd->lpbiSuggest == NULL)
  287.                 return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
  288.  
  289.         // Call COMPMAN to get a good format to display data in....
  290.         hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn, lpicd->lpbiSuggest,
  291.                                                 0, lpicd->dxDst, lpicd->dyDst);
  292.  
  293.         if (hic)
  294.                 ICClose(hic);
  295.  
  296.         l = lpicd->lpbiSuggest->biClrUsed;
  297.  
  298.         if (lpicd->lpbiSuggest)
  299.                 if (lpicd->lpbiSuggest->biCompression == BI_RLE8)
  300.                         lpicd->lpbiSuggest->biCompression = BI_RGB;
  301.  
  302.         // !!! Should check this format here to make sure it's RGB...
  303.         // !!! If not, we could force it to 8-bit....
  304.  
  305.         l = l * sizeof(RGBQUAD);
  306.         return l + sizeof(BITMAPINFOHEADER);
  307. }
  308.  
  309. /*****************************************************************************
  310.  *
  311.  * AVIDrawBegin() implements ICM_DRAW_BEGIN
  312.  *
  313.  ****************************************************************************/
  314.  
  315. static LONG LOCAL AVIDrawBegin(
  316. LPINSTINFO pi,
  317. LPICDRAWBEGIN lpicd,
  318. LONG cbicd)
  319. {
  320.         LONG l = AVIDrawQuery(pi, lpicd->lpbi);
  321.  
  322.         if ((l != 0) || (lpicd->dwFlags & ICDRAW_QUERY))
  323.                 return l;
  324.  
  325.         // Copy over whatever we want to remember
  326.         pi->hdc = lpicd->hdc;
  327.         pi->xDst = lpicd->xDst;
  328.         pi->yDst = lpicd->yDst;
  329.         pi->dxDst = lpicd->dxDst;
  330.         pi->dyDst = lpicd->dyDst;
  331.         pi->xSrc = lpicd->xSrc;
  332.         pi->ySrc = lpicd->ySrc;
  333.         pi->dxSrc = lpicd->dxSrc;
  334.         pi->dySrc = lpicd->dySrc;
  335.  
  336.         SetStretchBltMode(pi->hdc, COLORONCOLOR);
  337.  
  338.         if (!DrawDibBegin(
  339.                         pi->hdd,
  340.                         pi->hdc,
  341.                         pi->dxDst,
  342.                         pi->dyDst,
  343.                         lpicd->lpbi,
  344.                         pi->dxSrc,
  345.                         pi->dySrc,
  346.                         0)) {  // !!! Flags?
  347.                 return ICERR_UNSUPPORTED;
  348.         }
  349.  
  350.         // !!! error check
  351.  
  352.         // Allocate a buffer for the scrambled picture
  353.         if (pi->lpBuffer)
  354.                 GlobalFreePtr(pi->lpBuffer);
  355.  
  356.         pi->lpBuffer = GlobalAllocPtr(GMEM_MOVEABLE, lpicd->lpbi->biSizeImage);
  357.  
  358.         if (!pi->lpBuffer)
  359.                 return ICERR_MEMORY;
  360.  
  361.         return ICERR_OK;
  362. }
  363. /*****************************************************************************
  364.  *
  365.  * AVIDraw() implements ICM_DRAW
  366.  *
  367.  ****************************************************************************/
  368.  
  369. static LONG LOCAL AVIDraw(
  370. LPINSTINFO pi,
  371. LPICDRAW lpicd,
  372. LONG cbicd)
  373. {
  374.         UINT wFlags = DDF_SAME_HDC;
  375.  
  376.         if ((lpicd->dwFlags & ICDRAW_NULLFRAME) || lpicd->lpData == NULL) {
  377.                 if (lpicd->dwFlags & ICDRAW_UPDATE)
  378.                         wFlags |= DDF_UPDATE;
  379.                 else
  380.                         return ICERR_OK;            // nothing to draw
  381.         }
  382.  
  383.         if (lpicd->dwFlags & ICDRAW_PREROLL)
  384.                 wFlags |= DDF_DONTDRAW;
  385.  
  386.         if (lpicd->dwFlags & ICDRAW_HURRYUP)
  387.                 wFlags |= DDF_HURRYUP;
  388.  
  389.         // This is the only part that actually has to do with the puzzle:
  390.         // Mix up the picture into our extra buffer.
  391.         if (lpicd->lpData)
  392.                 MixPicture(&gPuzzle, lpicd->lpFormat, lpicd->lpData, pi->lpBuffer);
  393.  
  394.         if (!DrawDibDraw(
  395.                         pi->hdd,
  396.                         pi->hdc,
  397.                         pi->xDst,
  398.                         pi->yDst,
  399.                         pi->dxDst,
  400.                         pi->dyDst,
  401.                         lpicd->lpFormat,
  402.                         pi->lpBuffer,
  403.                         pi->xSrc,
  404.                         pi->ySrc,
  405.                         pi->dxSrc,
  406.                         pi->dySrc,
  407.                         wFlags)) {
  408.                 if (wFlags & DDF_UPDATE)
  409.                         return ICERR_CANTUPDATE;
  410.                 else
  411.                         return ICERR_UNSUPPORTED;
  412.         }
  413.  
  414.         return ICERR_OK;
  415. }
  416. /*****************************************************************************
  417.  *
  418.  * AVIDrawChangePalette() implements ICM_DRAW_CHANGE_PALETTE
  419.  *
  420.  ****************************************************************************/
  421.  
  422. static LONG LOCAL AVIDrawChangePalette(
  423. LPINSTINFO pi,
  424. LPBITMAPINFOHEADER lpbi)
  425. {
  426.         PALETTEENTRY ape[256];
  427.         LPRGBQUAD lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  428.         int i;
  429.  
  430.         for (i = 0; i < (int) lpbi->biClrUsed; i++) {
  431.                 ape[i].peRed = lprgb[i].rgbRed;
  432.                 ape[i].peGreen = lprgb[i].rgbGreen;
  433.                 ape[i].peBlue = lprgb[i].rgbBlue;
  434.                 ape[i].peFlags = 0;
  435.         }
  436.  
  437.         DrawDibChangePalette(pi->hdd, 0, (int) lpbi->biClrUsed, (LPPALETTEENTRY)ape);
  438.         return ICERR_OK;
  439. }
  440. /*****************************************************************************
  441.  *
  442.  * AVIDrawEnd() implements ICM_DRAW_END
  443.  *
  444.  ****************************************************************************/
  445.  
  446. static LONG LOCAL AVIDrawEnd(
  447. LPINSTINFO pi)
  448. {
  449.         // Note: do not call DrawDibEnd here, as we still may be asked to
  450.         // update our current display, and calling DrawDibEnd would wipe
  451.         // that out.
  452.  
  453.         return ICERR_OK;
  454. }
  455.