IDispatch::Invoke
dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr)DISPID dispidMember
REFIID riid
LCID lcid
unsigned short wFlags
DISPPARAMS FAR* pdispparams
VARIANT FAR* pvarResult
EXCEPINFO FAR* pexcepinfo
unsigned int FAR* puArgErr Provides access to properties and methods exposed by an object. The dispatch function DispInvoke provides a standard implementation of IDispatch::Invoke. Parameters dispidMember Identifies the member. Use GetIDsOfNames or the object's documentation to obtain the dispatch identifier. riid Reserved for future use. Must be IID_NULL. lcid The locale context in which to interpret arguments. The lcid is used by the GetIDsOfNames function, and is also passed to Invoke to allow the object to interpret its arguments in a locale-specific way. Applications that don't support multiple national languages can ignore this parameter. See "Supporting Multiple National Languages," in Chapter 2, for more information. wFlags Flags describing the context of the Invoke call, as follows:
Value
| Description
|
DISPATCH_METHOD
| The member is being invoked as a method. If a property has the same name, both
this and the DISPATCH_PROPERTYGET flag may be set.
|
DISPATCH_PROPERTYGET
| The member is being retrieved as a property or data member.
|
DISPATCH_PROPERTYPUT
| The member is being changed as a property or data member.
|
DISPATCH_PROPERTYPUTREF
| The member is being changed via a reference assignment, rather than a value
assignment. This flag is valid only when the property accepts a reference to an
object.
|
SCODE
| Meaning
|
S_OK
| Success.
|
DISP_E_BADPARAMCOUNT
| The number of elements provided DISPPARAMS is different from the number of
arguments accepted by the method or property.
|
DISP_E_BADVARTYPE
| One of the arguments in rgvarg is not a valid variant type.
|
DISP_E_EXCEPTION
| The application needs to raise an exception. In this case the structure passed
in pexcepinfo should be filled in.
|
DISP_E_MEMBERNOTFOUND
| The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.
|
DISP_E_NONAMEDARGS
| This implementation of IDispatch does not support named arguments.
|
DISP_E_OVERFLOW
| One of the arguments in rgvarg could not be coerced to the specified type.
|
DISP_E_PARAMNOTFOUND
| One of the parameter dispatch IDs does not correspond to a parameter on the
method. In this case puArgErr should be set to the first argument that contains the error.
|
DISP_E_TYPEMISMATCH
| One or more of the arguments could not be coerced. The index within rgvarg of the first parameter with the incorrect type is returned in the puArgErr parameter.
|
DISP_E_UNKNOWNINTERFACE
| The interface ID passed in riid is not IID_NULL.
|
DISP_E_UNKNOWNLCID
| The member being invoked interprets string arguments according to the locale
ID (LCID), and the LCID is not recognized. If the LCID is not needed to
interpret arguments, this error should not be returned.
|
DISP_E_PARAMNOTOPTIONAL
| A required parameter was omitted.
|
IDispatch FAR* pdisp = (IDispatch FAR*)NULL; OLECHAR FAR* szMember = "simple"; DISPID dispid; DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; hresult = CoCreateInstance(CLSID_CMyObject, NULL, CLSCTX_SERVER,
IID_Unknown, (void FAR* FAR*)&punk); hresult = punk->QueryInterface(IID_IDispatch,
(void FAR* FAR*)&pdisp); hresult = pdisp->GetIDsOfNames(IID_NULL, &szMember, 1,
LOCALE_SYSTEM_DEFAULT, &dispid) ; hresult = pdisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, NULL, NULL, NULL); The example invokes a method named Simple on an object of the class CMyObject. First, it calls CoCreateInstance, which instantiates the object and returns a pointer to the object's IUnknown interface (punk). Next, it calls QueryInterface, receiving a pointer to the object's IDispatch interface (pdisp), and then uses pdisp to call the object's GetIDsOfNames function, passing the string 'Simple' in szMember to get the dispatch ID for the Simple method. With the dispatch ID for Simple in dispid, it calls Invoke to invoke the method, specifying DISPATCH_METHOD for the wFlags parameter, and using the system default locale. To further simplify the code, the example declares a DISPPARAMS structure named dispparamsNoArgs appropriate to an Invoke call with no arguments. Because the Simple method takes no arguments and returns no result, the puArgErr and pvarResult parameters are NULL. In addition, the example passes NULL for pexcepinfo, indicating that it is not prepared to handle exceptions and will handle only HRESULT errors. Most methods, however, take one or more arguments. To invoke these methods, you must fill in the DISPPARAMS structure, as described in "Passing Parameters." OLE Automation defines special dispatch IDs for invoking an object's Value (default), _NewEnum, and Evaluate members. See DISPID. Getting and Setting Properties Properties are accessed the same way as methods, except that DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT is specified instead of DISPATCH_METHOD. Note that some languages can't distinguish between retrieving a property and calling a method; both the DISPATCH_PROPERTYGET and DISPATCH_METHOD flags should be set in this case. The following example gets the value of a property named On. Assume that the object has been created and its interfaces queried as in the previous example: VARIANT FAR *pvarResult; //...code omitted for brevity... szMember = "On"; hresult = pdisp->GetIDsOfNames(IID_NULL, &szMember, 1,
LOCALE_SYSTEM_DEFAULT, &dispid) ; hresult = pdisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, pvarResult, NULL, NULL); As in the previous example, the code calls GetIDsOfNames for the dispatch ID of the On property, then passes the ID to Invoke. Invoke returns the property's value in pvarResult. In general, the return value does not have VT_BYREF set. However, implementors may set this bit and return a pointer to the return value, if the lifetime of the return value is the same as that of the object. To change the property's value, the call looks like this: VARIANT FAR *pvarResult; DISPPARAMS dispparams; //...Code omitted for brevity... szMember = "On"; dispparams.rgvarg[0].vt = VT_BOOL; dispparams.rgvarg[0].bool = FALSE; dispparams.rgdispidNamedArgs = DISPID_PROPERTYPUT; dispparams.cArgs = 1; disparams.cNamedArgs = 1; hresult = pdisp->GetIDsOfNames(IID_NULL, &szMember, 1,
LOCALE_SYSTEM_DEFAULT, &dispid) ; hresult = pdisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); The new value for the property ( the Boolean value False) is passed as an argument when the On property's put function is invoked. Note that the dispatch ID for the argument is DISPID_PROPERTYPUT. This special dispatch ID is defined by OLE Automation to designate the parameter that contains the new value for a property's put function. The remaining details of the DISPPARAMS structure are described in the next section, "Passing Parameters." The DISPATCH_PROPERTYPUT flag in the example above indicates that a property is being set by value. In Visual Basic, the following statement assigns the Value (default) property of YourObj to the property Prop: MyObj.Prop = YourObj This statement should be flagged as a DISPATCH_PROPERTYPUT. Similarly, statements like the following assign the Value property of one object to the Value property of another object: Worksheet.Cell(1,1) = Worksheet.Cell(6,6) MyDoc.Text1 = YourDoc.Text1 These statements result in a PROPERTY_PUT operation on Worksheet.Cell(1,1) and MyDoc.Text1. Use the DISPATCH_PROPERTYPUTREF flag to indicate a property or data member that should be set by reference. For example, the following Visual Basic statement assigns the pointer to YourObj to the property Prop, and should be flagged as DISPATCH_PROPERTYPUTREF: Set MyObj.Prop = YourObj The Set statement causes a reference assignment, rather than a value assignment. Note that the right side parameter is always passed by name, and should not be accessed positionally. Passing Parameters Arguments to the method or property being invoked are passed in the DISPPARAMS structure. This structure consists of a pointer to an array of arguments represented as variants, a pointer to an array of dispatch IDs for named arguments, and the number of arguments in each array. typedef struct FARSTRUCT tagDISPPARAMS{ VARIANTARG FAR* rgvarg; // Array of arguments DISPID FAR* rgdispidNamedArgs; // Dispatch IDs of named arguments unsigned int cArgs; // Number of arguments unsigned int cNamedArgs; // Number of named arguments } DISPPARAMS; The arguments are passed in the array rgvarg[ ], with the number of arguments passed in cArgs. Place the arguments in the array from last to first, so rgvarg[0] has the last argument and rgvarg[cArgs 1] has the first argument. The method or property may change the values of elements within the array rgvarg only if they have the VT_BYREF flag set; otherwise they should be considered read only. A dispatch invocation can have named arguments as well as positional arguments. If cNamedArgs is 0, all the elements of rgvarg[ ] represent positional arguments. If cNamedArgs is nonzero, each element of rgdispidNamedArgs[ ] contains the DISPID of a named argument, and the value of the argument is in the matching element of rgvarg[ ]. The dispatch IDs of the named arguments are always contiguous in rgdispidNamedArgs, and their values are in the first cNamedArgs elements of rgvarg. Named arguments can't be accessed positionally and vice versa. The DISPID of an argument is its zero-based position in the argument list. For example, the following method takes three arguments: BOOL _export CDECL CCredit::CheckCredit(BSTR bstrCustomerID, // DISPID = 0
BSTR bstrLenderID, // DISPID = 1
CURRENCY cLoanAmt) // DISPID = 2 { ... // Code omitted. } If you include the DISPID with each named argument, you may pass the named arguments to Invoke in any order. For example, if a method is to be invoked with two positional arguments, followed by three named arguments (A, B, and C), using the following hypothetical syntax, then cArgs would be 5, and cNamedArgs would be 3: object.method("arg1", "arg2", A := "argA", B := "argB", C: = "argC") The first positional argument would be in rgvarg[4]. The second positional argument would be in rgvarg[3]. The ordering of named arguments should be immaterial to the IDispatch implementation, but these are also generally passed in reverse order. The argument named A would be in rgvarg[2], with the DISPID of A in rgdispidNamedArgs[2]. The argument named B would be in rgvarg[1], with the corresponding DISPID in rgdispidNamedArgs[1]. The argument named C would be in rgvarg[0], with the DISPID corresponding to C in rgdispidNamedArgs[0]. The following diagram illustrates the arrays and their contents. You can also use Invoke on members with optional arguments, but all the optional arguments must be of type VARIANT. As with required arguments, the contents of the argument vector depend on whether the arguments are positional or named. The invoked member must ensure that the arguments are valid; Invoke merely passes the DISPPARAMS structure it receives. Omitting named arguments is straightforward. You simply pass the arguments in rgvarg and their DISPIDs in rgdispidNamedArgs. To omit the argument named B, in the preceding example, you would set rgvarg[0] to the value of C, with its DISPID in rgdispidNamedArgs[0]; and rgvarg[1] to the value of A, with its DISPID in rgdispidNamedArgs[1]. The subsequent positional arguments would occupy elements 2 and 3 of the arrays. In this case, cArgs is 4, and cNamedArgs is 2. If the arguments are positional (unnamed), set cArgs to the total number of possible arguments, cNamedArgs to zero, and pass VT_ERROR as the type of the omitted arguments, and DISP_E_PARAMNOTFOUND as the value. For example, the following code invokes ShowMe (,1): VARIANT FAR *pvarResult; EXCEPINFO FAR *pExcepinfo; unsigned int FAR *puArgErr; DISPPARAMS dispparams; //...Code omitted for brevity... szMember = "ShowMe"; hresult = pdisp->GetIDsOfNames(IID_NULL, &szMember, 1,
LOCALE_SYSTEM_DEFAULT, &dispid) ; dispparams.rgvarg[0].vt = VT_I2; dispparams.rgvarg[0].ival = 1; dispparams.rgvarg[1].vt = VT_ERROR; dispparams.rgvarg[1].scode = DISP_E_PARAMNOTFOUND; dispparams.cArgs = 2; disparams.cNamedArgs = 0; hresult = pdisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, pvarResult, pExcepinfo, puArgErr); The example takes two positional arguments, but omits the first. Therefore, rgvarg[0] contains 1, the value of the last argument in the argument list, and rgvarg[1] contains VT_ERROR and the error scode, indicating the omitted first argument. The calling code is responsible for releasing all strings and objects referred to by rgvarg[ ] or placed in *pvarResult. As with other parameters that are passed by value, if the invoked member must maintain access to a string after returning, the string should be copied. Similarly, if the member needs access to a passed object pointer after returning, it must call AddRef on the object. A common example occurs when an object property is changed to refer to a new object, using the DISPATCH_PROPERTYPUTREF flag. For those implementing IDispatch::Invoke, OLE Automation provides the DispGetParam function to retrieve parameters from the argument vector and coerce them to the proper type. See the reference page for DispGetParam later in this chapter, for details. Indexed Properties When you invoke indexed properties of any dimension, you need to pass the indexes as additional arguments. To set an indexed property, place the new value in the first element of the rgvarg[ ] vector, and the indexes in the subsequent elements. To get an indexed property, pass the indexes in the first n elements of rgvarg and the number of indexes in cArg. Invoke returns the value of the property in pvarResult. OLE Automation stores array data in column-major order, which is the same ordering scheme used by Visual Basic and FORTRAN, but different from C, C++, and Pascal. If you're programming in C, C++, or Pascal, you need to pass the indexes in the reverse order. The following example shows how to fill the DISPPARAMS structure in C++: dispparams.rgvarg[0].vt = VT_I2; dispparams.rgvarg[0].iVal = 99; dispparams.rgvarg[1].vt = VT_I2; dispparams.rgvarg[1].iVal = 2; dispparams.rgvarg[2].vt = VT_I2; dispparams.rgvarg[2].iVal = 1; dispparams.rgdispidNamedArgs = DISPID_PROPERTYPUT; dispparams.cArgs = 3; disparams.cNamedArgs = 1; The example changes the value of Prop[1,2] to 99. The new property value is passed in rgvarg[0]. The rightmost index is passed in rgvarg[1], and the next index in rgvarg[2]. The cArgs field specifies the number of elements of rgvarg[ ] that contain data, and cNamedArgs is 1, indicating the new value for the property. Property collections are an extension of this feature. Raising Exceptions During Invoke When you implement IDispatch::Invoke, you can choose to communicate errors either through the normal return value or by raising an exception. An exception is a special situation that is normally dealt with by jumping to the nearest enclosing exception handler. To raise an exception, IDispatch::Invoke returns DISP_E_EXCEPTION and fills the structure passed through pexcepinfo with information about the cause of the exception or error. You can use the information to understand the cause of the exception and deal with it as necessary. The exception information structure includes an error code number which identifies the kind of exception, a string which describes the error in a human-readable way, and a Help file and Help context number which can be passed to Windows Help for details about the error. At a minimum, the error code number must be filled in with a valid number. If you consider IDispatch as another way to call C++ style methods in an interface, EXCEPINFO models the throwing of an exception or longjmp() call by such a method. Returning Errors Invoke returns DISP_E_MEMBERNOTFOUND if one of the following conditions occurs:
- A member or parameter with the specified DISPID and matching cArgs can't be found, and the parameter is not optional.
- The member is a void function and the caller didn't set pvarResult to NULL.
- The member is a read-only property and the caller set wFlags to DISPATCH_PROPERTYPUT or DISPATCH_PROPERTYPUTREF.
- Software for developers
-
Delphi Components
.Net Components
Software for Android Developers - More information resources
-
MegaDetailed.Net
Unix Manual Pages
Delphi Examples - Databases for Amazon shops developers
-
Amazon Categories Database
Browse Nodes Database