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

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