In the microsoft docs for 'collection', it says that
Collections must implement a method called NewEnum that accepts no
arguments, returns an appropriate IUnknown object, and has its
VB_UserMemId attribute set to -4.
If I look at 'Collection' in the excel VBA object browser, I can only see Add, Count, Item and Remove.
How do I see that Collection has a NewEnum method? Where do I see documentation for its NewEnum method? Is there any way to see the source code?
Many thanks!
Collections are Standard Objects defined in the COM Automation standard. This was written at the same time as VBA and for VBA. A programmer has to implement the collection.
A collection is created by a program according to some rules. There is no source code as it a standard that programmers must follow to create a collection. It purpose is to enable the For - Each construct.
VBA has an implementation of a generic collection for programmers to quickly use but advise not to use it in code that other code calls. You are supposed wrap VBA's generic collection in a class. You can stick anything in VBA's generic collection and you write a class to restrict what can be added.
When you get a collection from Excel Excel works out what to give you by what object you asked for in your For Each loop. EG Rows inherit from range so you treat it as a range object as it has same properties and methods. Under COM rules it could have more methods but not fewer than the range object. If you ask a rows object, via IUnknown:QueryInterface, are you a range it will answer yes.
From https://learn.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-ienumvariant
Collection Object Properties
A collection provides a set of objects over which iteration can be
performed. All collection objects must provide the following
properties:
Property name Return type Description
Count VT_I4 Returns the number of items in the collection; read only. Required.
_NewEnum VT_DISPATCH A special property that returns an enumerator object that
implements IEnumVARIANT. Required.
IEnumVARIANT Interface
The IEnumVARIANT interface provides a method for enumerating a
collection of variants, including heterogeneous collections of objects
and intrinsic types. Callers of this interface do not need to know the
specific type (or types) of the elements in the collection.
Implemented by Used by Header file name
Applications that expose collections of objects Applications that
access collections of objects Oleauto.h (32-bit systems)
Dispatch.h (16-bit systems)
The following is the definition that results from expanding the
parameterized type IEnumVARIANT:
interface IEnumVARIANT : IUnknown {
virtual HRESULT Next(unsigned long celt,
VARIANT FAR* rgvar,
unsigned long FAR* pceltFetched) = 0;
virtual HRESULT Skip(unsigned long celt) = 0;
virtual HRESULT Reset() = 0;
virtual HRESULT Clone(IEnumVARIANT FAR* FAR* ppenum) = 0;
};
To see how to implement a collection of objects using IEnumVARIANT,
refer to the file Enumvar.cpp in the Lines sample code.
IEnumVARIANT Methods Description
Clone Creates a copy of the current state of enumeration.
Next Gets the next items in the enumeration sequence
Reset Resets the enumeration sequence to the beginning.
Skip Attempts to skip over the next celt elements in the enumeration sequence.
Related
I would like to use the tlbinf32.dll to read type info for a COM object. At the moment I have access to the pointer to the ITypeLib interface. I can use VTable offsets and DispCallFunc to manually call methods and navgate, however I was hoping to use the powerful builtin capabilities of that library.
I was thinking that since TLI.ClassInfoFromObject(Object As IUnknown) can be used to query the IDispatch::GetTypeInfo method, I could manually construct a dummy object that implements just this method to allow the TypeInfo to be read into memory. Similar to manually defining IEnumVariant where most of the methods just return E_NOTIMPL = &H80004001. Does this sound feasible? Is there a simpler way to access the TypeInfo from a pointer using VBA?
Update
To be clear, my problem is I can't find a way to declare the ITypeInfo interface and allow me to work with it directly - VBA accesses IUnknownfrom stole2.tlb so I can use that fine, but the only place I can find ITypeInfo declared is in mscorlib.dll, but it doesn't have the COMVisible attribute so there's no way to access it in VBA, AFAIK, and VBA doesn't have an equivalent to [ComImport] to let you define it with a GUID yourself. So I want to use tlbinf32.dll to save me having to use raw pointers.
Turns out tlbinf32.dll supports this out of the box but it's hidden. From the help file:
ITypeLib As IUnknown
TypeLibInfoFromITypeLib(ByVal ptlib As IUnknown) As TypeLibInfo
Inside every TypeLibInfo is a reference to an ITypeLib instance. In
fact, the TypeLibInfo object can be viewed as a wrapper on the
ITypeLib interface which is easier to program against than ITypeLib
itself. To see if two TypeLibInfo objects actually refer to the same
internal object, use VB's Is operator with the ITypeLib property of
the two objects. The Is operator will usually return False for
TypeLibInfo objects which actually correspond to the same underlying
type, but not for the internal ITypeLib pointers. The ITypeLib
property is settable, so you can put a TypeLibInfo object on top of an
existing ITypeLib.
If you have an ITypeLib reference and want to use TLI objects, then
you can call TLI.TypeLibInfoFromITypeLib to generate a fully
functional TypeLibInfo object.
The ITypeLib property and TypeLibInfoFromITypeLib method are
considered advanced features and are marked as hidden.
emphasis my own
... similar story for an ITypeInfo pointer
So how to use? Quite simple. First a way to get the IUnknown from a pointer. e.g:
Public Function ObjectFromObjPtr(ByVal Address As LongPtr) As IUnknown
Dim result As IUnknown
MemLongPtr(VarPtr(result)) = Address
Set ObjectFromObjPtr = result
MemLongPtr(VarPtr(result)) = 0
End Function
Private Property Let MemLongPtr(ByVal dest as LongPtr, ByVal value As LongPtr)
CopyMemory ByVal dest, value, LenB(value)
End Property
Followed by the call
Dim ITypeLibPtr As LongPtr
ITypeLibPtr = ... 'get the raw pointer
Dim ITypeLibObj As IUnknown
Set ITypeLibObj = ObjectFromObjPtr(ITypeLibPtr)
Dim NiceTypeLib As tli.TypeLibInfo
Set NiceTypeLib = tli.TypeLibInfoFrom(ITypeLibITypeLibObj)
or words to that effect
I understand arrays. I know some java from 15 years ago, and I know about classes, objects, instances, variables, static variables and constructors. Not so familiar with these things in VB.
I don't understand object collections..
Suppose I draw a listbox, and name it lstbox1
I see that I can say lstbox1.items.item(0) or lstbox1.items(0)
The fact that I can say listbox1.items(0) puzzles me a little bit. If an object collection is not an array, then it's clearly not an object either.
This link https://msdn.microsoft.com/en-us/library/yb7y698k(v=vs.90).aspx says Collection is an object.
But then what is items(0) items is not a class so that can't be calling a constructor... and items is not a method, it's a property that is an instance of object collection, so I can't see how the (0) works.. I know what it refers to the first object, the element with index 0, but I don't understand how that can work. I know blah(0) would work if blah was an array. And I am sure lstbox1.items is not an array of object collections it's just 1 object collection.
Is it a data structure like an Array, that has its own syntax.. for example one can say dim blah as Integer() or dim blah() as Integer and thus define it without even stating the class Array. Is ObjectCollection a bit like that? It does seem to allow (index) after an instance of it.
VB has a concept called Default Properties. In the case of an ItemCollection type (and a number of other types, as well), the Item property is the default property for the collection. This allows you to use the shorthand from the question.
It's basically just a bit of syntactical sugar. When you say, lstbox1.items(0), it's just shorthand for lstbox1.items.item(0).
Also, don't mistake the various collection types for simple arrays. They will have similar syntax, but every collection type has it's own quirks and use cases, and it's generally worth your time to look at the documentation for the specific type you're working with. Don't assume something is an array, just because you can access the items by index.
Think about this just as a "language feature". This is what really called indexer property. It is implemented as default property in vb.net. In c# implementation is different. The data structure behind it could be anything you want - array, list, dictionary, hashtable. The fact is - it lets you access something by supplying a parameter without calling property syntax. myParentObject(1) instead of myParentObject.GetChildObject(1)
In VB, default property must be indexed.
listbox1 . Items . item(0) --> listbox1 - main object that has property Items , which is a collection. This collection has property item, which is default property or indexer. Item is a property exposing single object from underlying collection.
I use pin_ptr for cli::array types and everything works fine.
Is it possible to do the same with System::Collection::Generic::List which I believe is a contiguous block of memory?
The obvious
List<double>^ stuff = gcnew List<double>( 10 );
cli::pin_ptr<double> resultPtr = &stuff[ 0 ];
gives a compiler error "error C2102: '&' requires l-value" presumably because the indexed property returns something that is not a l-value! So is there another way to do this. I have played around with interior_ptr as well but have not found anything that works yet.
I know that I could call ToArray on the List but the whole point is to not copy stuff around.
No, this is not possible.
True, a List does use an array behind the scenes, but the [] operator is different. With an array, [] is simple pointer math, but with a List, [] is a full-fledged method call. That's why the & isn't working: you can take the address of an array location, but you can't take the address of a value returned from a method.
Think about it like this: If they wanted to, they could change the implementation of List without changing its external interface. It would be possible to change List to store the list contents in memory gzip-compressed. In that case, stuff[0] is generated on-the-fly by the [] method which does the decompression, so there is no single memory location that contains stuff[0] to pin.
Edit
Yes, internal to the List class, the contents are contiguous in memory. You can see this in the source that Microsoft has provided. However, the List class does not make that array public: The public interface to the List class is the public methods & properties, only. The public methods & properties present a contract, and the array that the values are stored in are not part of that contract. Microsoft would never do this, but they could do a gzip-compressed implementation of List, and the public contract of the List class wouldn't change. You should only write your code to the public methods & properties of a class, not to the internals that may change at any time.
I want to 'send' collection that contain numbers ( double ).
I try to add array to my DataContract but its fail ( thru exception .. when i remark the array type its work fine ).
How can i do it ?
Thanks for any help.
Collection Serialization happens automatically only when the collection in the contract is a concrete collection (that is, not an interface) and is serializable (annotated with the Serializable attribute). If that is the case, WCF can automatically serialize the collection as an array of the collection’s type as long as the collection contains an Add operation. This holds true for both the built-in .NET collections and for any of your own custom collections that implement the IEnumerable or IEnumerable interface; as long as they are serializable and have an Add operation, they can be serialized to arrays automatically.
If your collection does not meet these constraints specify the CollectionDataContractAttribute.
[CollectionDataContract(Name = "MyCollectionOf{0}")]
Yeah, I'm struggling with that. I cannot distinguish among them because every explanation I read is so unclear and philosophical enough. Can someone clear up these definitions for me ? Thanks guys.
These definitions apply as much to procedural-programming as oop ? Thanks.
Over time, the way people use each of these terms has changed (and will likely keep changing), but here's what they probably mean if you're reading articles written in the last decade or so:
Functions (aka subroutines) are relatively self-contained, relatively independent pieces of code that make up a larger program.
Methods are functions attached to specific classes (or instances) in object-oriented programming.
Properties are an object-oriented idiom. The term describes a one or two functions (depending on the desired program behavior) - a 'getter' that retrieves a value and a 'setter' that sets a value. By convention, properties usually don't have many side-effects. (And the side-effects they do have usually have limited scope: they may validate the item being set, notify listeners of a change, or convert an object's private data to or from a publicly-declared type.)
Function is a combination of instructions coupled together to achieve some result. It may take arguments and return result. If a function doesn't return a result it is usually called a procedure. Examples:
function drawLine(x1, y1, x2, y2):
// draws a line using Bresenham's algorithm from x1,y1 to x2,y2.
// doesn't return anything
function <number> add(a, b):
// adds a to b and returns the result as a number
return a + b
So functions are to do some particular work. For example, when you need to draw a polygon of 3 lines as a part of a vector image it is more convenient to call drawLine thrice than to put all the routine for line drawing inline.
Methods ("member functions") are similar to functions, they belongs to classes or objects and usually expresses the verbs of the objects/class. For example, an object of type Window usually would have methods open and close which do corresponding operations to the object they belong.
Properties are as in everyday language and technically are fields of objects/classes with dedicated getter/setter routines (which can be considered as methods. There are languages that don't have properties and this behavior is achieved using a private field+get/set methods.).
Field - A field is a variable of any type that is declared directly in a class or struct. Fields are members of their containing type.
Property - A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field.
Method - A method is a code block containing a series of statements. In C#, every executed instruction is done so in the context of a method.
Procedure - A procedure is a code block containing a series of statements.
Function - A function is a code block containing a series of statements. That return operation result.
Function is a standalone construction like trim(), strlen(), fopen() etc.
function myAbcFunction() { ... }
Method is a function of object. It is defined in class. Property is just property of object:
class MyClass {
public $property; // Public property: $objInstance->property
protected $property2; // Protected property
public function doSth() {
// That's a method. $objInstance->doSth();
}
}
I suggest read the manual Classes and Objects chapter.
In OOP the primary structure is an object.
Method is a named action which can be applied to the object.
Property is a named value, which the object has. For example, object Human has the property 'Age'.
function is a more general thing, than a method. It is just an action, that doesn't belong to any object. But method is a function that belongs to the object.
a)Function
Refers to block of statements that perform a particular task and return a value.
b)Procedure
Refers to the building blocks of a program that do not return a value when called.
c)Method
Refers to the action that object can perform.