home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / gdidemo / poly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  11.9 KB  |  414 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*---------------------------------------------------------------------------*\
  13. | POLYBEZIER MODULE
  14. |   This module contains the routines for demo
  15. \*---------------------------------------------------------------------------*/
  16.  
  17. #include <windows.h>
  18. #include "gdidemo.h"
  19. #include  "poly.h"
  20.  
  21. /*---------------------------------------------------------------------------*\
  22. | CREATE BEZIER WINDOW PROCEDURE
  23. |   Create the bezier MDI-child window.
  24. \*---------------------------------------------------------------------------*/
  25. HWND FAR CreatePolyWindow(HWND hWndClient, int nItem)
  26. {
  27.     HANDLE          hInstance;
  28.     MDICREATESTRUCT mcs;
  29.     static char buffer[256];
  30.  
  31.  
  32.     hInstance = GETINSTANCE(hWndClient);
  33.     LoadString (hInstance, POLYTITLE, buffer, 256);
  34.  
  35.     /*
  36.     ** Initialize the MDI create struct for creation of the
  37.     ** test window.
  38.     */
  39.     mcs.szClass = POLYCLASS;
  40.     mcs.szTitle = buffer;
  41.     mcs.hOwner  = hInstance;
  42.     mcs.x       = CW_USEDEFAULT;
  43.     mcs.y       = CW_USEDEFAULT;
  44.     mcs.cx      = CW_USEDEFAULT;
  45.     mcs.cy      = CW_USEDEFAULT;
  46.     mcs.style   = 0l;
  47.     mcs.lParam  = (LONG)nItem;
  48.  
  49.     return((HWND)SendMessage(hWndClient,WM_MDICREATE,0,(LONG)(LPMDICREATESTRUCT)&mcs));
  50. }
  51.  
  52.  
  53. /*---------------------------------------------------------------------------*\
  54. | POLYBEZIER WINDOW PROCEDURE
  55. |   This is the main window function for the polybezier demo window.
  56. \*---------------------------------------------------------------------------*/
  57. LONG APIENTRY PolyProc(HWND hWnd, UINT wMsg, WPARAM wParam, LONG lParam)
  58. {
  59.     switch(wMsg)
  60.     {
  61.         case WM_CREATE:
  62.             PolyCreateProc(hWnd);
  63.             break;
  64.  
  65.  
  66.         case WM_COMMAND:
  67.             PolyCommandProc(hWnd,wParam,lParam);
  68.             break;
  69.  
  70.         case WM_MOVE:
  71.             PolyRedraw(hWnd);
  72.             break;
  73.  
  74.  
  75.         case WM_TIMER:
  76.             PolyDrawBez(hWnd);
  77.             break;
  78.  
  79.  
  80.         case WM_PAINT:
  81.             PolyPaintProc(hWnd);
  82.             break;
  83.  
  84.  
  85.         case WM_DESTROY:
  86.             PolyDestroyProc(hWnd);
  87.             break;
  88.  
  89.  
  90.         default:
  91.             return(DefMDIChildProc(hWnd,wMsg,wParam,lParam));
  92.     }
  93.     return(0l);
  94. }
  95.  
  96.  
  97. /*---------------------------------------------------------------------------*\
  98. | POLYBEZIER CREATE PROCEDURE
  99. |   Create the polybezier window for the demo application.  This is a child
  100. |   of the MDI client window.  Allocate the extra object information for
  101. |   handling of the polybezier demo.
  102. \*---------------------------------------------------------------------------*/
  103. BOOL PolyCreateProc(HWND hWnd)
  104. {
  105.     PPOLYDATA ppd;
  106.  
  107.  
  108.     if(AllocWindowInfo(hWnd,sizeof(POLYDATA)))
  109.     {
  110.         if(ppd = (PPOLYDATA)LockWindowInfo(hWnd))
  111.         {
  112.             ppd->nBezTotal  = 20;
  113.             ppd->nBezCurr   = 0;
  114.             ppd->nColor     = 0;
  115.             ppd->hBezBuffer = GlobalAlloc(GHND,(DWORD)(sizeof(BEZBUFFER) * MAX_BEZIER));
  116.  
  117.             UnlockWindowInfo(hWnd);
  118.  
  119.             PolyInitPoints(hWnd);
  120.  
  121.             SetTimer(hWnd,1,50,NULL);
  122.             return(TRUE);
  123.         }
  124.         FreeWindowInfo(hWnd);
  125.     }
  126.     return(FALSE);
  127. }
  128.  
  129.  
  130. /*---------------------------------------------------------------------------*\
  131. | POLYBEZIER COMMAND PROCEDURE
  132. |   Process polybezier commands.  This is a NOP for now.  But who knows what
  133. |   tomorrow may bring.
  134. \*---------------------------------------------------------------------------*/
  135. BOOL PolyCommandProc(HWND hWnd, WPARAM wParam, LONG lParam)
  136. {
  137.     hWnd   = hWnd;
  138.     wParam = wParam;
  139.     lParam = lParam;
  140.  
  141.     return(TRUE);
  142. }
  143.  
  144.  
  145. /*---------------------------------------------------------------------------*\
  146. | POLYBEZIER PAINT PROCEDURE
  147. |   Repaint the bezier window.  All we really do here is validate our window,
  148. |   and reset the array of bezier objects.
  149. \*---------------------------------------------------------------------------*/
  150. VOID PolyPaintProc(HWND hWnd)
  151. {
  152.     HDC         hDC;
  153.     PAINTSTRUCT ps;
  154.  
  155.  
  156.     if(hDC = BeginPaint(hWnd,&ps))
  157.         EndPaint(hWnd,&ps);
  158.  
  159.     PolyRedraw(hWnd);
  160.  
  161.     return;
  162. }
  163.  
  164.  
  165. /*---------------------------------------------------------------------------*\
  166. | POLYBEZIER DESTROY PROCEDURE
  167. |   Kill the polybezier demo.  Free up the resources allocated on behalf of
  168. |   this object.
  169. \*---------------------------------------------------------------------------*/
  170. VOID PolyDestroyProc(HWND hWnd)
  171. {
  172.     PPOLYDATA ppd;
  173.  
  174.  
  175.     KillTimer(hWnd,1);
  176.     if(ppd = (PPOLYDATA)LockWindowInfo(hWnd))
  177.     {
  178.         GlobalFree(ppd->hBezBuffer);
  179.         UnlockWindowInfo(hWnd);
  180.     }
  181.     FreeWindowInfo(hWnd);
  182.  
  183.     return;
  184. }
  185.  
  186.  
  187. /*---------------------------------------------------------------------------*\
  188. | GET NEW VELOCITY
  189. |   This routine creates a new velocity for the bezier points.  Each bezier
  190. |   point is randomly chosen.  The two inside points should have a speed
  191. |   less then the endpoints (most of the time-better effect).
  192. \*---------------------------------------------------------------------------*/
  193. int PolyNewVel(int i)
  194. {
  195.     int nRet;
  196.  
  197.  
  198.     if ((i == 1) || (i == 2))
  199.         nRet = (int)((lRandom() % VELMAX) / 3) + VELMIN;
  200.     else
  201.         nRet = (int)(lRandom() % VELMAX) + VELMIN;
  202.  
  203.     return((nRet < 0) ? -nRet : nRet);
  204. }
  205.  
  206.  
  207. /*---------------------------------------------------------------------------*\
  208. | INITIALIZE POLYBEZIER POINTS
  209. |   This routine initializes the polybezier points for the first object.  This
  210. |   is performed on startup of the window.
  211. \*---------------------------------------------------------------------------*/
  212. VOID PolyInitPoints(HWND hWnd)
  213. {
  214.     PPOLYDATA   ppd;
  215.     LPBEZBUFFER lpBez;
  216.     int         idx;
  217.     RECT        rect;
  218.  
  219.  
  220.     if(ppd = (PPOLYDATA)LockWindowInfo(hWnd))
  221.     {
  222.         if(lpBez = (LPBEZBUFFER)GlobalLock(ppd->hBezBuffer))
  223.         {
  224.             GetClientRect(hWnd,&rect);
  225.  
  226.             for(idx=0; idx < BEZ_PTS-1; idx++)
  227.             {
  228.                 lpBez->pPts[idx].x = lRandom() % rect.right;
  229.                 lpBez->pPts[idx].y = lRandom() % rect.bottom;
  230.  
  231.                 ppd->pVel[idx].x = PolyNewVel(idx);
  232.                 ppd->pVel[idx].y = PolyNewVel(idx);
  233.             }
  234.             GlobalUnlock(ppd->hBezBuffer);
  235.         }
  236.         UnlockWindowInfo(hWnd);
  237.     }
  238.     return;
  239. }
  240.  
  241.  
  242. /*---------------------------------------------------------------------------*\
  243. | POLYBEZIER REDRAW
  244. |   This routine resets the bezier curves and redraws the poly-bezier client
  245. |   area.
  246. \*---------------------------------------------------------------------------*/
  247. VOID PolyRedraw(HWND hWnd)
  248. {
  249.     PPOLYDATA   ppd;
  250.     LPBEZBUFFER lpBez,lpCurr;
  251.     HDC         hDC;
  252.     int         i,j;
  253.     RECT        rect;
  254.  
  255.  
  256.     if(ppd = (PPOLYDATA)LockWindowInfo(hWnd))
  257.     {
  258.         if(lpBez = (LPBEZBUFFER)GlobalLock(ppd->hBezBuffer))
  259.         {
  260.             if(hDC = GetDC(hWnd))
  261.             {
  262.                 /*
  263.                 ** Save the current bezier.  Set the first bezier in the
  264.                 ** array to that curve, and use it as a basis for the next
  265.                 ** series.
  266.                 */
  267.                 lpCurr        = lpBez+ppd->nBezCurr;
  268.                 *lpBez        = *lpCurr;
  269.                 ppd->nBezCurr = 0;
  270.  
  271.  
  272.                 /*
  273.                 ** Clean the curves (all but the first curve).
  274.                 */
  275.                 for(j=1; j < ppd->nBezTotal; j++)
  276.                 {
  277.                     for(i=0; i < BEZ_PTS; i++)
  278.                     {
  279.                         (lpBez+j)->pPts[i].x = -1;
  280.                         (lpBez+j)->pPts[i].y = 0;
  281.                     }
  282.                 }
  283.  
  284.  
  285.  
  286.                 /*
  287.                 ** Clear the display.
  288.                 */
  289.                 GetClientRect(hWnd,&rect);
  290.                 BitBlt(hDC,0,0,rect.right, rect.bottom,(HDC)0,0,0,0);
  291.  
  292.  
  293.                 /*
  294.                 ** Draw the first curve in the bezier array.
  295.                 */
  296. #if defined(_WIN32) && defined(WIN32)
  297.                 PolyBezier(hDC,lpBez->pPts,BEZ_PTS);
  298. #else
  299.                 Polyline(hDC,lpBez->pPts,BEZ_PTS);
  300. #endif
  301.                 ReleaseDC(hWnd,hDC);
  302.             }
  303.             GlobalUnlock(ppd->hBezBuffer);
  304.         }
  305.         UnlockWindowInfo(hWnd);
  306.     }
  307.     return;
  308. }
  309.  
  310.  
  311.  
  312.  
  313. VOID PolyDrawBez(HWND hWnd)
  314. {
  315.     PPOLYDATA   ppd;
  316.     LPBEZBUFFER lpBez,lpCurr,lpPrev;
  317.     int         idx,x,y;
  318.     RECT        rect;
  319.     HDC         hDC;
  320.     HPEN        hPen;
  321.  
  322. static COLORREF crColor[] = {0x000000FF,0x0000FF00,0x00FF0000,0x0000FFFF,
  323.                              0x00FF00FF,0x00FFFF00,0x00FFFFFF,0x00000080,
  324.                              0x00008000,0x00800000,0x00008080,0x00800080,
  325.                              0x00808000,0x00808080,0x000000FF,0x0000FF00,
  326.                              0x00FF0000,0x0000FFFF,0x00FF00FF,0x00FFFF00};
  327.  
  328.  
  329.     if(ppd = (PPOLYDATA)LockWindowInfo(hWnd))
  330.     {
  331.         if(lpBez = (LPBEZBUFFER)GlobalLock(ppd->hBezBuffer))
  332.         {
  333.             if(hDC = GetDC(hWnd))
  334.             {
  335.                 GetClientRect(hWnd,&rect);
  336.  
  337.                 lpPrev = lpBez+ppd->nBezCurr;
  338.  
  339.                 ppd->nBezCurr += 1;
  340.  
  341.                 if(ppd->nBezCurr >= ppd->nBezTotal)
  342.                 {
  343.                     ppd->nBezCurr = 0;
  344.                     ppd->nColor  = (++ppd->nColor % 20);
  345.                 }
  346.                 lpCurr = lpBez+ppd->nBezCurr;
  347.  
  348.  
  349.                 if(lpCurr->pPts[0].x != -1)
  350.                 {
  351.                     hPen = SelectObject(hDC,GetStockObject(BLACK_PEN));
  352. #if defined(_WIN32) && defined(WIN32)
  353.                     PolyBezier(hDC,lpCurr->pPts,BEZ_PTS);
  354. #else
  355.                     Polyline(hDC,lpCurr->pPts,BEZ_PTS);
  356. #endif
  357.                     SelectObject(hDC,hPen);
  358.                 }
  359.  
  360.                 for(idx=0; idx < BEZ_PTS; idx++)
  361.                 {
  362.                     x  = lpPrev->pPts[idx].x;
  363.                     y  = lpPrev->pPts[idx].y;
  364.                     x += ppd->pVel[idx].x;
  365.                     y += ppd->pVel[idx].y;
  366.  
  367.                     if(x >= rect.right)
  368.                     {
  369.                         x = rect.right - ((x - rect.right)+1);
  370.                         ppd->pVel[idx].x = -PolyNewVel(idx);
  371.                     }
  372.  
  373.                     if(x <= rect.left)
  374.                     {
  375.                         x = rect.left + ((rect.left - x)+1);
  376.                         ppd->pVel[idx].x = PolyNewVel(idx);
  377.                     }
  378.  
  379.                     if(y >= rect.bottom)
  380.                     {
  381.                         y = rect.bottom - ((y - rect.bottom)+1);
  382.                         ppd->pVel[idx].y = -PolyNewVel(idx);
  383.                     }
  384.  
  385.                     if(y <= rect.top)
  386.                     {
  387.                         y = rect.top + ((rect.top - y)+1);
  388.                         ppd->pVel[idx].y = PolyNewVel(idx);
  389.                     }
  390.  
  391.                     lpCurr->pPts[idx].x = x;
  392.                     lpCurr->pPts[idx].y = y;
  393.  
  394.                 }
  395.  
  396.                 hPen = SelectObject(hDC,CreatePen(PS_SOLID,1,crColor[ppd->nColor]));
  397. #if defined(_WIN32) && defined(WIN32)
  398.                 PolyBezier(hDC,lpCurr->pPts,BEZ_PTS);
  399. #else
  400.                 Polyline(hDC,lpCurr->pPts,BEZ_PTS);
  401. #endif
  402.                 DeleteObject(SelectObject(hDC,hPen));
  403.  
  404. #if defined(_WIN32) && defined(WIN32)
  405.                 SetROP2(hDC,R2_COPYPEN);
  406. #endif
  407.                 ReleaseDC(hWnd,hDC);
  408.             }
  409.             GlobalUnlock(ppd->hBezBuffer);
  410.         }
  411.         UnlockWindowInfo(hWnd);
  412.     }
  413. }
  414.