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

  1. /*
  2.  * POLYWIN.CPP
  3.  * Polyline Component Chapter 21
  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.             ppl->m_hWnd=hWnd;
  43.             break;
  44.  
  45.  
  46.         case WM_PAINT:
  47.             hDC=BeginPaint(hWnd, &ps);
  48.             GetClientRect(hWnd, &rc);
  49.             ppl->Draw(hDC, FALSE, TRUE, &rc, NULL);
  50.             EndPaint(hWnd, &ps);
  51.             break;
  52.  
  53.  
  54.         case WM_LBUTTONDOWN:
  55.             //Stop if we are already at the limit.
  56.             if (CPOLYLINEPOINTS==ppl->m_pl.cPoints)
  57.                 {
  58.                 MessageBeep(0);
  59.                 break;
  60.                 }
  61.  
  62.             //Convert the points into 0-32767 range
  63.             GetClientRect(hWnd, &rc);
  64.             pt=MAKEPOINTS(lParam);
  65.             ppl->PointScale(&rc, &pt, FALSE);
  66.  
  67.             ppl->m_pl.rgpt[ppl->m_pl.cPoints++]=pt;
  68.  
  69.             //Draw the lines to this new point only.
  70.             hDC=GetDC(hWnd);
  71.             ppl->Draw(hDC, FALSE, FALSE, &rc, NULL);
  72.             ReleaseDC(hWnd, hDC);
  73.  
  74.             if (NULL!=ppl->m_pAdv)
  75.                 ppl->m_pAdv->OnPointChange();
  76.  
  77.             ppl->SendAdvise(OBJECTCODE_DATACHANGED);
  78.             break;
  79.  
  80.  
  81.         default:
  82.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  83.         }
  84.  
  85.     return 0L;
  86.     }
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94. /*
  95.  * CPolyline::Draw
  96.  *
  97.  * Purpose:
  98.  *  Paints the current line in the polyline window.
  99.  *
  100.  * Parameters:
  101.  *  hDC             HDC to draw on, a metafile or printer DC.
  102.  *  fMetafile       BOOL indicating if hDC is a metafile or not,
  103.  *                  so we can avoid operations that RIP.
  104.  *  fEntire         BOOL indicating if we should draw the entire
  105.  *                  figure or not.
  106.  *  pRect           LPRECT defining the bounds in which to draw.
  107.  *  ppl             PPOLYLINEDATA to draw.  If NULL, use current.
  108.  *
  109.  * Return Value:
  110.  *  None
  111.  */
  112.  
  113. void CPolyline::Draw(HDC hDC, BOOL fMetafile, BOOL fEntire
  114.     , LPRECT pRect, PPOLYLINEDATA ppl)
  115.     {
  116.     HBRUSH          hBrush;
  117.     HPEN            hPen;
  118.     HGDIOBJ         hObj1, hObj2;
  119.     UINT            i, j;
  120.     int             nDC;
  121.     POINTS          pt1,pt2;
  122.     POINT           rgpt[CPOLYLINEPOINTS];
  123.  
  124.     if (NULL==ppl)
  125.         ppl=&m_pl;
  126.  
  127.     nDC=SaveDC(hDC);
  128.  
  129.     for (i=0; i < ppl->cPoints; i++)
  130.         {
  131.         rgpt[i].x=ppl->rgpt[i].x;
  132.         rgpt[i].y=ppl->rgpt[i].y;
  133.         }
  134.  
  135.     //Printer and frozen differences handled in IViewObject::Draw
  136.  
  137.     hPen=CreatePen(ppl->iLineStyle, 1, ppl->rgbLine);
  138.     hObj1=SelectObject(hDC, hPen);
  139.  
  140.     hBrush=CreateSolidBrush(ppl->rgbBackground);
  141.     hObj2=SelectObject(hDC, hBrush);
  142.     SetBkColor(hDC, ppl->rgbBackground);
  143.  
  144.     /*
  145.      * Either draw the entire figure or just a single point.  The
  146.      * entire figure also includes erasing the background completely,
  147.      * since hDC may be a metafile DC.  Drawing a single point just
  148.      * updates the figure for that new point.
  149.      */
  150.     if (fEntire || 0==ppl->cPoints)
  151.         {
  152.         //Erase the background for bitmaps and metafiles.
  153.         SelectObject(hDC, GetStockObject(NULL_PEN));
  154.         Rectangle(hDC, pRect->left, pRect->top, pRect->right+1
  155.             , pRect->bottom+1);
  156.         SelectObject(hDC, hPen);
  157.  
  158.         /*
  159.          * If we are drawing the entire figure, then loop through
  160.          * each point drawing a line to each successive point.
  161.          */
  162.  
  163.         for (i=0; i < ppl->cPoints; i++)
  164.             {
  165.             for (j=i; j < ppl->cPoints; j++)
  166.                 {
  167.                 pt1.x=(short)rgpt[i].x;
  168.                 pt1.y=(short)rgpt[i].y;
  169.                 pt2.x=(short)rgpt[j].x;
  170.                 pt2.y=(short)rgpt[j].y;
  171.  
  172.                 PointScale(pRect, &pt1, TRUE);
  173.                 PointScale(pRect, &pt2, TRUE);
  174.                 MoveToEx(hDC, pt1.x, pt1.y, NULL);
  175.                 LineTo(hDC, pt2.x, pt2.y);
  176.                 }
  177.             }
  178.         }
  179.     else
  180.         {
  181.         /*
  182.          * If we are only drawing the last point, just cycle once
  183.          * through previous points.
  184.          */
  185.  
  186.         //Get the last point entered in the array.
  187.         j=ppl->cPoints-1;
  188.         pt1.x=(short)rgpt[j].x;
  189.         pt1.y=(short)rgpt[j].y;
  190.         PointScale(pRect, &pt1, TRUE);
  191.  
  192.         for (i=0; i < j; i++)
  193.             {
  194.             pt2.x=(short)rgpt[i].x;
  195.             pt2.y=(short)rgpt[i].y;
  196.             PointScale(pRect, &pt2, TRUE);
  197.  
  198.             MoveToEx(hDC, pt1.x, pt1.y, NULL);
  199.             LineTo(hDC, pt2.x, pt2.y);
  200.             }
  201.         }
  202.  
  203.     //If we have one point, draw a dot to indicate it's position.
  204.     if (1==ppl->cPoints)
  205.         {
  206.         pt1.x=(short)rgpt[0].x;
  207.         pt1.y=(short)rgpt[0].y;
  208.         PointScale(pRect, &pt1, TRUE);
  209.         SetPixel(hDC, pt1.x, pt1.y, m_pl.rgbLine);
  210.         }
  211.  
  212.     SelectObject(hDC, hObj1);
  213.     SelectObject(hDC, hObj2);
  214.     DeleteObject(hBrush);
  215.     DeleteObject(hPen);
  216.  
  217.     RestoreDC(hDC, nDC);
  218.     return;
  219.     }
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227. /*
  228.  * CPolyline::PointScale
  229.  *
  230.  * Purpose:
  231.  *  Scales a point to or from a relative window coordinate to a
  232.  *  0-32767 coordinate.
  233.  *
  234.  * Parameters:
  235.  *  pRect           LPRECT of the window.
  236.  *  ppt             LPPOINTS to convert
  237.  *  fScaleToWindow  BOOL indicating direction of scaling.
  238.  *
  239.  * Return Value:
  240.  *  None
  241.  */
  242.  
  243. void CPolyline::PointScale(LPRECT pRect, LPPOINTS ppt
  244.     , BOOL fScaleToWindow)
  245.     {
  246.     DWORD   cx, cy;
  247.  
  248.     //Window size
  249.     cx=(DWORD)(pRect->right-pRect->left);
  250.     cy=(DWORD)(pRect->bottom-pRect->top);
  251.  
  252.     //Prevent crashes
  253.     if (0L==cx) cx=1;
  254.     if (0L==cy) cy=1;
  255.  
  256.     //Must use DWORD to insure proper scaling.
  257.  
  258.     /*
  259.      * As an in-proc server we may not have a rectangle where the
  260.      * top left was (0,0) which was always true when we drew to
  261.      * a Polyline window.  But this may be a container's hDC in
  262.      * which case we'd better place the points in the container's
  263.      * rectangle.  That is, we have to add/subtract pRect->left
  264.      * and ->top in these calculations.
  265.      */
  266.  
  267.     if (fScaleToWindow)
  268.         {
  269.         ppt->x=pRect->left+(UINT)(((DWORD)ppt->x*cx) >> 15);
  270.         ppt->y=pRect->top+(UINT)(((DWORD)ppt->y*cy)  >> 15);
  271.         }
  272.     else
  273.         {
  274.         ppt->x=(UINT)(((DWORD)(ppt->x - pRect->left) << 15)/cx);
  275.         ppt->y=(UINT)(((DWORD)(ppt->y - pRect->top)  << 15)/cy);
  276.         }
  277.  
  278.     return;
  279.     }
  280.  
  281.  
  282.  
  283. /*
  284.  * PolyDlgProc
  285.  *
  286.  * Purpose:
  287.  *  Dialog procedure for a window in which to display the Polyline
  288.  *  for editing.  This pretty much handles all editing functionality
  289.  *  for the embedded object.
  290.  */
  291.  
  292. BOOL APIENTRY PolyDlgProc(HWND hDlg, UINT iMsg
  293.     , WPARAM wParam, LPARAM lParam)
  294.     {
  295.     PCPolyline      ppl=NULL;
  296.     HWND            hWnd;
  297.     RECT            rc;
  298.     POINT           pt;
  299.     UINT            uID, uTemp;
  300.     UINT            cx, cy;
  301.  
  302.    #ifdef WIN32
  303.     ppl=(PCPolyline)GetProp(hDlg, PROP_POINTER);
  304.    #else
  305.     WORD            w1, w2;
  306.  
  307.     w1=(WORD)GetProp(hDlg, PROP_SELECTOR);
  308.     w2=(WORD)GetProp(hDlg, PROP_OFFSET);
  309.  
  310.     ppl=(PCPolyline)MAKELP(w1, w2);
  311.    #endif
  312.  
  313.     switch (iMsg)
  314.         {
  315.         case WM_INITDIALOG:
  316.             ppl=(PCPolyline)lParam;
  317.             ppl->m_hDlg=hDlg;
  318.  
  319.            #ifdef WIN32
  320.             //Properties are 32-bits in Win32
  321.             SetProp(hDlg, PROP_POINTER, (HANDLE)ppl);
  322.            #else
  323.             SetProp(hDlg, PROP_SELECTOR, (HANDLE)SELECTOROF(ppl));
  324.             SetProp(hDlg, PROP_OFFSET,   (HANDLE)OFFSETOF(ppl));
  325.            #endif
  326.  
  327.             //Create the Polyline to exactly cover the static rect.
  328.             hWnd=GetDlgItem(hDlg, ID_POLYLINERECT);
  329.             GetWindowRect(hWnd, &rc);
  330.             SETPOINT(pt, rc.left, rc.top);
  331.             ScreenToClient(hDlg, &pt);
  332.  
  333.             //Set the polyline just within the black frame
  334.             SetRect(&rc, pt.x, pt.y, pt.x+(rc.right-rc.left)
  335.                 , pt.y+(rc.bottom-rc.top));
  336.             InflateRect(&rc, -1, -1);
  337.  
  338.             //Try to create the window.
  339.             ppl->m_pImpIPolyline->Init(hDlg, &rc, WS_CHILD | WS_VISIBLE
  340.                 , ID_POLYLINE);
  341.  
  342.             //Set the initial line style radiobutton.
  343.             ppl->m_pImpIPolyline->LineStyleGet(&uTemp);
  344.             CheckRadioButton(hDlg, ID_LINESOLID, ID_LINEDASHDOTDOT
  345.                 , uTemp+ID_LINEMIN);
  346.  
  347.             //Don't set focus--it takes it away from the container.
  348.             return FALSE;
  349.  
  350.  
  351.         case WM_SHOWWINDOW:
  352.             if (LOWORD(wParam))
  353.                 {
  354.                 //Center the dialog on the screen
  355.                 cx=GetSystemMetrics(SM_CXSCREEN);
  356.                 cy=GetSystemMetrics(SM_CYSCREEN);
  357.                 GetWindowRect(hDlg, &rc);
  358.                 SetWindowPos(hDlg, NULL, (cx-(rc.right-rc.left))/2
  359.                     , (cy-(rc.bottom-rc.top))/2, 0, 0, SWP_NOZORDER
  360.                     | SWP_NOSIZE);
  361.  
  362.                 //We didn't SetFocus from WM_INITDIALOG.  Do it now.
  363.                 SetFocus(GetDlgItem(hDlg, IDOK));
  364.                 }
  365.  
  366.             break;
  367.  
  368.  
  369.         case WM_COMMAND:
  370.             uID=LOWORD(wParam);
  371.  
  372.             switch (uID)
  373.                 {
  374.                 case IDOK:
  375.                     //Close the dialog, but save first.
  376.                     if (NULL!=ppl)
  377.                         {
  378.                         //IOleObject::Close does what we want
  379.                         ppl->m_pImpIOleObject->Close
  380.                             (OLECLOSE_SAVEIFDIRTY);
  381.                         }
  382.  
  383.                     break;
  384.  
  385.                 case ID_UNDO:
  386.                     if (NULL!=ppl)
  387.                         ppl->m_pImpIPolyline->Undo();
  388.                     break;
  389.  
  390.                 case ID_COLORLINE:
  391.                 case ID_COLORBACK:
  392.                     if (NULL!=ppl)
  393.                         {
  394.                         UINT            i;
  395.                         COLORREF        rgColors[16];
  396.                         CHOOSECOLOR     cc;
  397.  
  398.                         //Invoke the color chooser for either color
  399.                         uTemp=(ID_COLORBACK==uID)
  400.                             ? POLYLINECOLOR_BACKGROUND
  401.                             : POLYLINECOLOR_LINE;
  402.  
  403.                         for (i=0; i<16; i++)
  404.                             rgColors[i]=RGB(0, 0, i*16);
  405.  
  406.                         memset(&cc, 0, sizeof(CHOOSECOLOR));
  407.                         cc.lStructSize=sizeof(CHOOSECOLOR);
  408.                         cc.lpCustColors=rgColors;
  409.                         cc.hwndOwner=hDlg;
  410.                         cc.Flags=CC_RGBINIT;
  411.                         ppl->m_pImpIPolyline->ColorGet(uTemp
  412.                             , &cc.rgbResult);
  413.  
  414.                         if (ChooseColor(&cc))
  415.                             {
  416.                             //rgColor is just some COLORREF pointer
  417.                             ppl->m_pImpIPolyline->ColorSet(uTemp
  418.                                 , cc.rgbResult, rgColors);
  419.                             }
  420.                         }
  421.                     break;
  422.  
  423.                 case ID_LINESOLID:
  424.                 case ID_LINEDASH:
  425.                 case ID_LINEDOT:
  426.                 case ID_LINEDASHDOT:
  427.                 case ID_LINEDASHDOTDOT:
  428.                     if (NULL!=ppl)
  429.                         {
  430.                         ppl->m_pImpIPolyline
  431.                             ->LineStyleSet(uID-ID_LINEMIN, &uTemp);
  432.                         }
  433.  
  434.                     break;
  435.                 }
  436.             break;
  437.  
  438.         case WM_DESTROY:
  439.            #ifdef WIN32
  440.             RemoveProp(hDlg, PROP_POINTER);
  441.            #else
  442.             RemoveProp(hDlg, PROP_SELECTOR);
  443.             RemoveProp(hDlg, PROP_OFFSET);
  444.            #endif
  445.             break;
  446.  
  447.         case WM_CLOSE:
  448.             //This will do the IDOK handling, then send POLYM_CLOSE
  449.             SendCommand(hDlg, IDOK, 0, NULL);
  450.             break;
  451.  
  452.         case POLYM_CLOSE:
  453.             ShowWindow(hDlg, SW_HIDE);
  454.             ppl->SendAdvise(OBJECTCODE_HIDEWINDOW);
  455.             break;
  456.         }
  457.  
  458.     return FALSE;
  459.     }
  460.