home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / DOC.PAK / COLLECT.TXT < prev    next >
Text File  |  1995-08-29  |  8KB  |  189 lines

  1. AUTOMATING COLLECTIONS       
  2.  
  3. Frequently an application organizes data and objects in
  4. collections of various types, such as arrays, containers,
  5. or linked lists, or it utilizes such capabilites inherent in
  6. the operating platform.  Collections generally expose an
  7. iterator, a counter, a random-access function, and
  8. optionally methods for managing the collection. Exposing
  9. collections for automation generally involves three steps:
  10.  
  11.   1. The collection is exposed as a property which returns
  12.      an object.
  13.  
  14.   2. A C++ class is created, or enhanced, to support the
  15.      collection methods.
  16.  
  17.   3. An iterator is defined to provide code to iterate
  18.      through the collection.
  19.  
  20.  
  21. The iterator is internally exposed to the script controller
  22. as a property having the reserved name "_NewEnum" which
  23. returns an object supporting the IENUMVariant interface.
  24. This interface contains methods to perform iteration.  With
  25. VisualBasic for Applications, the following syntax is used
  26. for iteration:
  27.  
  28.   For Each Thing In Owner.Bunch  ("Thing" is an arbitrary 
  29.                                    iterator name)
  30.     Thing.Member......           (can access methods and 
  31.                                    properties)
  32.   Next Thing                     (loops through all items 
  33.                                    in collection)
  34.  
  35. Note that the server can return any data type for items,
  36. values or objects.
  37.  
  38.  
  39. CREATING C++ CLASSES SPECIFICALLY FOR AUTOMATION
  40.  
  41. Frequently C++ classes do not already exist to encapsulate
  42. items to be exposed for automation, such as collections,
  43. simple structures, and system objects represented by
  44. handles. The only C++ methods required are a constructor
  45. and support methods for the exposed automation. Instances
  46. of these classes are exposed as properties of their parent
  47. classes and are constructed as the properties are retrieved
  48. (as opposed to returning references to existing C++
  49. instances). The constructor must accept a single argument
  50. from the parent class: member data, result of an accessor
  51. function, or the object's this pointer. The parent class
  52. must supply an AUTOxxx macro that supplies this constructor
  53. argument as a data member or function, and declares its
  54. type with the templatized pointer class
  55. TAutoObjectByVal<T>, where T is the new automated C++
  56. class. TAutoObjectByVal<T> causes an instance of T to be
  57. constructed that persists until all external references to
  58. that instance are released (when the exposed object goes
  59. out of scope in the automation controller).  Examples of
  60. the macros used within the DECLARE_AUTOCLASS and
  61. DEFINE_AUTOCLASS sections are given below:
  62.  
  63.   AUTODATARO(Documents, DocList, TAutoObjectByVal<TDocumentList>,)
  64.   // DocList is a TDocument*, head of a linked list of.
  65.   // type TDocument. TDocumentList is a new class, constructor: 
  66.   // TDocumentList(TDocument*)
  67.   EXPOSE_PROPRO(Documents, TDocumentList, "Documents", "Doc Collection", 270)
  68.  
  69.   AUTOTHIS(Views, TAutoObjectByVal<TViewList>,)
  70.   // TViewList is a new class, constructor: TView(TDocument* owner)
  71.   // In this case the parent's this pointer is passed to the constuctor
  72.   EXPOSE_PROPRO(Views, TViewList, "Views", "View Collection", 240)
  73.  
  74.   AUTOFUNC0(Buttons, GetWindow(), TAutoObjectByVal<TCalcButtons>, )
  75.   // GetWindow() gets the window handle of the parent window of 
  76.   // the buttons. TCalcButtons is a new class, constructor: 
  77.   // TCalcButtons(HWND parent)
  78.   EXPOSE_PROPRO(Buttons, TCalcButtons, "Buttons", Button Collection", 170)
  79.  
  80.   AUTODATARO(MyArray, Elem, TAutoObjectByVal<TMyArray>,)
  81.   // Elem is an array of shorts, defined as short Elem[COUNT]
  82.   // TMyArray is a new class, constructor: TMyArray(short* array)
  83.   EXPOSE_PROPRO(MyArray, TMyArray, "Array", "Array as collection", 110)
  84.  
  85.  
  86. COLLECTION CLASSES
  87.  
  88. A C++ class must be defined to host the automation
  89. declarations along with the supporting C++ methods.  For
  90. some collections, a C++ class might already exist. Otherwise
  91. one must be defined to represent a collection object. 
  92.  
  93.  
  94. EXPOSING COLLECTION OBJECTS
  95.  
  96. EXPOSING ITERATORS
  97.  
  98. Iterators are defined for automation using the AUTOITERATOR
  99. macro, which defines the iteration algorithm for the
  100. enclosing collection class. No internal name is supplied,
  101. as only one iterator may exist within a class.  The macro
  102. has five arguments, each representing a code fragment,
  103. ordered as in a "for" loop.
  104.  
  105.   1. Declaration of state variables,      e.g. int Index
  106.   2. Loop initializer assigments,         e.g. Index = 0
  107.   3. Loop entry test boolean expression,  e.g. Index < This->Total
  108.   4. Loop iteration statements,           e.g. Index++
  109.   5. Current element access expression,   e.g. (This->Array)[Index]
  110.  
  111. Commas cannot be used unless inside parentheses. Semicolons
  112. can be used to separate multiple statements, but cannot 
  113. be used to end a macro argument.  In common with automated
  114. methods, "This" is defined to be the "this" pointer of the
  115. enclosing C++ class, in this case the collection itself.
  116.  
  117. The AUTOITERATOR macro generates a nested class definition.
  118. For complex iterators, this class can be specified directly
  119. in C++ as shown below:
  120.  
  121.   class TIterator : public TAutoIterator {
  122.     public:
  123.       ThisClass* This;
  124.       /* declare state variables here as members */
  125.       void Init() {/* loop initialization function body */}
  126.       bool Test() {/* loop entry test function body */}
  127.       void Step() {/* loop iteration function body;}
  128.       void Return(TAutoVal& v) {/* current element return: v = expr */}
  129.       TIterator* Copy() {return new TIterator(*this);}
  130.       TIterator(ThisClass* obj, TServedObject& owner)
  131.                     : This(obj), TAutoIterator(owner) {}
  132.       static TAutoIterator* Build(ObjectPtr obj, TServedObject& owner)
  133.       { return new TIterator((ThisClass*)obj, owner); }
  134.   }; friend class TIterator;
  135.  
  136. Iterators are exposed as properties using the
  137. EXPOSE_ITERATOR macro. Note that no internal or external
  138. names are supplied (the external name is internally
  139. hard-wired as "_NewEnum"). The automation type describes the
  140. type of the items returned from the iterator, in the same
  141. manner as a function return.
  142.  
  143.   AUTOITERATOR(int Index, Index=0, Index<COUNT, Index++, 
  144.                  (This->Array)[Index])
  145.   // Array is a member array of shorts for which an iterator 
  146.   // is defined. It will exposed as a "_NewEnum" property which 
  147.   // returns an OLE enumerator.
  148.   EXPOSE_ITERATOR(TAutoShort, "Array Iterator", HC_ARRAY_ITERATOR)
  149.  
  150. In addition to exposing an iterator, a collection class by
  151. convention exposes a "Count" method to return the number of
  152. items in the collections, an "Index" method to randomly
  153. access an element of the collection, and optionally,
  154. methods to externally manage the collection, such as add and
  155. delete.
  156.  
  157. ____________________________________________________________
  158.  
  159.  
  160.          ----example code from AutoCalc------
  161.  
  162. class TCalcButtons {
  163.   public:
  164.     TCalcButtons(HWND window) : HWnd(window) {}
  165.     short GetCount() { return IDC_LASTID - IDC_FIRSTID; }
  166.     HWND HWnd;
  167.  
  168.   DECLARE_AUTOCLASS(TCalcButtons)
  169.     AUTOFUNC0 (Count, GetCount, short,)
  170.     AUTOITERATOR(int Id, Id = IDC_FIRSTID+1, 
  171.       Id <= IDC_LASTID, Id++,
  172.       TAutoObjectByVal<TCalcButton>(::GetDlgItem(This->HWnd,Id)))
  173. };
  174.  
  175. DEFINE_AUTOCLASS(TCalcButtons)
  176.  
  177.   EXPOSE_PROPRO(Count, TAutoLong, "!Count","Button Count", 
  178.       HC_TCALCBUTTONS_COUNT)
  179.   EXPOSE_ITERATOR(TCalcButton, "Button Iterator", 
  180.     HC_TCALCBUTTONS_ITERATOR)
  181.   EXPOSE_METHOD_ID(0, Item, TCalcButton,"!Item",  
  182.     "Button Collection Item", 0)
  183.     REQUIRED_ARG(TAutoShort, "!Index")
  184.  
  185. END_AUTOCLASS(TCalcButtons, "ButtonCollection", 
  186.     "Button Collection", HC_TCALCBUTTONS)
  187.  
  188.  
  189.