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 / chap23 / polyline / polywin.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  15.2 KB  |  541 lines

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