This paper studies how to JS and other scripting languages communicate with ActiveX controls, how to pass various types of parameters, and COM's IDispatch interface. Using a similar approach, you can generalize to all other scripting languages, such as Lua,autocad .
This article will study the following aspects:
1. Shaping an array to pass parameters
2. String parameter, String return value
3. Modifying incoming string content
4. Array parameters
5. IDispatch Interface Introduction
6. Modifying input array Contents
7. Adding array contents
8. Using the array-pass method, JS calls S4execute ()
Due to the length of this article, so will be published in serial form, a main discussion 1-3 points, serial two main discussion 4-6 points, serial three mainly discuss 7-8 points.
(iv) Array parameters
1. When used, it is sometimes necessary to use array parameters, such as the Inbuff/outbuff of S4execute ().
2. js in the Shaping data byte/short/int, etc., so the array element type is int (VT_I4 in COM, where I represents shaping, 4 means 4 bytes)
3. The array in JS is a IDispatch object in COM and can be manipulated through the IDispatch interface API. For IDispatch please see the next section for an introduction.
4. C + + definition in COM
The following code defines two functions Getarraynumberofindex, getarraylength two functions, each of which gets the array length and gets the specified ordinal element
The following code means, refer to the next section "Introduction to IDispatch Interface"
JS Array is a IDispatch object in COM, gets the length, actually gets the property value named "Length" in it.
And getting the last array is actually getting the property value named "4" (assuming 5 elements)
STDMETHODIMP Cjsatl::getlastelement (VARIANT varray, long* retVal)
{
int len = 0;
HRESULT hr = Getarraylength (Varray.pdispval, &len);
if (FAILED (HR))
return HR;
hr = Getarraynumberofindex (Varray.pdispval, len-1, RetVal);
return S_OK;
}
// ***
Get the JavaScript array length
Array length in JavaScript computes only the part of the list that is labeled as a number
// ***
HRESULT getarraylength (idispatch* pdisp, int* plength)
{
BSTR varName = L "Length";
VARIANT Varvalue;
Dispparams Noargs = {null, NULL, 0, 0};
DISPID DispID;
HRESULT hr = 0;
hr = Pdisp->getidsofnames (Iid_null, &varname, 1, Locale_user_default, &dispid);
if (FAILED (HR))
return HR;
hr = Pdisp->invoke (DispID, Iid_null, Locale_system_default, Dispatch_propertyget, &noargs, &varValue, NULL, NULL);
if (SUCCEEDED (HR))
{
*plength = Varvalue.intval;
return HR;
}
Else
{
return HR;
}
}
// ***
Gets the integer element value at the specified position in the JavaScript array
// ***
HRESULT Getarraynumberofindex (idispatch* pdisp, int index, int * pValue)
{
CComVariant varName (index, VT_I4); Array subscript
Dispparams Noargs = {null, NULL, 0, 0};
DISPID DispID;
VARIANT Varvalue;
HRESULT hr = 0;
Varname.changetype (VT_BSTR); Converts an array subscript to a digital type for GetIDsOfNames
//
Gets the procedure to access an array by subscript, saving the procedure name in DispID
//
hr = Pdisp->getidsofnames (Iid_null, &varname.bstrval, 1, Locale_user_default, &dispid);
if (FAILED (HR))
return HR;
//
Calls a COM procedure, accesses the specified subscript array element, and saves the element value in Varvalue based on DISPID
//
hr = Pdisp->invoke (DispID, Iid_null, Locale_system_default, Dispatch_property GET, &noargs, &varValue, NULL, NULL);
if (SUCCEEDED (HR))
{
*pvalue = Varvalue.intval; To remove an array element as an int type
return HR;
}
Else
{
return HR;
}
}
5. js in the call
function Test_get_last ()
{
var array = new Array (0, 1, 2, 3); Defining arrays
try {
var obj = document.getelementbyidx_xx_x ("obj");
var lastelement = obj. Getlastelement (array); Gets the last element of the array
Alert ("Lastelement:" + lastelement);
} catch (e) {
Alert ("JS ERROR:" + e.message);
}
}
6. Test execution
Array definition: {0,1,2,3}
Last element: 3
(v) Introduction of IDispatch interface
1. When the C program is called, the caller must know the interface specification beforehand (for example, parameter type, parameter byte length, parameter order, etc.). Because these specifications differ in different languages, COM does not resolve calls between different languages and provides the IDispatch interface.
2. IDispatch requires that its instance be self-describing, that is, after getting an object, you can get the calling method directly from the object without having to be explicit beforehand.
3. In IDispatch, the correlation type is specified by Vt_type, for example, VT_I4 is 4-byte shaped, VT_BSTR is a Unicode string, and Vt_dispatch represents a IDispatch object
4. Assigns an integer ID and a string name to each attribute or function in the object, and the caller can determine how to invoke it through the name string. For example, if the name is a property of "length", the caller is understood to be length. Because the property is usually understood by name, the name description should be accurate enough. For example, it is inappropriate to implement the integer addition function with a function named "Length ()".
5. When using the IDispatch object, the Prime Minister calls IDispatch::GetIDsOfNames () to take the property, function name as an argument, and get the corresponding property, function ID.
6. Call IDispatch::Invoke () to invoke the ID as an argument, and actually call the function.
7. If an invoke () call is obtained for the property value, the DISPATCH_PROPERTYGET flag is passed in.
8. If the property value is set, the Invoke () is called when the DISPATCH_PROPERTYPUT flag is passed in. The Dispparams parameter is specified to modify the value of the property. Dispparams structure description after see.
9. If the Invoke function is called, the DISPATCH_METHOD flag is passed in when invoke () is called. If the method requires a parameter, it is specified by the Dispparams parameter of IDispatch::Invoke ().
Examples of use of DISPPARAMS structures:
Dispparams Dispparams;
Dispparams.rgdispidnamedargs = &dispidOfNamedArgs;
Dispparams.cargs = 1;
Dispparams.cnamedargs = 1;
Dispparams.rgvarg = new Variantarg[1];
DISPPARAMS.RGVARG[0].VT = VT_I4;
Dispparams.rgvarg[0].intval = 123;
A. The above code is a simple example of how to pass a parameter to a method, first creating a Dispparams object
B. Cargs specifies the number of arguments in the method.
C. Cnamedargs specifies the number of parameters that have been named in the method. (a named parameter is a concept that corresponds to an unnamed parameter.) Some languages can define indeterminate parameters, at which point the parameter is not assigned a name in the description of the IDispatch, but it is called with an unnamed parameter. For example, JS in the Array object's push () method, can support an indefinite number of parameters)
D. Rgvarg is an actual parameter array, each element represents a parameter, where. VT indicates the data type of this element, and the Intval item is a C + + federated structure, such as VT = = VT_I4, should be assigned in intval = xxx; if VT = = VT_BSTR, then Assign value in bstrval = XXX mode
11. Example: two parameters, all of them are non-named parameters, the first one is shaping, the second is a BSTR type
Dispparams Dispparams;
Dispparams.rgdispidnamedargs = NULL;
Dispparams.cargs = 2;
Dispparams.cnamedargs = 0;
Dispparams.rgvarg = new Variantarg[2]; 2 parameters, allocating 2 spaces
DISPPARAMS.RGVARG[0].VT = VT_I4; Plastic
Dispparams.rgvarg[0].intval = 123;
DISPPARAMS.RGVARG[1].VT = VT_BSTR; String type
Dispparams.rgvarg[1].bstrval = L "ABCD";
(vi) Modifying the contents of an input array
1. The fifth section describes how to pass array parameters from JS to COM, and how to get parameters in COM. This section describes how to modify the incoming array of JS in COM.
2. When modifying the JS array value, first get the DispID of the specified ordinal element by GetIDsOfNames, then call Invoke (), the incoming Dispatch_propertyput flag indicates the write operation, This element type and element values are indicated in the DISPPARAMS structure.
3. C + + definition in COM
STDMETHODIMP Cjsatl::arraymodiy (VARIANT varray)
{
Setarraynumberofindex (varray.pdispval, 0, 123); Modifies the [0] element of the array, with a value of
return S_OK;
}
// ***
Sets the integer element value at the specified position in the JavaScript array
// ***
HRESULT Setarraynumberofindex (idispatch* pdisp, int index, int value)
{
CComVariant varName (index, VT_I4);
DISPID DispID;
CComVariant Varvalue;
HRESULT hr = 0;
Varname.changetype (VT_BSTR); Converts an array subscript to a digital type for GetIDsOfNames
hr = Pdisp->getidsofnames
(Iid_null, &varname.bstrval, 1, Locale_user_default, &dispid);
if (FAILED (HR))
return HR;
DispID dispidput = dispid_propertyput; Put operation
Dispparams Dispparams;
Dispparams.rgvarg = new Variantarg[1]; Initialize Rgvarg
DISPPARAMS.RGVARG[0].VT = VT_I4; Data type
Dispparams.rgvarg[0].intval = value; Update values
Dispparams.cargs = 1; Number of parameters
Dispparams.cnamedargs = 1; Parameter name
Dispparams.rgdispidnamedargs = &dispidPut; Operation DispID, indicating that this parameter applies to the put operation
hr = Pdisp->invoke (DispID, Iid_null, Locale_user_default, Dispatch_property PUT, &dispparams, NULL, NULL, NULL);
return HR;
}
4. JS Call
function Test_set_first ()
{
var array = new Array (0, 1, 2, 3);
try {
var obj = document.getelementbyidx_xx_x ("obj");
Obj. Arraymodiy (array);
Alert ("First element:" + array[0]);
} catch (e) {
Alert ("JS ERROR:" + e.message);
}
}
5. Test execution
Original array: {0,------
Modified: {123,1,2,3}
(go) How to pass data between JavaScript and ActiveX 2