|
|
1.1 root 1: /***
2: *cpoly.cpp - Implementation of the CPoly object.
3: *
4: * Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
5: * Information Contained Herein Is Proprietary and Confidential.
6: *
7: *Purpose:
8: * This module implements the CPoly class. This class implements a
9: * number of methods and properties, and exposes them via IDispatch.
10: *
11: * This module is intended as a sample implementation of the IDispatch
12: * interface, and its purpose is to demonstrate how an object can
13: * expose methods and properties for programatic and cross-process
14: * access via the IDispatch interface.
15: *
16: *Implementation Notes:
17: *
18: *****************************************************************************/
19:
20: #include <windows.h>
21: #include <ole2.h>
22: #if !defined(WIN32)
23: #include <olenls.h>
24: #endif
25: #include <dispatch.h>
26:
27: #include "statbar.h"
28: #include "cenumpt.h"
29:
30: #include "spoly.h"
31: #include "cpoint.h"
32: #include "cpoly.h"
33:
34:
35: // Adjust for WIN16/WIN32 synchronization
36: #if defined(WIN32) && !defined(OLE2FINAL)
37: #define E_FAIL E_UNSPEC
38: #endif
39:
40:
41: extern HWND g_hwndClient;
42:
43: extern CStatBar FAR* g_psb;
44:
45: extern BOOL g_fExitOnLastRelease;
46:
47:
48: // our global list of polygons.
49: //
50: POLYLINK FAR* g_ppolylink = (POLYLINK FAR*)NULL;
51:
52: // global count of polygons.
53: //
54: int g_cPoly = 0;
55:
56:
57: CPoly::CPoly()
58: {
59: m_refs = 0;
60: m_xorg = 0;
61: m_yorg = 0;
62: m_width = 0;
63: m_cPoints = 0;
64:
65: m_red = 0;
66: m_green = 0;
67: m_blue = 0;
68:
69: m_ptinfo = NULL;
70:
71: m_ppointlink = NULL;
72: m_ppointlinkLast = NULL;
73: }
74:
75:
76: /***
77: *CPoly *CPoly::Create(void)
78: *Purpose:
79: * Create an instance of a CPoly object, and add it to the global
80: * list of polygons.
81: *
82: *Entry:
83: * None
84: *
85: *Exit:
86: * returns a polygon object, NULL the allocation failed.
87: *
88: ***********************************************************************/
89: CPoly FAR*
90: CPoly::Create()
91: {
92: HRESULT hresult;
93: CPoly FAR* ppoly;
94: ITypeInfo FAR* ptinfo;
95: POLYLINK FAR* ppolylink;
96: extern INTERFACEDATA NEAR g_idataCPoly;
97:
98:
99: if((ppolylink = new FAR POLYLINK) == (POLYLINK FAR*)NULL)
100: return (CPoly FAR*)NULL;
101:
102: if((ppoly = new FAR CPoly()) == (CPoly FAR*)NULL)
103: return (CPoly FAR*)NULL;
104:
105: ppoly->AddRef();
106:
107: // create and attach its TypeInfo
108: //
109: hresult = CreateDispTypeInfo(&g_idataCPoly, LOCALE_SYSTEM_DEFAULT, &ptinfo);
110: if(hresult != NOERROR)
111: goto LError0;
112:
113: ppoly->m_ptinfo = ptinfo;
114:
115: // push the new polygon onto the front of the polygon list.
116: //
117: ++g_cPoly;
118:
119: ppolylink->ppoly = ppoly;
120:
121: ppolylink->next = g_ppolylink;
122: g_ppolylink = ppolylink;
123:
124: SBprintf(g_psb, "#poly = %d", g_cPoly);
125:
126: return ppoly;
127:
128:
129: LError0:;
130: ppoly->Release();
131:
132: return NULL;
133: }
134:
135:
136: //---------------------------------------------------------------------
137: // IUnknown Methods
138: //---------------------------------------------------------------------
139:
140:
141: STDMETHODIMP
142: CPoly::QueryInterface(REFIID riid, void FAR* FAR* ppv)
143: {
144: if(riid != IID_IUnknown)
145: if(riid != IID_IDispatch)
146: return ResultFromScode(E_NOINTERFACE);
147:
148: *ppv = this;
149: AddRef();
150: return NOERROR;
151: }
152:
153:
154: STDMETHODIMP_(ULONG)
155: CPoly::AddRef()
156: {
157: return ++m_refs;
158: }
159:
160:
161: STDMETHODIMP_(ULONG)
162: CPoly::Release()
163: {
164: POLYLINK FAR* FAR* pppolylink, FAR* ppolylinkDead;
165:
166: if(--m_refs == 0){
167: Reset(); // release all CPoints
168:
169: // remove ourselves from the global list of polygons
170: //
171: for( pppolylink = &g_ppolylink;
172: *pppolylink != NULL;
173: pppolylink = &(*pppolylink)->next)
174: {
175: if((*pppolylink)->ppoly == this){
176: ppolylinkDead = *pppolylink;
177: *pppolylink = (*pppolylink)->next;
178: delete ppolylinkDead;
179: break;
180: }
181: }
182:
183: if(m_ptinfo != NULL){
184: m_ptinfo->Release();
185: }
186:
187: --g_cPoly;
188:
189: #ifndef _MAC
190: SBprintf(g_psb, "#poly = %d", g_cPoly);
191: #endif
192:
193: delete this;
194: return 0;
195: }
196: return m_refs;
197: }
198:
199:
200: //---------------------------------------------------------------------
201: // IDispatch Methods
202: //---------------------------------------------------------------------
203:
204: STDMETHODIMP
205: CPoly::GetTypeInfoCount(UINT FAR* pctinfo)
206: {
207: // This object has a single *introduced* interface
208: //
209: *pctinfo = 1;
210:
211: return NOERROR;
212: }
213:
214:
215: STDMETHODIMP
216: CPoly::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
217: {
218: if(itinfo != 0)
219: return ResultFromScode(DISP_E_BADINDEX);
220:
221: m_ptinfo->AddRef();
222: *pptinfo = m_ptinfo;
223:
224: return NOERROR;
225: }
226:
227:
228: /***
229: *HRESULT CPoly::GetIDsOfNames(char**, UINT, LCID, LONG*)
230: *Purpose:
231: * This method translates the given array of names to a corresponding
232: * array of DISPIDs.
233: *
234: * This method deferrs to a common implementation shared by
235: * both the CPoly and CPoint objects. See the description of
236: * 'SPolyGetIDsOfNames()' in dispimpl.cpp for more information.
237: *
238: *Entry:
239: * rgszNames = pointer to an array of names
240: * cNames = the number of names in the rgszNames array
241: * lcid = the callers locale ID
242: *
243: *Exit:
244: * return value = HRESULT
245: * rgdispid = array of DISPIDs corresponding to the rgszNames array
246: * this array will contain -1 for each entry that is not known.
247: *
248: ***********************************************************************/
249: STDMETHODIMP
250: CPoly::GetIDsOfNames(
251: REFIID riid,
252: char FAR* FAR* rgszNames,
253: UINT cNames,
254: LCID lcid,
255: DISPID FAR* rgdispid)
256: {
257: if(riid != IID_NULL)
258: return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
259:
260: return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);
261: }
262:
263:
264: /***
265: *HRESULT CPoly::Invoke(...)
266: *Purpose:
267: * Dispatch a method or property request for objects of type CPoly.
268: *
269: * see the IDispatch document for more information, and a general
270: * description of this method.
271: *
272: *Entry:
273: * dispidMember = the DISPID of the member being requested
274: *
275: * riid = reference to the interface ID of the interface on this object
276: * that the requested member belongs to. IID_NULL means to interpret
277: * the member as belonging to the implementation defined "default"
278: * or "primary" interface.
279: *
280: * lcid = the caller's locale ID
281: *
282: * wFlags = flags indicating the type of access being requested
283: *
284: * pdispparams = pointer to the DISPPARAMS struct containing the
285: * requested members arguments (if any) and its named parameter
286: * DISPIDs (if any).
287: *
288: *Exit:
289: * return value = HRESULT
290: * see the IDispatch spec for a description of possible success codes.
291: *
292: * pvarResult = pointer to a caller allocated VARIANT containing
293: * the members return value (if any).
294: *
295: * pexcepinfo = caller allocated exception info structure, this will
296: * be filled in only if an exception was raised that must be passed
297: * up through Invoke to an enclosing handler.
298: *
299: * puArgErr = pointer to a caller allocated UINT, that will contain the
300: * index of the offending argument if a DISP_E_TYPEMISMATCH error
301: * was returned indicating that one of the arguments was of an
302: * incorrect type and/or could not be reasonably coerced to a proper
303: * type.
304: *
305: ***********************************************************************/
306: STDMETHODIMP
307: CPoly::Invoke(
308: DISPID dispidMember,
309: REFIID riid,
310: LCID lcid,
311: WORD wFlags,
312: DISPPARAMS FAR* pdispparams,
313: VARIANT FAR* pvarResult,
314: EXCEPINFO FAR* pexcepinfo,
315: UINT FAR* puArgErr)
316: {
317: if(riid != IID_NULL)
318: return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
319:
320: return DispInvoke(
321: this, m_ptinfo,
322: dispidMember, wFlags, pdispparams,
323: pvarResult, pexcepinfo, puArgErr);
324: }
325:
326:
327: //---------------------------------------------------------------------
328: // Introduced Methods
329: //---------------------------------------------------------------------
330:
331:
332: /***
333: *void CPoly::Draw(void)
334: *Purpose:
335: * Draw the polygon, using the current x/y origin and line width
336: * properties.
337: *
338: *Entry:
339: * None
340: *
341: *Exit:
342: * None
343: *
344: ***********************************************************************/
345: void METHODCALLTYPE EXPORT
346: CPoly::Draw()
347: {
348: POINTLINK FAR* ppointlinkFirst, FAR* ppointlink;
349:
350: if((ppointlinkFirst = m_ppointlink) == (POINTLINK FAR*)NULL)
351: return;
352:
353: #ifdef _MAC /* { */
354:
355: #else /* }{ */
356:
357: HDC hdc;
358: RECT rect;
359: short xorg, yorg;
360: HPEN hpen, hpenOld;
361:
362: GetClientRect(g_hwndClient, &rect);
363: xorg = m_xorg + (short) rect.left;
364: yorg = m_yorg + (short) rect.top;
365:
366: hdc = GetDC(g_hwndClient);
367: hpen = CreatePen(PS_SOLID, m_width, RGB(m_red, m_green, m_blue));
368: hpenOld = SelectObject(hdc, hpen);
369:
370: #ifdef WIN32
371: MoveToEx(hdc,
372: xorg + ppointlinkFirst->ppoint->m_x,
373: yorg + ppointlinkFirst->ppoint->m_y, NULL);
374: #else
375: MoveTo(hdc,
376: xorg + ppointlinkFirst->ppoint->m_x,
377: yorg + ppointlinkFirst->ppoint->m_y);
378: #endif
379:
380: for(ppointlink = ppointlinkFirst->next;
381: ppointlink != (POINTLINK FAR*)NULL;
382: ppointlink = ppointlink->next)
383: {
384: LineTo(hdc,
385: xorg + ppointlink->ppoint->m_x,
386: yorg + ppointlink->ppoint->m_y);
387: }
388:
389: LineTo(hdc,
390: xorg + ppointlinkFirst->ppoint->m_x,
391: yorg + ppointlinkFirst->ppoint->m_y);
392:
393: SelectObject(hdc, hpenOld);
394: DeleteObject(hpen);
395:
396: ReleaseDC(g_hwndClient, hdc);
397:
398: #endif /* } */
399: }
400:
401:
402: /***
403: *void CPoly::Reset(void)
404: *Purpose:
405: * Release all points referenced by this poly.
406: *
407: *Entry:
408: * None
409: *
410: *Exit:
411: * None
412: *
413: ***********************************************************************/
414: void METHODCALLTYPE EXPORT
415: CPoly::Reset()
416: {
417: POINTLINK FAR* ppointlink, FAR* ppointlinkNext;
418:
419: for(ppointlink = m_ppointlink;
420: ppointlink != (POINTLINK FAR*)NULL;
421: ppointlink = ppointlinkNext)
422: {
423: ppointlinkNext = ppointlink->next;
424: ppointlink->ppoint->Release();
425: delete ppointlink;
426: }
427:
428: m_cPoints = 0;
429: m_ppointlink = NULL;
430: m_ppointlinkLast = NULL;
431: }
432:
433:
434: /***
435: *HRESULT CPoly::AddPoint(short, short)
436: *Purpose:
437: * Add a CPoint with the given coordinates to the end of our current
438: * list of points.
439: *
440: *Entry:
441: * x,y = the x and y coordinates of the new point.
442: *
443: *Exit:
444: * return value = HRESULT
445: *
446: ***********************************************************************/
447: HRESULT METHODCALLTYPE
448: CPoly::AddPoint(short x, short y)
449: {
450: CPoint FAR* ppoint;
451: POINTLINK FAR* ppointlink;
452:
453: ppoint = CPoint::Create();
454: if(ppoint == (CPoint FAR*)NULL)
455: return ResultFromScode(E_OUTOFMEMORY);
456:
457: ppoint->SetX(x);
458: ppoint->SetY(y);
459:
460: ppointlink = new FAR POINTLINK;
461: if(ppointlink == (POINTLINK FAR*)NULL){
462: delete ppoint;
463: return ResultFromScode(E_OUTOFMEMORY);
464: }
465:
466: ppointlink->ppoint = ppoint;
467: ppointlink->next = (POINTLINK FAR*)NULL;
468:
469: if(m_ppointlinkLast == (POINTLINK FAR*)NULL){
470: m_ppointlink = m_ppointlinkLast = ppointlink;
471: }else{
472: m_ppointlinkLast->next = ppointlink;
473: m_ppointlinkLast = ppointlink;
474: }
475:
476: ++m_cPoints;
477:
478: return NOERROR;
479: }
480:
481:
482: /***
483: *IUnknown FAR* CPoly::EnumPoints(void);
484: *Purpose:
485: * Return and enumerator for the points in this polygon.
486: *
487: *Entry:
488: * None
489: *
490: *Exit:
491: * return value = HRESULT
492: *
493: * *ppenum = pointer to an IEnumVARIANT for the points in this polygon
494: *
495: ***********************************************************************/
496: IUnknown FAR* METHODCALLTYPE EXPORT
497: CPoly::EnumPoints()
498: {
499: UINT i;
500: HRESULT hresult;
501: VARIANT var;
502: SAFEARRAY FAR* psa;
503: IUnknown FAR* punk;
504: CEnumPoint FAR* penum;
505: POINTLINK FAR* ppointlink;
506: SAFEARRAYBOUND rgsabound[1];
507:
508: rgsabound[0].lLbound = 0;
509: rgsabound[0].cElements = m_cPoints;
510:
511: psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
512: if(psa == NULL){
513: hresult = ResultFromScode(E_OUTOFMEMORY);
514: goto LError0;
515: }
516:
517: ppointlink = m_ppointlink;
518: for(i = 0; i < m_cPoints; ++i){
519: LONG ix[1];
520:
521: if(ppointlink == NULL){
522: // this indicates an internal consistency error.
523: // (this test should probably be an assertion)
524: hresult = ResultFromScode(E_FAIL);
525: goto LError1;
526: }
527:
528: V_VT(&var) = VT_DISPATCH;
529: hresult = ppointlink->ppoint->QueryInterface(
530: IID_IDispatch, (void FAR* FAR*)&V_DISPATCH(&var));
531: if(hresult != NOERROR)
532: goto LError1;
533:
534: ix[0] = i;
535: SafeArrayPutElement(psa, ix, &var);
536:
537: ppointlink = ppointlink->next;
538: }
539:
540: hresult = CEnumPoint::Create(psa, &penum);
541: if(hresult != NOERROR)
542: goto LError1;
543:
544: // ownership of the array has passed to the enumerator
545: psa = NULL;
546:
547: hresult = penum->QueryInterface(IID_IUnknown, (void FAR* FAR*)&punk);
548: if(hresult != NOERROR)
549: goto LError2;
550:
551: penum->Release();
552:
553: return punk;
554:
555: LError2:;
556: penum->Release();
557:
558: LError1:;
559: // destroy the array if we were not successful creating the enumerator.
560: if(psa != NULL)
561: SafeArrayDestroy(psa);
562:
563: LError0:;
564: return NULL;
565: }
566:
567:
568: short METHODCALLTYPE EXPORT
569: CPoly::GetXOrigin()
570: {
571: return m_xorg;
572: }
573:
574: void METHODCALLTYPE EXPORT
575: CPoly::SetXOrigin(short x)
576: {
577: m_xorg = x;
578: }
579:
580: short METHODCALLTYPE EXPORT
581: CPoly::GetYOrigin()
582: {
583: return m_yorg;
584: }
585:
586: void METHODCALLTYPE EXPORT
587: CPoly::SetYOrigin(short y)
588: {
589: m_yorg = y;
590: }
591:
592: short METHODCALLTYPE EXPORT
593: CPoly::GetWidth()
594: {
595: return m_width;
596: }
597:
598:
599: void METHODCALLTYPE EXPORT
600: CPoly::SetWidth(short width)
601: {
602: m_width = width;
603: }
604:
605: short METHODCALLTYPE EXPORT
606: CPoly::get_red()
607: {
608: return m_red;
609: }
610:
611: void METHODCALLTYPE EXPORT
612: CPoly::set_red(short red)
613: {
614: m_red = red;
615: }
616:
617: short METHODCALLTYPE EXPORT
618: CPoly::get_green()
619: {
620: return m_green;
621: }
622:
623: void METHODCALLTYPE EXPORT
624: CPoly::set_green(short green)
625: {
626: m_green = green;
627: }
628:
629: short METHODCALLTYPE EXPORT
630: CPoly::get_blue()
631: {
632: return m_blue;
633: }
634:
635: void METHODCALLTYPE EXPORT
636: CPoly::set_blue(short blue)
637: {
638: m_blue = blue;
639: }
640:
641:
642: /***
643: *void CPoly::Dump(void)
644: *Purpose:
645: * Output a debug dump of this instance.
646: *
647: *Entry:
648: * None
649: *
650: *Exit:
651: * None
652: *
653: ***********************************************************************/
654: void METHODCALLTYPE EXPORT
655: CPoly::Dump()
656: {
657: #ifdef _MAC
658:
659: // REVIEW: implement for the mac
660:
661: #else
662:
663: char buffer[80];
664: POINTLINK FAR* ppointlink;
665:
666: wsprintf(buffer, "CPoly(0x%x) =\n", (int)this);
667: OutputDebugString(buffer);
668:
669: wsprintf(buffer,
670: " xorg = %d, yorg = %d, width = %d, rgb = {%d,%d,%d}\n points = ",
671: m_xorg, m_yorg, m_width,
672: get_red(),
673: get_green(),
674: get_blue());
675:
676: OutputDebugString(buffer);
677:
678: for(ppointlink = m_ppointlink;
679: ppointlink != (POINTLINK FAR*)NULL;
680: ppointlink = ppointlink->next)
681: {
682: wsprintf(buffer, "{%d,%d}",
683: ppointlink->ppoint->GetX(),
684: ppointlink->ppoint->GetY());
685: OutputDebugString(buffer);
686:
687: wsprintf(buffer, " ");
688: OutputDebugString(buffer);
689: }
690: wsprintf(buffer, "\n");
691: OutputDebugString(buffer);
692:
693: #endif
694: }
695:
696: /***
697: *void CPoly::PolyDraw(void)
698: *Purpose:
699: * Draw all polygons.
700: *
701: *Entry:
702: * None
703: *
704: *Exit:
705: * None
706: *
707: ***********************************************************************/
708: void
709: CPoly::PolyDraw()
710: {
711: POLYLINK FAR* polylink;
712:
713: for(polylink = g_ppolylink;
714: polylink != (POLYLINK FAR*)NULL;
715: polylink = polylink->next)
716: {
717: polylink->ppoly->Draw();
718: }
719: }
720:
721:
722: /***
723: *void PolyTerm(void)
724: *Purpose:
725: * Release all polygons.
726: *
727: *Entry:
728: * None
729: *
730: *Exit:
731: * None
732: *
733: ***********************************************************************/
734: void
735: CPoly::PolyTerm()
736: {
737: POLYLINK FAR* ppolylink;
738: POLYLINK FAR* ppolylinkNext;
739:
740: for(ppolylink = g_ppolylink;
741: ppolylink != (POLYLINK FAR*)NULL;
742: ppolylink = ppolylinkNext)
743: {
744: ppolylinkNext = ppolylink->next;
745: ppolylink->ppoly->Release();
746: delete ppolylink;
747: }
748: }
749:
750:
751: /***
752: *void PolyDump(void)
753: *Purpose:
754: * Invoke the debug Dump() method on all polygons were currently
755: * holding on to.
756: *
757: *Entry:
758: * None
759: *
760: *Exit:
761: * None
762: *
763: ***********************************************************************/
764: void
765: CPoly::PolyDump()
766: {
767: POLYLINK FAR* ppolylink;
768:
769: if(g_ppolylink == (POLYLINK FAR*)NULL){
770: OutputDebugString("\t(none)\n");
771: return;
772: }
773:
774: for(ppolylink = g_ppolylink;
775: ppolylink != (POLYLINK FAR*)NULL;
776: ppolylink = ppolylink->next)
777: {
778: ppolylink->ppoly->Dump();
779: }
780: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.