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 / chap08 / polyline / polywin.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  7KB  |  280 lines

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