POLYWIN.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

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