home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap12 / cosmo / polywin.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  7KB  |  283 lines

  1. /*
  2.  * POLYWIN.CPP
  3.  * Cosmo Chapter 12
  4.  *
  5.  * Window procedure for the polyline drawing window and support
  6.  * functions.  This window is not complicated.  On creation it
  7.  * allocates a block of memory for a POLYLINEDATA structure that
  8.  * contains 20 POINTs.  We do not attempt to reallocate this
  9.  * array at all just to maintain simplicity.
  10.  *
  11.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  12.  *
  13.  * Kraig Brockschmidt, Microsoft
  14.  * Internet  :  kraigb@microsoft.com
  15.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  16.  */
  17.  
  18.  
  19. #include "cosmo.h"
  20.  
  21.  
  22. /*
  23.  * PolylineWndProc
  24.  *
  25.  * Purpose:
  26.  *  Window procedure for the polyline drawing window.
  27.  */
  28.  
  29. LRESULT APIENTRY PolylineWndProc(HWND hWnd, UINT iMsg
  30.     , WPARAM wParam, LPARAM lParam)
  31.     {
  32.     PCPolyline      ppl;
  33.     PAINTSTRUCT     ps;
  34.     HDC             hDC;
  35.     POINTS          pt;
  36.     RECT            rc;
  37.  
  38.     ppl=(PCPolyline)GetWindowLong(hWnd, PLWL_STRUCTURE);
  39.  
  40.     switch (iMsg)
  41.         {
  42.         case WM_CREATE:
  43.             ppl=(PCPolyline)((LPCREATESTRUCT)lParam)->lpCreateParams;
  44.             SetWindowLong(hWnd, PLWL_STRUCTURE, (LONG)ppl);
  45.             ppl->m_hWnd=hWnd;
  46.             ppl->New();
  47.             break;
  48.  
  49.  
  50.         case WM_PAINT:
  51.             hDC=BeginPaint(hWnd, &ps);
  52.             ppl->Draw(hDC, FALSE, TRUE);
  53.             EndPaint(hWnd, &ps);
  54.             break;
  55.  
  56.  
  57.         case WM_LBUTTONDOWN:
  58.             //Stop if we are already at the limit.
  59.             if (CPOLYLINEPOINTS==ppl->m_pl.cPoints)
  60.                 {
  61.                 MessageBeep(0);
  62.                 break;
  63.                 }
  64.  
  65.             //Convert the points into 0-32767 range
  66.             GetClientRect(hWnd, &rc);
  67.             pt=MAKEPOINTS(lParam);
  68.             ppl->PointScale(&rc, &pt, FALSE);
  69.  
  70.             ppl->m_pl.rgpt[ppl->m_pl.cPoints++]=pt;
  71.  
  72.             //Draw the lines to this new point only.
  73.             hDC=GetDC(hWnd);
  74.             ppl->Draw(hDC, FALSE, FALSE);
  75.             ReleaseDC(hWnd, hDC);
  76.  
  77.             if (NULL!=ppl->m_pAdv)
  78.                 ppl->m_pAdv->OnPointChange();
  79.  
  80.             break;
  81.  
  82.  
  83.         default:
  84.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  85.         }
  86.  
  87.     return 0L;
  88.     }
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96. /*
  97.  * CPolyline::Draw
  98.  *
  99.  * Purpose:
  100.  *  Paints the current line in the polyline window.
  101.  *
  102.  * Parameters:
  103.  *  hDC             HDC to draw on, could be metafile or printer DC.
  104.  *  fMetafile       BOOL indicating if hDC is a metafile or not, so
  105.  *                  we can avoid operations that RIP.
  106.  *  fEntire         BOOL indicating if we should draw the entire
  107.  *                  figure or not.
  108.  *
  109.  * Return Value:
  110.  *  None
  111.  */
  112.  
  113. void CPolyline::Draw(HDC hDC, BOOL fMetafile, BOOL fEntire)
  114.     {
  115.     HBRUSH          hBrush;
  116.     HPEN            hPen;
  117.     HGDIOBJ         hObj1, hObj2;
  118.     UINT            i, j;
  119.     UINT            uMM;
  120.     POINTS          pt1, pt2;
  121.     POINT           rgpt[CPOLYLINEPOINTS];
  122.     RECT            rc;
  123.  
  124.     GetClientRect(m_hWnd, &rc);
  125.  
  126.     /*
  127.      * Make a 32-bit copy of the points in the POLYLINE itself
  128.      * so we can use DPtoLP and LPtoDP.
  129.      */
  130.     for (i=0; i < m_pl.cPoints; i++)
  131.         {
  132.         rgpt[i].x=m_pl.rgpt[i].x;
  133.         rgpt[i].y=m_pl.rgpt[i].y;
  134.         }
  135.  
  136.     /*
  137.      * If the mapping mode is not MM_TEXT, convert the points to
  138.      * whatever mapping mode in in effect before drawing.
  139.      * This specifically supports metafiles in MM_ANISOTROPIC.
  140.      */
  141.     uMM=fMetafile ? MM_TEXT : GetMapMode(hDC);
  142.  
  143.     if (MM_TEXT!=uMM)
  144.         DPtoLP(hDC, rgpt, m_pl.cPoints);
  145.  
  146.     hPen=CreatePen(m_pl.iLineStyle, 1, m_pl.rgbLine);
  147.     hObj1=SelectObject(hDC, hPen);
  148.  
  149.     hBrush=CreateSolidBrush(m_pl.rgbBackground);
  150.     hObj2=SelectObject(hDC, hBrush);
  151.     SetBkColor(hDC, m_pl.rgbBackground);
  152.  
  153.     /*
  154.      * Either draw the entire figure or just a single point.  The
  155.      * entire figure also includes erasing the background
  156.      * completely,since hDC may be a metafile DC.  Drawing a
  157.      * single point just updates the figure for that new point.
  158.      */
  159.     if (fEntire || 0==m_pl.cPoints)
  160.         {
  161.         //Erase the background for bitmaps and metafiles.
  162.         SelectObject(hDC, GetStockObject(NULL_PEN));
  163.         Rectangle(hDC, rc.left, rc.top, rc.right+1, rc.bottom+1);
  164.         SelectObject(hDC, hPen);
  165.  
  166.  
  167.         /*
  168.          * If we are drawing the entire figure, then loop through
  169.          * each point drawing a line to each successive point.
  170.          */
  171.  
  172.         for (i=0; i < m_pl.cPoints; i++)
  173.             {
  174.             for (j=i; j < m_pl.cPoints; j++)
  175.                 {
  176.                 /*
  177.                  * Not using POINTTOPOINTS since it unfortunately
  178.                  * returns a LONG which doesn't equate to a POINTS.
  179.                  */
  180.                 pt1.x=(short)rgpt[i].x;
  181.                 pt1.y=(short)rgpt[i].y;
  182.                 pt2.x=(short)rgpt[j].x;
  183.                 pt2.y=(short)rgpt[j].y;
  184.  
  185.                 PointScale(&rc, &pt1, TRUE);
  186.                 PointScale(&rc, &pt2, TRUE);
  187.                 MoveToEx(hDC, pt1.x, pt1.y, NULL);
  188.                 LineTo(hDC, pt2.x, pt2.y);
  189.                 }
  190.             }
  191.         }
  192.     else
  193.         {
  194.         /*
  195.          * If we are only drawing the last point, just cycle once
  196.          * through previous points.
  197.          */
  198.  
  199.         //Get the last point entered in the array.
  200.         j=m_pl.cPoints-1;
  201.         pt1.x=(short)rgpt[j].x;
  202.         pt1.y=(short)rgpt[j].y;
  203.         PointScale(&rc, &pt1, TRUE);
  204.  
  205.         for (i=0; i < j; i++)
  206.             {
  207.             pt2.x=(short)rgpt[i].x;
  208.             pt2.y=(short)rgpt[i].y;
  209.             PointScale(&rc, &pt2, TRUE);
  210.  
  211.             MoveToEx(hDC, pt1.x, pt1.y, NULL);
  212.             LineTo(hDC, pt2.x, pt2.y);
  213.             }
  214.         }
  215.  
  216.     //If we have one point, draw a dot to indicate it's position.
  217.     if (1==m_pl.cPoints)
  218.         {
  219.         pt1.x=(short)rgpt[0].x;
  220.         pt1.y=(short)rgpt[0].y;
  221.         PointScale(&rc, &pt1, TRUE);
  222.         SetPixel(hDC, pt1.x, pt1.y, m_pl.rgbLine);
  223.         }
  224.  
  225.     //Note:  m_pl.rgpt is unmodified in this code.
  226.  
  227.     SelectObject(hDC, hObj1);
  228.     SelectObject(hDC, hObj2);
  229.     DeleteObject(hBrush);
  230.     DeleteObject(hPen);
  231.     return;
  232.     }
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240. /*
  241.  * CPolyline::PointScale
  242.  *
  243.  * Purpose:
  244.  *  Scales a point to or from a relative window coordinate to a
  245.  *  0-32767 coordinate.
  246.  *
  247.  * Parameters:
  248.  *  pRect           LPRECT of the window.
  249.  *  ppt             LPPOINTS to convert
  250.  *  fScaleToWindow  BOOL indicating direction of scaling.
  251.  *
  252.  * Return Value:
  253.  *  None
  254.  */
  255.  
  256. void CPolyline::PointScale(LPRECT pRect, LPPOINTS ppt
  257.     , BOOL fScaleToWindow)
  258.     {
  259.     DWORD   cx, cy;
  260.  
  261.     //Window size
  262.     cx=(DWORD)(pRect->right-pRect->left);
  263.     cy=(DWORD)(pRect->bottom-pRect->top);
  264.  
  265.     //Prevent crashes
  266.     if (0L==cx) cx=1;
  267.     if (0L==cy) cy=1;
  268.  
  269.     //Must use DWORD to insure proper scaling.
  270.     if (fScaleToWindow)
  271.         {
  272.         ppt->x=(UINT)(((DWORD)ppt->x*cx) >> 15);
  273.         ppt->y=(UINT)(((DWORD)ppt->y*cy) >> 15);
  274.         }
  275.     else
  276.         {
  277.         ppt->x=(UINT)(((DWORD)ppt->x << 15)/cx);
  278.         ppt->y=(UINT)(((DWORD)ppt->y << 15)/cy);
  279.         }
  280.  
  281.     return;
  282.     }
  283.