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

  1. /*
  2.  * POLYWIN.CPP
  3.  * Polyline Component Chapter 24
  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.     COMMANDPARAMS(wID, wCode, hWndMsg);
  36.  
  37.     ppl=(PCPolyline)GetWindowLong(hWnd, PLWL_STRUCTURE);
  38.  
  39.     switch (iMsg)
  40.         {
  41.         case WM_CREATE:
  42.             ppl=(PCPolyline)((LPCREATESTRUCT)lParam)->lpCreateParams;
  43.             SetWindowLong(hWnd, PLWL_STRUCTURE, (LONG)ppl);
  44.             ppl->m_hWnd=hWnd;
  45.             break;
  46.  
  47.  
  48.         case WM_PAINT:
  49.             hDC=BeginPaint(hWnd, &ps);
  50.             GetClientRect(hWnd, &rc);
  51.             ppl->Draw(hDC, FALSE, TRUE, &rc, NULL);
  52.             EndPaint(hWnd, &ps);
  53.             break;
  54.  
  55.  
  56.         case WM_LBUTTONDOWN:
  57.             //CHAPTER24MOD
  58.             //If the UI is dead, we ignore all mouse clicks.
  59.             if (ppl->m_fUIDead)
  60.                 break;
  61.             //End CHAPTER24MOD
  62.  
  63.             //We become UI Active with mouse action
  64.             if (!ppl->m_fUIActive && NULL!=ppl->m_pIOleIPSite)
  65.                 ppl->UIActivate();
  66.  
  67.             //Stop if we are already at the limit.
  68.             if (CPOLYLINEPOINTS==ppl->m_pl.cPoints)
  69.                 {
  70.                 MessageBeep(0);
  71.                 break;
  72.                 }
  73.  
  74.             //Convert the points into 0-32767 range
  75.             GetClientRect(hWnd, &rc);
  76.             pt=MAKEPOINTS(lParam);
  77.             ppl->PointScale(&rc, &pt, FALSE);
  78.  
  79.             ppl->m_pl.rgpt[ppl->m_pl.cPoints++]=pt;
  80.  
  81.             //Draw the lines to this new point only.
  82.             hDC=GetDC(hWnd);
  83.             ppl->Draw(hDC, FALSE, FALSE, &rc, NULL);
  84.             ReleaseDC(hWnd, hDC);
  85.  
  86.             if (NULL!=ppl->m_pAdv)
  87.                 ppl->m_pAdv->OnPointChange();
  88.  
  89.             ppl->SendAdvise(OBJECTCODE_DATACHANGED);
  90.             break;
  91.  
  92.  
  93.         case WM_COMMAND:
  94.             //CHAPTER24MOD
  95.             //Ignore Open commands when we're UIDead
  96.             if (ppl->m_fUIDead)
  97.                 break;
  98.             //End CHAPTER24MOD
  99.  
  100.             if (ID_HATCHWINDOW==wID
  101.                 && HWN_BORDERDOUBLECLICKED==wCode)
  102.                 {
  103.                 ppl->m_pImpIOleObject->DoVerb(OLEIVERB_OPEN, NULL
  104.                     , ppl->m_pIOleClientSite, -1, NULL, NULL);
  105.                 }
  106.             break;
  107.  
  108.         default:
  109.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  110.         }
  111.  
  112.     return 0L;
  113.     }
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121. /*
  122.  * CPolyline::Draw
  123.  *
  124.  * Purpose:
  125.  *  Paints the current line in the polyline window.
  126.  *
  127.  * Parameters:
  128.  *  hDC             HDC to draw on, a metafile or printer DC.
  129.  *  fMetafile       BOOL indicating if hDC is a metafile or not,
  130.  *                  so we can avoid operations that RIP.
  131.  *  fEntire         BOOL indicating if we should draw the entire
  132.  *                  figure or not.
  133.  *  pRect           LPRECT defining the bounds in which to draw.
  134.  *  ppl             PPOLYLINEDATA to draw.  If NULL, use current.
  135.  *
  136.  * Return Value:
  137.  *  None
  138.  */
  139.  
  140. void CPolyline::Draw(HDC hDC, BOOL fMetafile, BOOL fEntire
  141.     , LPRECT pRect, PPOLYLINEDATA ppl)
  142.     {
  143.     HBRUSH          hBrush;
  144.     HPEN            hPen;
  145.     HGDIOBJ         hObj1, hObj2;
  146.     UINT            i, j;
  147.     int             nDC;
  148.     POINTS          pt1,pt2;
  149.     POINT           rgpt[CPOLYLINEPOINTS];
  150.  
  151.     if (NULL==ppl)
  152.         ppl=&m_pl;
  153.  
  154.     nDC=SaveDC(hDC);
  155.  
  156.     for (i=0; i < ppl->cPoints; i++)
  157.         {
  158.         rgpt[i].x=ppl->rgpt[i].x;
  159.         rgpt[i].y=ppl->rgpt[i].y;
  160.         }
  161.  
  162.     //Printer and frozen differences handled in IViewObject::Draw
  163.  
  164.     hPen=CreatePen(ppl->iLineStyle, 1, ppl->rgbLine);
  165.     hObj1=SelectObject(hDC, hPen);
  166.  
  167.     hBrush=CreateSolidBrush(ppl->rgbBackground);
  168.     hObj2=SelectObject(hDC, hBrush);
  169.     SetBkColor(hDC, ppl->rgbBackground);
  170.  
  171.     /*
  172.      * Either draw the entire figure or just a single point.  The
  173.      * entire figure also includes erasing the background completely,
  174.      * since hDC may be a metafile DC.  Drawing a single point just
  175.      * updates the figure for that new point.
  176.      */
  177.     if (fEntire || 0==ppl->cPoints)
  178.         {
  179.         //Erase the background for bitmaps and metafiles.
  180.         SelectObject(hDC, GetStockObject(NULL_PEN));
  181.         Rectangle(hDC, pRect->left, pRect->top, pRect->right+1
  182.             , pRect->bottom+1);
  183.         SelectObject(hDC, hPen);
  184.  
  185.         /*
  186.          * If we are drawing the entire figure, then loop through
  187.          * each point drawing a line to each successive point.
  188.          */
  189.  
  190.         for (i=0; i < ppl->cPoints; i++)
  191.             {
  192.             for (j=i; j < ppl->cPoints; j++)
  193.                 {
  194.                 pt1.x=(short)rgpt[i].x;
  195.                 pt1.y=(short)rgpt[i].y;
  196.                 pt2.x=(short)rgpt[j].x;
  197.                 pt2.y=(short)rgpt[j].y;
  198.  
  199.                 PointScale(pRect, &pt1, TRUE);
  200.                 PointScale(pRect, &pt2, TRUE);
  201.                 MoveToEx(hDC, pt1.x, pt1.y, NULL);
  202.                 LineTo(hDC, pt2.x, pt2.y);
  203.                 }
  204.             }
  205.         }
  206.     else
  207.         {
  208.         /*
  209.          * If we are only drawing the last point, just cycle once
  210.          * through previous points.
  211.          */
  212.  
  213.         //Get the last point entered in the array.
  214.         j=ppl->cPoints-1;
  215.         pt1.x=(short)rgpt[j].x;
  216.         pt1.y=(short)rgpt[j].y;
  217.         PointScale(pRect, &pt1, TRUE);
  218.  
  219.         for (i=0; i < j; i++)
  220.             {
  221.             pt2.x=(short)rgpt[i].x;
  222.             pt2.y=(short)rgpt[i].y;
  223.             PointScale(pRect, &pt2, TRUE);
  224.  
  225.             MoveToEx(hDC, pt1.x, pt1.y, NULL);
  226.             LineTo(hDC, pt2.x, pt2.y);
  227.             }
  228.         }
  229.  
  230.     //If we have one point, draw a dot to indicate it's position.
  231.     if (1==ppl->cPoints)
  232.         {
  233.         pt1.x=(short)rgpt[0].x;
  234.         pt1.y=(short)rgpt[0].y;
  235.         PointScale(pRect, &pt1, TRUE);
  236.         SetPixel(hDC, pt1.x, pt1.y, m_pl.rgbLine);
  237.         }
  238.  
  239.     SelectObject(hDC, hObj1);
  240.     SelectObject(hDC, hObj2);
  241.     DeleteObject(hBrush);
  242.     DeleteObject(hPen);
  243.  
  244.     RestoreDC(hDC, nDC);
  245.     return;
  246.     }
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254. /*
  255.  * CPolyline::PointScale
  256.  *
  257.  * Purpose:
  258.  *  Scales a point to or from a relative window coordinate to a
  259.  *  0-32767 coordinate.
  260.  *
  261.  * Parameters:
  262.  *  pRect           LPRECT of the window.
  263.  *  ppt             LPPOINTS to convert
  264.  *  fScaleToWindow  BOOL indicating direction of scaling.
  265.  *
  266.  * Return Value:
  267.  *  None
  268.  */
  269.  
  270. void CPolyline::PointScale(LPRECT pRect, LPPOINTS ppt
  271.     , BOOL fScaleToWindow)
  272.     {
  273.     DWORD   cx, cy;
  274.  
  275.     //Window size
  276.     cx=(DWORD)(pRect->right-pRect->left);
  277.     cy=(DWORD)(pRect->bottom-pRect->top);
  278.  
  279.     //Prevent crashes
  280.     if (0L==cx) cx=1;
  281.     if (0L==cy) cy=1;
  282.  
  283.     //Must use DWORD to insure proper scaling.
  284.  
  285.     /*
  286.      * As an in-proc server we may not have a rectangle where the
  287.      * top left was (0,0) which was always true when we drew to
  288.      * a Polyline window.  But this may be a container's hDC in
  289.      * which case we'd better place the points in the container's
  290.      * rectangle.  That is, we have to add/subtract pRect->left
  291.      * and ->top in these calculations.
  292.      */
  293.  
  294.     if (fScaleToWindow)
  295.         {
  296.         ppt->x=pRect->left+(UINT)(((DWORD)ppt->x*cx) >> 15);
  297.         ppt->y=pRect->top+(UINT)(((DWORD)ppt->y*cy)  >> 15);
  298.         }
  299.     else
  300.         {
  301.         ppt->x=(UINT)(((DWORD)(ppt->x - pRect->left) << 15)/cx);
  302.         ppt->y=(UINT)(((DWORD)(ppt->y - pRect->top)  << 15)/cy);
  303.         }
  304.  
  305.     return;
  306.     }
  307.  
  308.  
  309.  
  310. /*
  311.  * PolyDlgProc
  312.  *
  313.  * Purpose:
  314.  *  Dialog procedure for a window in which to display the Polyline
  315.  *  for editing.  This pretty much handles all editing functionality
  316.  *  for the embedded object.
  317.  */
  318.  
  319. BOOL APIENTRY PolyDlgProc(HWND hDlg, UINT iMsg
  320.     , WPARAM wParam, LPARAM lParam)
  321.     {
  322.     PCPolyline      ppl=NULL;
  323.     RECT            rc;
  324.     UINT            uID, uTemp;
  325.     UINT            cx, cy;
  326.  
  327.    #ifdef WIN32
  328.     ppl=(PCPolyline)GetProp(hDlg, PROP_POINTER);
  329.    #else
  330.     WORD            w1, w2;
  331.  
  332.     w1=(WORD)GetProp(hDlg, PROP_SELECTOR);
  333.     w2=(WORD)GetProp(hDlg, PROP_OFFSET);
  334.  
  335.     ppl=(PCPolyline)MAKELP(w1, w2);
  336.    #endif
  337.  
  338.     switch (iMsg)
  339.         {
  340.         case WM_INITDIALOG:
  341.             ppl=(PCPolyline)lParam;
  342.             ppl->m_hDlg=hDlg;
  343.  
  344.            #ifdef WIN32
  345.             //Properties are 32-bits in Win32
  346.             SetProp(hDlg, PROP_POINTER, (HANDLE)ppl);
  347.            #else
  348.             SetProp(hDlg, PROP_SELECTOR, (HANDLE)SELECTOROF(ppl));
  349.             SetProp(hDlg, PROP_OFFSET,   (HANDLE)OFFSETOF(ppl));
  350.            #endif
  351.  
  352.             //Get the rectangle that Polyline occupies
  353.             CalcPolyRectInDialog(hDlg, &rc);
  354.  
  355.             //Try to create the window.
  356.             ppl->m_pImpIPolyline->Init(hDlg, &rc, WS_CHILD | WS_VISIBLE
  357.                 , ID_POLYLINE);
  358.  
  359.             //Set the initial line style radiobutton.
  360.             ppl->m_pImpIPolyline->LineStyleGet(&uTemp);
  361.             CheckRadioButton(hDlg, ID_LINESOLID, ID_LINEDASHDOTDOT
  362.                 , uTemp+ID_LINEMIN);
  363.  
  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.                         HRESULT     hr;
  395.  
  396.                         /*
  397.                          * Instead of just closing, see if we can
  398.                          * activate in-place again--we know we're an
  399.                          * inside out object and want to be activated
  400.                          * when we can be.  If we can't activate
  401.                          * in-place, then close like we normally
  402.                          * would.  Note that this makes sense only
  403.                          * with an inside-out supporting container,
  404.                          * which we determine from whether it ever
  405.                          * used OLEIVERB_INPLACEACTIVATE.
  406.                          */
  407.  
  408.                         hr=ResultFromScode(E_FAIL);
  409.  
  410.                         if (ppl->m_fContainerKnowsInsideOut)
  411.                             {
  412.                             hr=ppl->InPlaceActivate
  413.                                 (ppl->m_pIOleClientSite, FALSE);
  414.                             }
  415.  
  416.                         if (FAILED(hr))
  417.                             {
  418.                             ppl->m_pImpIOleObject->Close
  419.                                 (OLECLOSE_SAVEIFDIRTY);
  420.                             }
  421.                         }
  422.  
  423.                     break;
  424.  
  425.                 case ID_UNDO:
  426.                     if (NULL!=ppl)
  427.                         ppl->m_pImpIPolyline->Undo();
  428.                     break;
  429.  
  430.                 case ID_COLORLINE:
  431.                 case ID_COLORBACK:
  432.                     if (NULL!=ppl)
  433.                         {
  434.                         UINT            i;
  435.                         COLORREF        rgColors[16];
  436.                         CHOOSECOLOR     cc;
  437.  
  438.                         //Invoke the color chooser for either color
  439.                         uTemp=(ID_COLORBACK==uID)
  440.                             ? POLYLINECOLOR_BACKGROUND
  441.                             : POLYLINECOLOR_LINE;
  442.  
  443.                         for (i=0; i<16; i++)
  444.                             rgColors[i]=RGB(0, 0, i*16);
  445.  
  446.                         memset(&cc, 0, sizeof(CHOOSECOLOR));
  447.                         cc.lStructSize=sizeof(CHOOSECOLOR);
  448.                         cc.lpCustColors=rgColors;
  449.                         cc.hwndOwner=hDlg;
  450.                         cc.Flags=CC_RGBINIT;
  451.                         ppl->m_pImpIPolyline->ColorGet(uTemp
  452.                             , &cc.rgbResult);
  453.  
  454.                         if (ChooseColor(&cc))
  455.                             {
  456.                             //rgColor is just some COLORREF pointer
  457.                             ppl->m_pImpIPolyline->ColorSet(uTemp
  458.                                 , cc.rgbResult, rgColors);
  459.                             }
  460.                         }
  461.                     break;
  462.  
  463.                 case ID_LINESOLID:
  464.                 case ID_LINEDASH:
  465.                 case ID_LINEDOT:
  466.                 case ID_LINEDASHDOT:
  467.                 case ID_LINEDASHDOTDOT:
  468.                     if (NULL!=ppl)
  469.                         {
  470.                         ppl->m_pImpIPolyline
  471.                             ->LineStyleSet(uID-ID_LINEMIN, &uTemp);
  472.                         }
  473.  
  474.                     break;
  475.                 }
  476.             break;
  477.  
  478.         case WM_DESTROY:
  479.            #ifdef WIN32
  480.             RemoveProp(hDlg, PROP_POINTER);
  481.            #else
  482.             RemoveProp(hDlg, PROP_SELECTOR);
  483.             RemoveProp(hDlg, PROP_OFFSET);
  484.            #endif
  485.             break;
  486.  
  487.         case WM_CLOSE:
  488.             //This will do the IDOK handling, then send POLYM_CLOSE
  489.             SendCommand(hDlg, IDOK, 0, NULL);
  490.             break;
  491.  
  492.         case POLYM_CLOSE:
  493.             ShowWindow(hDlg, SW_HIDE);
  494.             ppl->SendAdvise(OBJECTCODE_HIDEWINDOW);
  495.             break;
  496.         }
  497.  
  498.     return FALSE;
  499.     }
  500.  
  501.  
  502.  
  503. /*
  504.  * CalcPolyRectInDialog
  505.  *
  506.  * Purpose:
  507.  *  Calculates the rectangle that the Polyline should occupy in the
  508.  *  dialog box.  This is separated for in-place handling because
  509.  *  when we open the dialog from an in-place active situation we
  510.  *  have to move the Polyline window from the container into the
  511.  *  dialog and position it properly.
  512.  *
  513.  * Parameters:
  514.  *  hDlg            HWND of the dialog.
  515.  *  prc             LPRECT in which to store the rectangle.
  516.  *
  517.  * Return Value:
  518.  *  None
  519.  */
  520.  
  521. void CalcPolyRectInDialog(HWND hDlg, LPRECT prc)
  522.     {
  523.     HWND        hWnd;
  524.     POINT       pt;
  525.  
  526.     hWnd=GetDlgItem(hDlg, ID_POLYLINERECT);
  527.     GetWindowRect(hWnd, prc);
  528.     SETPOINT(pt, prc->left, prc->top);
  529.     ScreenToClient(hDlg, &pt);
  530.  
  531.     //Set the polyline just within the black frame
  532.     SetRect(prc, pt.x, pt.y, pt.x+(prc->right-prc->left)
  533.         , pt.y+(prc->bottom-prc->top));
  534.     InflateRect(prc, -1, -1);
  535.     return;
  536.     }
  537.