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

Windows编程

开发平台:

Visual C++

  1. /*** 
  2. *CPoly.cpp
  3. *
  4. *  This is a part of the Microsoft Source Code Samples.
  5. *
  6. *  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  7. *
  8. *  This source code is only intended as a supplement to Microsoft Development
  9. *  Tools and/or WinHelp documentation.  See these sources for detailed
  10. *  information regarding the Microsoft samples programs.
  11. *
  12. *Purpose:
  13. *  This module implements the CPoly and CPolyCF classes.
  14. *
  15. *  This module is intended as a sample implementation of the IDispatch
  16. *  interface, and its purpose is to demonstrate how an object can
  17. *  expose methods and properties for programatic and cross-process
  18. *  access via the IDispatch interface.
  19. *
  20. *Implementation Notes:
  21. *
  22. *****************************************************************************/
  23. #include "spoly.h"
  24. #include "cpoint.h"
  25. #include "cpoly.h"
  26. #include "cenumpt.h"
  27. #ifndef _MAC
  28. extern CStatBar FAR* g_psb;
  29. #else
  30. extern "C" WindowPtr g_pwndClient;
  31. #endif
  32. extern unsigned int g_fQuit;
  33. // our global list of polygons.
  34. //
  35. POLYLINK FAR* g_ppolylink = (POLYLINK FAR*)NULL;
  36. // global count of polygons.
  37. //
  38. int g_cPoly = 0;
  39. CPoly::CPoly()
  40. {
  41.     m_refs = 0;
  42.     m_xorg = 0;
  43.     m_yorg = 0;
  44.     m_width = 0;
  45.     m_cPoints = 0;
  46.     m_red   = 0;
  47.     m_green = 0;
  48.     m_blue  = 0;
  49.     m_ppointlink = NULL;
  50.     m_ppointlinkLast = NULL;
  51. }
  52. /***
  53. *CPoly *CPoly::Create(void)
  54. *Purpose:
  55. *  Create an instance of a CPoly object, and add it to the global
  56. *  list of polygons.
  57. *
  58. *Entry:
  59. *  None
  60. *
  61. *Exit:
  62. *  returns a polygon object, NULL the allocation failed.
  63. *
  64. ***********************************************************************/
  65. CPoly FAR*
  66. CPoly::Create()
  67. {
  68.     CPoly FAR* ppoly;
  69.     POLYLINK FAR* ppolylink;
  70.     if((ppolylink = new FAR POLYLINK) == (POLYLINK FAR*)NULL)
  71.       return (CPoly FAR*)NULL;
  72.     if((ppoly = new FAR CPoly()) == (CPoly FAR*)NULL)
  73.       return (CPoly FAR*)NULL;
  74.     ppoly->AddRef();
  75.     // push the new polygon onto the front of the polygon list.
  76.     //
  77.     ++g_cPoly;
  78.     ppolylink->ppoly = ppoly;
  79.     ppolylink->next = g_ppolylink;
  80.     g_ppolylink = ppolylink;
  81. #ifndef _MAC
  82.     SBprintf(g_psb, TSTR("#poly = %d"), g_cPoly);
  83. #endif
  84.     IncObjectCount();
  85.     return ppoly;
  86. }
  87. //---------------------------------------------------------------------
  88. //                     IUnknown Methods
  89. //---------------------------------------------------------------------
  90. STDMETHODIMP
  91. CPoly::QueryInterface(REFIID riid, void FAR* FAR* ppv)
  92. {
  93.     if(IsEqualIID(riid, IID_IUnknown) ||
  94.        IsEqualIID(riid, IID_IDispatch)) {
  95.       *ppv = this;
  96.       AddRef();
  97.       return NOERROR;       
  98.     }
  99.        
  100.     *ppv = NULL;
  101.     return E_NOINTERFACE;
  102. }
  103. STDMETHODIMP_(unsigned long)
  104. CPoly::AddRef()
  105. {
  106.     return ++m_refs;
  107. }
  108. STDMETHODIMP_(unsigned long)
  109. CPoly::Release()
  110. {
  111.     POLYLINK FAR* FAR* pppolylink, FAR* ppolylinkDead;
  112.     if(--m_refs == 0){
  113.       Reset(); // release all CPoints
  114.       // remove ourselves from the global list of polygons
  115.       //
  116.       for( pppolylink = &g_ppolylink;
  117.           *pppolylink != NULL;
  118.    pppolylink = &(*pppolylink)->next)
  119.       {
  120. if((*pppolylink)->ppoly == this){
  121.   ppolylinkDead = *pppolylink;
  122.   *pppolylink = (*pppolylink)->next;
  123.   delete ppolylinkDead;
  124.   break;
  125. }
  126.       }
  127.       --g_cPoly;
  128. #ifndef _MAC
  129.       SBprintf(g_psb, TSTR("#poly = %d"), g_cPoly);
  130. #endif
  131.       delete this;
  132.       DecObjectCount();
  133.       return 0;
  134.     }
  135.     return m_refs;
  136. }
  137. //---------------------------------------------------------------------
  138. //                     IDispatch Methods
  139. //---------------------------------------------------------------------
  140. /*
  141.  * NOTE: Support for the following two methods is not available
  142.  * in this version.
  143.  *
  144.  */
  145. STDMETHODIMP
  146. CPoly::GetTypeInfoCount(unsigned int FAR* pctinfo)
  147. {
  148.     *pctinfo = 0;
  149.     return NOERROR;
  150. }
  151. STDMETHODIMP
  152. CPoly::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  153. {
  154.     UNUSED(itinfo);
  155.     UNUSED(lcid);
  156.     UNUSED(pptinfo);
  157.     return E_NOTIMPL;
  158. }
  159. /***
  160. *HRESULT CPoly::GetIDsOfNames(OLECHAR**, unsigned int, LCID, long*)
  161. *Purpose:
  162. *  This method translates the given array of names to a corresponding
  163. *  array of DISPIDs.
  164. *
  165. *  This method deferrs to a common implementation shared by
  166. *  both the CPoly and CPoint objects. See the description of
  167. *  'SPolyGetIDsOfNames()' in dispimpl.cpp for more information.
  168. *
  169. *Entry:
  170. *  rgszNames = pointer to an array of names
  171. *  cNames = the number of names in the rgszNames array
  172. *  lcid = the callers locale ID
  173. *
  174. *Exit:
  175. *  return value = HRESULT
  176. *  rgdispid = array of DISPIDs corresponding to the rgszNames array
  177. *    this array will contain -1 for each entry that is not known.
  178. *
  179. ***********************************************************************/
  180. STDMETHODIMP
  181. CPoly::GetIDsOfNames(
  182.     REFIID riid,
  183.     OLECHAR FAR* FAR* rgszNames,
  184.     unsigned int cNames,
  185.     LCID lcid,
  186.     DISPID FAR* rgdispid)
  187. {
  188. static PARAM_DESC rgpdAddPoint[] = {
  189.     {OLESTR("X")}, {OLESTR("Y")}
  190. };
  191. static MEMBERDESC rgmdCPoly[] = {
  192.     {OLESTR("DRAW"),    IDMEMBER_CPOLY_DRAW, NULL, 0},
  193.     {OLESTR("RESET"),    IDMEMBER_CPOLY_RESET, NULL, 0},
  194.     {OLESTR("ADDPOINT"),   IDMEMBER_CPOLY_ADDPOINT, rgpdAddPoint, 2},
  195.     {OLESTR("ENUMPOINTS"), IDMEMBER_CPOLY_ENUMPOINTS, NULL, 0},
  196.     {OLESTR("GETXORIGIN"), IDMEMBER_CPOLY_GETXORIGIN, NULL, 0},
  197.     {OLESTR("SETXORIGIN"), IDMEMBER_CPOLY_SETXORIGIN, NULL, 0},
  198.     {OLESTR("GETYORIGIN"), IDMEMBER_CPOLY_GETYORIGIN, NULL, 0},
  199.     {OLESTR("SETYORIGIN"), IDMEMBER_CPOLY_SETYORIGIN, NULL, 0},
  200.     {OLESTR("GETWIDTH"),   IDMEMBER_CPOLY_GETWIDTH, NULL, 0},
  201.     {OLESTR("SETWIDTH"),   IDMEMBER_CPOLY_SETWIDTH, NULL, 0},
  202.     {OLESTR("get_red"),    IDMEMBER_CPOLY_GETRED, NULL, 0},
  203.     {OLESTR("set_red"),    IDMEMBER_CPOLY_SETRED, NULL, 0},
  204.     {OLESTR("get_green"),  IDMEMBER_CPOLY_GETGREEN, NULL, 0},
  205.     {OLESTR("set_green"),  IDMEMBER_CPOLY_SETGREEN, NULL, 0},
  206.     {OLESTR("get_blue"),   IDMEMBER_CPOLY_GETBLUE, NULL, 0},
  207.     {OLESTR("set_blue"),   IDMEMBER_CPOLY_SETBLUE, NULL, 0},
  208.     {OLESTR("DUMP"),    IDMEMBER_CPOLY_DUMP, NULL, 0},
  209.     {OLESTR("Quit"),       IDMEMBER_CPOLY_QUIT,     NULL,       0}
  210. };
  211.     // this object only exposes a "default" interface.
  212.     //
  213.     if(!IsEqualIID(riid, IID_NULL))
  214.       return DISP_E_UNKNOWNINTERFACE;
  215.     return SPolyGetIDsOfNames(
  216.       rgmdCPoly, DIM(rgmdCPoly), rgszNames, cNames, lcid, rgdispid);
  217. }
  218. /***
  219. *HRESULT CPoly::Invoke(...)
  220. *Purpose:
  221. *  Dispatch a method or property request for objects of type CPoly.
  222. *
  223. *  see the IDispatch document for more information, and a general
  224. *  description of this method.
  225. *
  226. *Entry:
  227. *  dispidMember = the DISPID of the member being requested
  228. *
  229. *  riid = reference to the interface ID of the interface on this object
  230. *    that the requested member belongs to. IID_NULL means to interpret
  231. *    the member as belonging to the implementation defined "default"
  232. *    or "primary" interface.
  233. *
  234. *  lcid = the caller's locale ID
  235. *
  236. *  wFlags = flags indicating the type of access being requested
  237. *
  238. *  pdispparams = pointer to the DISPPARAMS struct containing the
  239. *    requested members arguments (if any) and its named parameter
  240. *    DISPIDs (if any).
  241. *
  242. *Exit:
  243. *  return value = HRESULT
  244. *   see the IDispatch spec for a description of possible success codes.
  245. *
  246. *  pvarResult = pointer to a caller allocated VARIANT containing
  247. *    the members return value (if any).
  248. *
  249. *  pexcepinfo = caller allocated exception info structure, this will
  250. *    be filled in only if an exception was raised that must be passed
  251. *    up through Invoke to an enclosing handler.
  252. *
  253. *  puArgErr = pointer to a caller allocated UINT, that will contain the
  254. *    index of the offending argument if a DISP_E_TYPEMISMATCH error
  255. *    was returned indicating that one of the arguments was of an
  256. *    incorrect type and/or could not be reasonably coerced to a proper
  257. *    type.
  258. *
  259. ***********************************************************************/
  260. STDMETHODIMP
  261. CPoly::Invoke(
  262.     DISPID dispidMember,
  263.     REFIID riid,
  264.     LCID lcid,
  265.     unsigned short wFlags,
  266.     DISPPARAMS FAR* pdispparams,
  267.     VARIANT FAR* pvarResult,
  268.     EXCEPINFO FAR* pexcepinfo,
  269.     unsigned int FAR* puArgErr)
  270. {
  271.     HRESULT hresult;
  272.     VARIANTARG varg0, varg1;
  273.     VARIANT varResultDummy;
  274.     UNUSED(lcid);
  275.     UNUSED(pexcepinfo);
  276.     if(wFlags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
  277.       return E_INVALIDARG;
  278.     // this object only exposes a "default" interface.
  279.     //
  280.     if(!IsEqualIID(riid, IID_NULL))
  281.       return DISP_E_UNKNOWNINTERFACE;
  282.     // This makes the following code a bit simpler if the caller
  283.     // happens to be ignoring the return value. Some implementations
  284.     // may choose to deal with this differently.
  285.     //
  286.     if(pvarResult == (VARIANT FAR*)NULL)
  287.       pvarResult = &varResultDummy;
  288.     VariantInit(&varg0);
  289.     VariantInit(&varg1);
  290.     // assume the return type is void, unless we find otherwise.
  291.     VariantInit(pvarResult);
  292.     switch(dispidMember){
  293.     case IDMEMBER_CPOLY_DRAW:
  294.       Draw();
  295.       break;
  296.     case IDMEMBER_CPOLY_RESET:
  297.       Reset();
  298.       break;
  299.     case IDMEMBER_CPOLY_DUMP:
  300.       Dump();
  301.       break;
  302.     case IDMEMBER_CPOLY_QUIT:
  303.       Quit();
  304.       break;
  305.     case IDMEMBER_CPOLY_ADDPOINT:
  306.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  307.       if(hresult != NOERROR)
  308. return hresult;
  309.       hresult = DispGetParam(pdispparams, 1, VT_I2, &varg1, puArgErr);
  310.       if(hresult != NOERROR)
  311. return hresult;
  312.       hresult = AddPoint(V_I2(&varg1), V_I2(&varg0));
  313.       if(hresult != NOERROR)
  314. return hresult;
  315.       break;
  316.     case IDMEMBER_CPOLY_ENUMPOINTS:
  317.       IEnumVARIANT FAR* penum;
  318.       hresult = EnumPoints(&penum);
  319.       if(hresult != NOERROR)
  320. return hresult;
  321.       V_VT(pvarResult) = VT_UNKNOWN;
  322.       hresult = penum->QueryInterface(
  323. IID_IUnknown, (void FAR* FAR*)&V_UNKNOWN(pvarResult));
  324.       if(hresult != NOERROR)
  325. return hresult;
  326.       penum->Release();
  327.       break;
  328.     case IDMEMBER_CPOLY_GETXORIGIN:
  329.       V_VT(pvarResult) = VT_I2;
  330.       V_I2(pvarResult) = m_xorg;
  331.       break;
  332.     case IDMEMBER_CPOLY_SETXORIGIN:
  333.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  334.       if(hresult != NOERROR)
  335.         return hresult;
  336.       m_xorg = V_I2(&varg0);
  337.       break;
  338.     case IDMEMBER_CPOLY_GETYORIGIN:
  339.       V_VT(pvarResult) = VT_I2;
  340.       V_I2(pvarResult) = m_yorg;
  341.       break;
  342.     case IDMEMBER_CPOLY_SETYORIGIN:
  343.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  344.       if(hresult != NOERROR)
  345.         return hresult;
  346.       m_yorg = V_I2(&varg0);
  347.       break;
  348.     case IDMEMBER_CPOLY_GETWIDTH:
  349.       V_VT(pvarResult) = VT_I2;
  350.       V_I2(pvarResult) = GetWidth();
  351.       break;
  352.     case IDMEMBER_CPOLY_SETWIDTH:
  353.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  354.       if(hresult != NOERROR)
  355.         return hresult;
  356.       SetWidth(V_I2(&varg0));
  357.       break;
  358.     case IDMEMBER_CPOLY_GETRED:
  359.       V_VT(pvarResult) = VT_I2;
  360.       V_I2(pvarResult) = get_red();
  361.       break;
  362.     case IDMEMBER_CPOLY_SETRED:
  363.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  364.       if(hresult != NOERROR)
  365.         return hresult;
  366.       set_red(V_I2(&varg0));
  367.       break;
  368.     case IDMEMBER_CPOLY_GETGREEN:
  369.       V_VT(pvarResult) = VT_I2;
  370.       V_I2(pvarResult) = get_green();
  371.       break;
  372.     case IDMEMBER_CPOLY_SETGREEN:
  373.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  374.       if(hresult != NOERROR)
  375.         return hresult;
  376.       set_green(V_I2(&varg0));
  377.       break;
  378.     case IDMEMBER_CPOLY_GETBLUE:
  379.       V_VT(pvarResult) = VT_I2;
  380.       V_I2(pvarResult) = get_blue();
  381.       break;
  382.     case IDMEMBER_CPOLY_SETBLUE:
  383.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  384.       if(hresult != NOERROR)
  385.         return hresult;
  386.       set_blue(V_I2(&varg0));
  387.       break;
  388.     default:
  389.       return DISP_E_MEMBERNOTFOUND;
  390.     }
  391.     return NOERROR;
  392. }
  393. //---------------------------------------------------------------------
  394. //                     Introduced Methods
  395. //---------------------------------------------------------------------
  396. /***
  397. *void CPoly::Draw(void)
  398. *Purpose:
  399. *  Draw the polygon, using the current x/y origin and line width
  400. *  properties.
  401. *
  402. *Entry:
  403. *  None
  404. *
  405. *Exit:
  406. *  None
  407. *
  408. ***********************************************************************/
  409. void PASCAL
  410. CPoly::Draw()
  411. {
  412.     short xorg, yorg;
  413.     POINTLINK FAR* ppointlinkFirst, FAR* ppointlink;
  414.     if((ppointlinkFirst = m_ppointlink) == (POINTLINK FAR*)NULL)
  415.       return;
  416. #ifdef _MAC /* { */
  417.     short x, y;
  418.     RGBColor rgb;
  419.     WindowPtr pwndSaved;
  420.     GetPort(&pwndSaved);
  421.     SetPort(g_pwndClient);
  422.     PenNormal();
  423.     PenSize(m_width, m_width);
  424.     rgb.red = m_red;
  425.     rgb.green = m_green;
  426.     rgb.blue = m_blue;
  427.     RGBForeColor(&rgb);
  428.     xorg = m_xorg;
  429.     yorg = m_yorg;
  430.     MoveTo(
  431.       xorg + ppointlinkFirst->ppoint->m_x,
  432.       yorg + ppointlinkFirst->ppoint->m_y);
  433.     for(ppointlink = ppointlinkFirst->next;
  434. ppointlink != (POINTLINK FAR*)NULL;
  435. ppointlink = ppointlink->next)
  436.     {
  437.       x = xorg + ppointlink->ppoint->m_x;
  438.       y = yorg + ppointlink->ppoint->m_y;
  439.       LineTo(x, y);
  440.     }
  441.     LineTo(
  442.       xorg + ppointlinkFirst->ppoint->m_x,
  443.       yorg + ppointlinkFirst->ppoint->m_y);
  444.     SetPort(pwndSaved);
  445. #else /* }{ */
  446.     HDC hdc;
  447.     RECT rect;
  448.     HPEN hpen, hpenOld;
  449. extern HWND g_hwndClient;
  450.     GetClientRect(g_hwndClient, &rect);
  451.     xorg = m_xorg + (short) rect.left;
  452.     yorg = m_yorg + (short) rect.top;
  453.     hdc = GetDC(g_hwndClient);
  454.     hpen = CreatePen(PS_SOLID, m_width, RGB(m_red, m_green, m_blue));
  455.     hpenOld = (HPEN)SelectObject(hdc, hpen);
  456. #ifdef WIN32
  457.     MoveToEx(hdc,
  458.       xorg + ppointlinkFirst->ppoint->m_x,
  459.       yorg + ppointlinkFirst->ppoint->m_y, NULL);
  460. #else
  461.     MoveTo(hdc,
  462.       xorg + ppointlinkFirst->ppoint->m_x,
  463.       yorg + ppointlinkFirst->ppoint->m_y);
  464. #endif
  465.     for(ppointlink = ppointlinkFirst->next;
  466. ppointlink != (POINTLINK FAR*)NULL;
  467. ppointlink = ppointlink->next)
  468.     {
  469.       LineTo(hdc,
  470. xorg + ppointlink->ppoint->m_x,
  471. yorg + ppointlink->ppoint->m_y);
  472.     }
  473.     LineTo(hdc,
  474.       xorg + ppointlinkFirst->ppoint->m_x,
  475.       yorg + ppointlinkFirst->ppoint->m_y);
  476.     SelectObject(hdc, hpenOld);
  477.     DeleteObject(hpen);
  478.     ReleaseDC(g_hwndClient, hdc);
  479. #endif /* } */
  480. }
  481. /***
  482. *void CPoly::Reset(void)
  483. *Purpose:
  484. *  Release all points referenced by this poly.
  485. *
  486. *Entry:
  487. *  None
  488. *
  489. *Exit:
  490. *  None
  491. *
  492. ***********************************************************************/
  493. void PASCAL
  494. CPoly::Reset()
  495. {
  496.     POINTLINK FAR* ppointlink, FAR* ppointlinkNext;
  497.     for(ppointlink = m_ppointlink;
  498. ppointlink != (POINTLINK FAR*)NULL;
  499. ppointlink = ppointlinkNext)
  500.     {
  501.       ppointlinkNext = ppointlink->next;
  502.       ppointlink->ppoint->Release();
  503.       delete ppointlink;
  504.     }
  505.     m_cPoints = 0;
  506.     m_ppointlink = NULL;
  507.     m_ppointlinkLast = NULL;
  508. }
  509. /***
  510. *HRESULT CPoly::AddPoint(short, short)
  511. *Purpose:
  512. *  Add a CPoint with the given coordinates to the end of our current
  513. *  list of points.
  514. *
  515. *Entry:
  516. *  x,y = the x and y coordinates of the new point.
  517. *
  518. *Exit:
  519. *  return value = HRESULT
  520. *
  521. ***********************************************************************/
  522. HRESULT PASCAL
  523. CPoly::AddPoint(short x, short y)
  524. {
  525.     CPoint FAR* ppoint;
  526.     POINTLINK FAR* ppointlink;
  527.     ppoint = CPoint::Create();
  528.     if(ppoint == (CPoint FAR*)NULL)
  529.       return E_OUTOFMEMORY;
  530.     ppoint->SetX(x);
  531.     ppoint->SetY(y);
  532.     ppointlink = new FAR POINTLINK;
  533.     if(ppointlink == (POINTLINK FAR*)NULL){
  534.       delete ppoint;
  535.       return E_OUTOFMEMORY;
  536.     }
  537.     ppointlink->ppoint = ppoint;
  538.     ppointlink->next = (POINTLINK FAR*)NULL;
  539.     if(m_ppointlinkLast == (POINTLINK FAR*)NULL){
  540.       m_ppointlink = m_ppointlinkLast = ppointlink;
  541.     }else{
  542.       m_ppointlinkLast->next = ppointlink;
  543.       m_ppointlinkLast = ppointlink;
  544.     }
  545.     ++m_cPoints;
  546.     return NOERROR;
  547. }
  548. /***
  549. *HRESULT CPoly::EnumPoints(IEnumVARIANT**);
  550. *Purpose:
  551. *  Return and enumerator for the points in this polygon.
  552. *
  553. *Entry:
  554. *  None
  555. *
  556. *Exit:
  557. *  return value = HRESULT
  558. *
  559. *  *ppenum = pointer to an IEnumVARIANT for the points in this polygon
  560. *
  561. ***********************************************************************/
  562. HRESULT PASCAL
  563. CPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
  564. {
  565.     unsigned int i;
  566.     VARIANT var;
  567.     HRESULT hresult;
  568.     SAFEARRAY FAR* psa;
  569.     CEnumPoint FAR* penum;
  570.     POINTLINK FAR* ppointlink;
  571.     SAFEARRAYBOUND rgsabound[1];
  572.     rgsabound[0].lLbound = 0;
  573.     rgsabound[0].cElements = m_cPoints;
  574.     psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  575.     if(psa == NULL){
  576.       hresult = E_OUTOFMEMORY;
  577.       goto LError0;
  578.     }
  579.     ppointlink = m_ppointlink;
  580.     for(i = 0; i < m_cPoints; ++i){
  581.       long ix[1];
  582.       if(ppointlink == NULL){
  583.         // this indicates an internal consistency error.
  584. // (this test should probably be an assertion)
  585.         hresult = E_FAIL;
  586.         goto LError1;
  587.       }
  588.       V_VT(&var) = VT_DISPATCH;
  589.       hresult = ppointlink->ppoint->QueryInterface(
  590. IID_IDispatch, (void FAR* FAR*)&V_DISPATCH(&var));
  591.       if(hresult != NOERROR)
  592.         goto LError1;
  593.       ix[0] = i;
  594.       SafeArrayPutElement(psa, ix, &var);
  595.       // SafeArrayPutElement adds a reference to the contents of the
  596.       // variant, so we must free the variable we have.
  597.       //
  598.       VariantClear(&var);
  599.       ppointlink = ppointlink->next;
  600.     }
  601.     hresult = CEnumPoint::Create(psa, &penum);
  602.     if(hresult != NOERROR)
  603.       goto LError1;
  604.     *ppenum = penum;
  605.     return NOERROR;
  606. LError1:;
  607.     // destroy the array if we were not successful creating the enumerator.
  608.     SafeArrayDestroy(psa);
  609. LError0:;
  610.     return hresult;
  611. }
  612. short PASCAL
  613. CPoly::GetXOrigin()
  614. {
  615.     return m_xorg;
  616. }
  617. void PASCAL
  618. CPoly::SetXOrigin(short x)
  619. {
  620.     m_xorg = x;
  621. }
  622. short PASCAL
  623. CPoly::GetYOrigin()
  624. {
  625.     return m_yorg;
  626. }
  627. void PASCAL
  628. CPoly::SetYOrigin(short y)
  629. {
  630.     m_yorg = y;
  631. }
  632. short PASCAL
  633. CPoly::GetWidth()
  634. {
  635.     return m_width;
  636. }
  637. void PASCAL
  638. CPoly::SetWidth(short width)
  639. {
  640.     m_width = width;
  641. }
  642. short PASCAL
  643. CPoly::get_red()
  644. {
  645.     return m_red;
  646. }
  647. void PASCAL
  648. CPoly::set_red(short red)
  649. {
  650.     m_red = red;
  651. }
  652. short PASCAL
  653. CPoly::get_green()
  654. {
  655.     return m_green;
  656. }
  657. void PASCAL
  658. CPoly::set_green(short green)
  659. {
  660.     m_green = green;
  661. }
  662. short PASCAL
  663. CPoly::get_blue()
  664. {
  665.     return m_blue;
  666. }
  667. void PASCAL
  668. CPoly::set_blue(short blue)
  669. {
  670.     m_blue = blue;
  671. }
  672. /***
  673. *void CPoly::Dump(void)
  674. *Purpose:
  675. *  Output a debug dump of this instance.
  676. *
  677. *Entry:
  678. *  None
  679. *
  680. *Exit:
  681. *  None
  682. *
  683. ***********************************************************************/
  684. void PASCAL
  685. CPoly::Dump()
  686. {
  687. #ifdef _MAC
  688.     // REVIEW: implement for the mac
  689. #else
  690.     TCHAR buffer[80];
  691.     POINTLINK FAR* ppointlink;
  692.     wsprintf(buffer, TSTR("CPoly(0x%x) =n"), (int)this);
  693.     OutputDebugString(buffer);
  694.     wsprintf(buffer,
  695.       TSTR("    xorg = %d, yorg = %d, width = %d, rgb = {%d,%d,%d}n    points = "),
  696.       m_xorg, m_yorg, m_width,
  697.       get_red(),
  698.       get_green(),
  699.       get_blue());
  700.     OutputDebugString(buffer);
  701.     for(ppointlink = m_ppointlink;
  702. ppointlink != (POINTLINK FAR*)NULL;
  703. ppointlink = ppointlink->next)
  704.     {
  705.       wsprintf(buffer, TSTR("{%d,%d}"),
  706.         ppointlink->ppoint->GetX(),
  707.         ppointlink->ppoint->GetY());
  708.       OutputDebugString(buffer);
  709.       wsprintf(buffer, TSTR(" "));
  710.       OutputDebugString(buffer);
  711.     }
  712.     wsprintf(buffer, TSTR("n"));
  713.     OutputDebugString(buffer);
  714. #endif
  715. }
  716. /***
  717. *void CPoly::Quit(void)
  718. *Purpose:
  719. *  Exit when all objects are released.
  720. *
  721. *Entry:
  722. *  None
  723. *
  724. *Exit:
  725. *  None
  726. *
  727. ***********************************************************************/
  728. void PASCAL
  729. CPoly::Quit()
  730. {
  731.     g_fQuit = 1;
  732. }
  733. /***
  734. *void CPoly::PolyDraw(void)
  735. *Purpose:
  736. *  Draw all polygons.
  737. *
  738. *Entry:
  739. *  None
  740. *
  741. *Exit:
  742. *  None
  743. *
  744. ***********************************************************************/
  745. void
  746. CPoly::PolyDraw()
  747. {
  748.     POLYLINK FAR* polylink;
  749.     for(polylink = g_ppolylink;
  750. polylink != (POLYLINK FAR*)NULL;
  751. polylink = polylink->next)
  752.     {
  753.       polylink->ppoly->Draw();
  754.     }
  755. }
  756. /***
  757. *void PolyTerm(void)
  758. *Purpose:
  759. *  Release all polygons.
  760. *
  761. *Entry:
  762. *  None
  763. *
  764. *Exit:
  765. *  None
  766. *
  767. ***********************************************************************/
  768. void
  769. CPoly::PolyTerm()
  770. {
  771.     POLYLINK FAR* ppolylink;
  772.     POLYLINK FAR* ppolylinkNext;
  773.     for(ppolylink = g_ppolylink;
  774. ppolylink != (POLYLINK FAR*)NULL;
  775. ppolylink = ppolylinkNext)
  776.     {
  777.       ppolylinkNext = ppolylink->next;
  778.       ppolylink->ppoly->Release();
  779.       delete ppolylink;
  780.     }
  781.     g_ppolylink = NULL;
  782. }
  783. /***
  784. *void PolyDump(void)
  785. *Purpose:
  786. *  Invoke the debug Dump() method on all polygons were currently
  787. *  holding on to.
  788. *
  789. *Entry:
  790. *  None
  791. *
  792. *Exit:
  793. *  None
  794. *
  795. ***********************************************************************/
  796. void
  797. CPoly::PolyDump()
  798. {
  799.     POLYLINK FAR* ppolylink;
  800.     if(g_ppolylink == (POLYLINK FAR*)NULL){
  801. #ifndef _MAC
  802.       OutputDebugString(TSTR("t(none)n"));
  803. #endif
  804.       return;
  805.     }
  806.     for(ppolylink = g_ppolylink;
  807. ppolylink != (POLYLINK FAR*)NULL;
  808. ppolylink = ppolylink->next)
  809.     {
  810.       ppolylink->ppoly->Dump();
  811.     }
  812. }
  813. //---------------------------------------------------------------------
  814. //             Implementation of the CPoly Class Factory 
  815. //---------------------------------------------------------------------
  816. CPolyCF::CPolyCF()
  817. {
  818.     m_refs = 0;
  819. }
  820. IClassFactory FAR*
  821. CPolyCF::Create()
  822. {
  823.     CPolyCF FAR* pCF;
  824.     if((pCF = new FAR CPolyCF()) == NULL)
  825.       return NULL;
  826.     pCF->AddRef();
  827.     return pCF;
  828. }
  829. STDMETHODIMP
  830. CPolyCF::QueryInterface(REFIID riid, void FAR* FAR* ppv) 
  831. {
  832.     if(!IsEqualIID(riid, IID_IUnknown)){
  833.       if(!IsEqualIID(riid, IID_IClassFactory)){
  834. *ppv = NULL;
  835.         return E_NOINTERFACE;
  836.       }
  837.     }
  838.     *ppv = this;
  839.     ++m_refs;
  840.     return NOERROR;
  841. }
  842. STDMETHODIMP_(unsigned long)
  843. CPolyCF::AddRef(void)
  844. {
  845.     return ++m_refs;
  846. }
  847. STDMETHODIMP_(unsigned long)
  848. CPolyCF::Release(void)
  849. {
  850.     if(--m_refs == 0){
  851.       delete this;
  852.       return 0;
  853.     }
  854.     return m_refs;
  855. }
  856. STDMETHODIMP
  857. CPolyCF::CreateInstance(
  858.     IUnknown FAR* punkOuter,
  859.     REFIID iid,
  860.     void FAR* FAR* ppv)
  861. {
  862.     HRESULT hresult;
  863.     CPoly FAR *ppoly;
  864.     UNUSED(punkOuter);
  865. #ifdef _MAC
  866.     if(GetZone() != ApplicZone()){
  867. #ifndef _MSC_VER
  868. #ifndef ConstStr255Param
  869. #define ConstStr255Param StringPtr
  870. #endif
  871. #endif
  872.       DebugStr((ConstStr255Param)"pZones do not match");
  873.     }
  874. #endif
  875.     if((ppoly = CPoly::Create()) == NULL){
  876.       *ppv = NULL;
  877.       return E_OUTOFMEMORY;
  878.     }
  879.     hresult = ppoly->QueryInterface(iid, ppv);
  880.     ppoly->Release();
  881.     return hresult;
  882. }
  883. STDMETHODIMP
  884. #ifdef _MAC
  885. CPolyCF::LockServer(unsigned long fLock)
  886. #else
  887. CPolyCF::LockServer(BOOL fLock)
  888. #endif
  889. {
  890.     UNUSED(fLock);
  891.     return NOERROR;
  892. }