登录
首页 PC Based IPC 工控机 PC Based IPC 工控机
回帖 发帖
正文

主题:CVI ActiveX Controller For Visual Basic

点击:1549 回复:0


labwindows/cvi activex controller for visual basic 6.0 users
9 评级 | 3.33 out of 5
the labwindows/cvi activex controller wizard generates c wrappers to call activex servers. this document, which describes the wrappers generated by this tool, is intended for users who are more familiar using microsoft visual basic 6.0 to control activex servers or controls.
introduction to labwindows/cvi activex controller wizard
complete the following steps to generate wrappers with the activex controller wizard:
select tools»create activex controller to open the activex controller wizard and click next in the welcome panel.
the labwindows/cvi activex controller wizard displays all the activex servers and controls registered on your computer. you also can browse to and select an unregistered server or type library that is not listed. select an activex server and click next.
enter a target file name and prefix. the wizard-generated code is in the form of a labwindows/cvi instrument—this is similar to a c library with labwindows/cvi function panel support. based on the target file name, for example, myclient.fp, labwindows/cvi generates four files—myclient.fp, myclient.sub, myclient.c, and myclient.h.
click compatibility options to select one of the following options for wrapper functions to access properties:
-- per property—if you select the per property option, the wizard will generate individual wrapper functions for each activex property.
-- per object—if you select the per object option, the wizard will generate a wrapper function for each activex object to access all the properties of that object.
-- per server—if you select the per server option, the wizard will generate a wrapper function to access all the properties of all the activex objects in the server.
note that the per object and per server options are available only if the server exposes idispatch based interfaces. national instruments recommends that you use the default per property option because it supports both dispatch interfaces and custom interfaces.
click ok in the compatibility options dialog box and click next.
click advanced options to open the activex controller advanced options dialog box. in this dialog box, the wizard displays the objects, methods, and properties of the activex server and allows you to change the names used in generated wrapper functions and specify which methods and properties you want labwindows/cvi to create wrapper functions for.
click ok to generate the labwindows/cvi instrument.
example server
for example, consider that you have an activex server named myserver, with one object called myobject exposing imyinterface1 and imyinterface2 interfaces. in this example, imyinterface1 comprises the mymethod1() method and the myproperty1 integer property. imyinterface2 comprises the mymethod2() method and the myproperty2 integer property. figure 1 illustrates this object.
figure 1: example activex server object
wrapper functions
wrapper naming convention
the activex controller wizard generates a function panel class for each interface implemented in the activex server. in each of these function panel classes, the wizard generates new, active, and open functions if the interface is implemented by a creatable object. the names of the functions are generated according to the following rules:
_new
_active
_open
note that if the same interface is implemented by another creatable object, for example, myobject2, then the object names also are included in the wrapper function names according to the following rules:
_new
_active
_open
using the preceding rules results in the following names:
myserver_newmyobjectimyinterface1
myserver_newmyobject2imyinterface1
.. .. ..
the labwindows/cvi activex controller wizard generates the following wrapper functions for the example server with the property access functions option set to per property and myserver as the instrument prefix.
function panel class: imyinterface1
hresult cvifunc myserver_newimyinterface1 (
const char *server,
int supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_openimyinterface1 (
const char *filename,
const char *server,
int supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_activeimyinterface1 (
const char *server,
int supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_imyinterface1mymethod1 (
caobjhandle objecthandle,
errorinfo *errorinfo);
hresult cvifunc myserver_imyinterface1getmyproperty1 (
caobjhandle objecthandle,
errorinfo *errorinfo,
int *myproperty1);
hresult cvifunc myserver_imyinterface1setmyproperty1 (
caobjhandle objecthandle,
errorinfo *errorinfo,
int myproperty1);
function panel class: imyinterface2
hresult cvifunc myserver_newimyinterface2 (
const char *server,
int  supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_openimyinterface2 (
const char *filename,
const char *server,
int supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_activeimyinterface2 (
const char *server,
int supportmultithreading,
lcid locale,
int reserved,
caobjhandle *objecthandle);
hresult cvifunc myserver_imyinterface2mymethod2 (
caobjhandle objecthandle,
errorinfo *errorinfo);
hresult cvifunc myserver_imyinterface2getmyproperty2 (
caobjhandle objecthandle,
errorinfo *errorinfo,
int *myproperty2);
hresult cvifunc myserver_imyinterface2setmyproperty2 (
caobjhandle objecthandle,
errorinfo *errorinfo,
int myproperty2);
the myserver_newimyinterface1 and myserver_newimyinterface2 wrapper functions create new instances of the object and are equivalent to the createobject function or new operator in visual basic. the myserver_activeimyinterface1 and myserver_activeimyinterface2 wrapper functions return the registered active object and are equivalent to calling the visual basic getobject function with the path omitted. the myserver_openimyinterface2 and myserver_openimyinterface2 wrapper functions create the object from a file and are equivalent to calling the visual basic getobject function with a valid path.
in the wrapper functions, activex objects are represented by the labwindows/cvi caobjhandle type. this type is equivalent to the visual basic object type. the generated creation functions have parameters to get the object from a remote server and get thread-safe or locale-specific object handles. use the getobjhandlefromactivexctrl function in the labwindows/cvi user interface library to get the labwindows/cvi activex object handle of activex controls loaded in labwindows/cvi user interface panels.
examples
create a new object and get its imyinterface1 interface:
visual basic
dim obj as myserver.myobject
set obj = new myserver.myobject
labwindows/cvi
caobjhandle obj;
myserver_newimyinterface1(0, 1, locale_neutral, 0, &obj);
create a new myobject and get its imyinterface1 interface on a remote server:
visual basic
dim obj as myobject
set obj = createobject(myserver.myobject, server_address)
labwindows/cvi
caobjhandle obj;
myserver_newimyinterface1(server_address, 1,
locale_neutral, 0, &obj);
create the object from file and get its imyinterface1 interface:
visual basic
dim obj as myobject
set obj = getobject(file_path, myserver.myobject)
labwindows/cvi
caobjhandle obj;
myserver_openimyinterface1(file_path, 0, 1,
locale_neutral, 0, &obj);
get the active objects imyinterface1 interface:
visual basic
dim obj as myobject
set obj = getobject(, myserver.myobject)
labwindows/cvi
caobjhandle obj;
myserver_activeimyinterface1(0, 1, locale_neutral, 0, &obj);
create a new myobject and get its imyinterface2 interface:
visual basic
dim obj as imyinterface2
set obj = createobject(myserver.myobject)
labwindows/cvi
caobjhandle obj;
myserver_newimyinterface2(0, 1, locale_neutral, 0, &obj);
get the activex object handle for an activex control loaded in a labwindows/cvi panel:
caobjhandle obj;
getobjhandlefromactivexctrl(panelhandle, panel_ctrl, &obj);
method and property wrappers
in the function panel classes corresponding to an activex interface, the labwindows/cvi activex controller wizard generates wrapper functions for the methods and properties of that interface. the names of the functions are generated according to the following rules:
_
_get
_set
_setbyref
for read-only properties, the set and setbyref wrappers are not generated. the setbyref wrapper is generated if the server supports setting the property by reference. if a server exposes both set and setbyref accessors for a property, then you should refer to the servers documentation to decide between calling the set or setbyref wrappers. for write-only properties, the get wrapper is not generated.
if you set the property access functions option to per object, the wizard generates one group of get-set-setbyref property wrapper functions for all the properties in an interface. for these functions, you must pass the property id and property type in addition to the object handle. these functions are named according to the following rules:
_getproperty
_setproperty
_setpropertybyref
if you set the property access functions option to per server, the wizard generates one pair of get-set property wrapper functions for all the properties in the server. for these functions, you must pass the property id and property type in addition to the object handle. these functions are named according to the following rules:
_getproperty
_setpropertybyref
note that the per object and per server options are available only if the server exposes idispatch based interfaces. also, the property wrapper functions generated for the per object and per server options require additional parameters to identify the property to get or set and its data type.
examples
call mymethod1:
visual basic
dim obj as myobject
set obj = createobject( “myserver.myobject”)
obj.mymethod1
labwindows/cvi
caobjhandle obj;
myserver_newimyinterface1(0, 1, locale_neutral, 0, &obj);
myserver_imyinterface1mymethod1(obj, 0);
get, set, and setbyref myproperty1:
visual basic
dim obj as myobject
dim myprop as integer
set obj = createobject( “myserver.myobject”)
myprop = obj.myproperty1
obj.myproperty1 = 42
set obj.myproperty1 = 42
labwindows/cvi
caobjhandle obj;
int myprop;
myserver_newimyinterface1(0, 1, locale_neutral, 0, &obj);
myserver_imyinterface1getmyproperty1(obj, 0, &myprop);
myserver_imyinterface1setmyproperty1(obj, 0, 42);
myserver_imyinterface1setbyrefmyproperty1(obj, 0, 42);
disposing objects
in labwindows/cvi, you must dispose the object handles by calling the ca_discardobjhandle function when you finish using the activex object. this process is equivalent to setting the object to nothing in visual basic. disposing object handles is required to prevent memory leaks in your program. note that for out-of-process activex servers such as microsoft excel, word, and so on, you also may have to call a quit or exit method on the top-level application object to ensure that the activex server process exits.
visual basic
dim obj as myobject
set obj = createobject(myserver.myobject)
set obj = nothing
labwindows/cvi
caobjhandle obj;
myserver_newimyinterface1(0, 1, locale_neutral, 0, &obj);
ca_discardobjhandle(obj);
activex threading model
before calling activex components, the execution thread must initialize what is known as the activex threading model. activex threading is an advanced topic and beyond the scope of this document. in labwindows/cvi, the default activex threading model is the multithreaded model, which is set when you first call an activex library function or wrapper function. in visual basic, the default threading model is the apartment-threaded model. while most activex servers work in both threading models, some servers may work only in the apartment threaded model. for this reason, if you encounter a case where your visual basic code works, but the equivalent labwindows/cvi code does not work, then you can try changing the labwindows/cvi threading model to apartment threaded by calling the ca_initactivexthreadstyleforcurrentthread activex library function.
note that you must call this function before calling any other activex library functions or wrapper functions.
optional parameters
in visual basic you can omit passing values to optional parameters, which causes the server to use default values for such parameters. for non-variant optional parameters, labwindows/cvi places the default value in the function panel control for that parameter. for optional parameters that are variants, labwindows/cvi places a default value of ca_default_val in the function panel. you can pass these values to get the same behavior as omitting optional parameters in visual basic.
enumerating collections
in visual basic you can iterate over collections using the for each construct. ansi c does not have a for each construct, so you should iterate over the collection in for or while loops using the item wrapper function to get an element of the collection. most activex collection interfaces expose an item or similar method to index the collection.
the following example shows how to pass default values for optional parameters and enumerating collections. this example opens an excel workbook and gets the names of all the worksheets in it.
visual basic
dim app as excel.application
dim s as excel.worksheet
set app = createobject(excel.application)
app.workbooks.open (c:\temp\book.xls)
for each s in app.sheets
   text1.text = text1.text & vbcrlf & s.name
next
labwindows/cvi
int i, numsheets = 0;
caobjhandle app = 0, books = 0, book = 0, sheets = 0;
excel_newapp(0, 1, locale_neutral, 0, &app);
excel_getproperty(app, 0, excel_appworkbooks,
cavt_objhandle, &books);
excel_workbooksopen(books, 0, c:\\temp\\book.xls,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val, &book);
excel_getproperty(app, 0, excel_appsheets,
cavt_objhandle, &sheets);
excel_getproperty(sheets, 0, excel_sheetscount,
cavt_long, &numsheets);
for (i = 1; i
{
caobjhandle sheet = 0;
char * name = 0;
// get the sheet object at index i
// ca_variantlong is used to pass the index as a variant
excel_sheetsitem(sheets, 0, ca_variantlong(i), &sheet);
excel_getproperty(sheet, 0, excel_worksheetname,
cavt_cstring, &name);
printf(name of worksheet %d is %s\n, i, name);
ca_freememory(name);
// discard the temporary sheet object handle
ca_discardobjhandle(sheet);}
duplicating object references
in visual basic, you can use the set statement to assign object references to properties. see the section method and property wrappers for more information on the equivalent operation in labwindows/cvi. you can also use duplicate object references using the set command. in labwindows/cvi, you can do the same using the ca_duplicateobjhandle activex library function. this function is similar to the queryinterface method of the com iunknown interface that is implemented by all activex objects. note that you can pass the guid of the interface you want to the ca_duplicateobjhandle function. you also can pass 0 if you want to get the same interface that is in the object handle being duplicated. you must discard the duplicated handle when you no longer need it.
visual basic
dim obj as object
dim obj2 as myserver.myobject
create obj
.. ..
duplicate object reference
set obj2 = obj
.. ..
set obj2 = nothing
labwindows/cvi
caobjhandle obj, obj2;
// create obj
.. ..
ca_duplicateobjhandle(obj, &iid_imyinterface2, &obj2);
.. ..
ca_discardobjhandle(obj2);
getting interfaces from objects
in most cases, you do not need to get the activex interface pointers from the labwindows/cvi object handles because all the wrapper functions use object handles to refer to the objects. however, sometimes you may have to call functions that take interface pointers as input or output parameters. you can use the labwindows/cvi library functions to get interface pointers from object handles and object handles from interface pointers. the following code shows how to bind a microsoft grid activex control to a microsoft ado data control activex object.
visual basic
using the adodc and datagrid activex controls
adodc1.connectionstring = dsnstring
adodc1.recordsource = select * from  [table1]
assign the adodc control as the data source
to the datagrid control.
set datagrid1.datasource = adodc1
labwindows/cvi
// get labwindows/cvi activex object handles for the activex controls
getobjhandlefromactivexctrl(panelhandle, panel_datagrid, &gridhandle);
getobjhandlefromactivexctrl(panelhandle, panel_adodc, &adohandle);
// set up ado to use a database and have a query
msadodclib_iadodcsetconnectionstring(adohandle, null, dsnstring);
msadodclib_iadodcsetrecordsource(adohandle, null, select * from [table1]);
// the microsoft datagrid expects a datasource interface.
// this is automatically handled by visual basic.
ca_getinterfacefromobjhandle(adohandle, &msdatasrc_iid_datasource, 1, &sourceiunknown, null);
msdatagridlib_idatagridsetbyrefdatasource(gridhandle, null,
sourceiunknown);
data type conversion
like visual basic, labwindows/cvi also converts activex data types such as bstr to native types like c string in the generated code. the generated code cannot automatically convert certain abstract activex data types like safearray and variant. in this case, you can use the functions in the activex library to convert these data types to c types. refer to the generated wrapper function help and the activex library help for more information about specific data type conversions.
accessing sub-objects
in visual basic, you can access sub-objects nested at multiple levels such as the following:
app.workbooks.open(c:\temp\book.xls)
to execute this statement, visual basic creates a temporary workbooks object and uses it to call the open method. labwindows/cvi does not support this syntax. you must access each sub-object one level at a time. that is, you must first get a handle to the workbooks object and then use that handle to call the open method as shown in the following example:
visual basic
dim books as workbooks
dim book as workbook
books = app.workbooks
book = books.open(c:\temp\book.xls)
labwindows/cvi
excelobj_workbooks books = 0;
excelobj_workbook book = 0;
excel_getproperty(app, 0, excel_appworkbooks, cavt_objhandle, &books);
excel_workbooksopen(books, 0, c:\\temp\\book.xls,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val, &book);
ca_discardobjhandle(books);
note that you must discard the workbooks object when you no longer need it. visual basic automatically discards temporary objects.
activex events
to handle activex events in visual basic, you use the withevents keyword in the dim command used to define the activex object. visual basic lists the events supported by the object in the drop-down menu and generates an event handler in your code when you select the event from the drop-down menu. labwindows/cvi generates functions that you can use to register callback functions for the events you want to handle. all these event registration functions are generated in the event callback registration functions class in the generated instrument. the prototypes of the callback functions are in the generated header file. the following example shows how to handle the workbookopen event of the excel application object.
visual basic
dim withevents app as excel.application
private sub app_workbookopen(byval wb as excel.workbook)
msgbox (workbook open event: + wb.name)
end sub
private sub form_load()
set app = new excel.application
app.workbooks.open (c:\temp\book.xls)
end sub
other code
.. .. ..
labwindows/cvi
void main(void)
{
excelobj_app app = 0;
excelobj_workbooks books = 0;
excelobj_workbook book = 0;
excel_newapp(0, 1, locale_neutral, 0, &app);
excel_appeventsregonworkbookopen(app, workbookopencallback, 0, 1, 0);
excel_getproperty(app, 0, excel_appworkbooks, cavt_objhandle, &books);
excel_workbooksopen(books, 0, c:\\temp\\book.xls,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val,
ca_default_val, ca_default_val, ca_default_val, &book);
.. .. ..}
hresult cvicallback workbookopencallback(caobjhandle caserverobjhandle, void *cacallbackdata, excelobj_workbook wb)
{
char * name;
excel_getproperty (wb, 0, excel_workbookname,
cavt_cstring, &name);
messagepopup(workbookopen, name);
ca_freememory(name);
return s_ok;}
getting error information
in visual basic, you handle activex errors using the on error statement. in labwindows/cvi, the generated wrapper functions return error codes. negative return values indicates an error condition, and you can get more information using the error processing functions in the activex library. most of the time, this information is insufficient because the error code is a library error code or system error code and does not contain information from the server. the labwindows/cvi generated wrapper function also contains an errorinfo output parameter that you can use to get additional error information from the server as shown in the following example:
void main(void)
{
caobjhandle app = 0, books = 0;
hresult error;
errorinfo errorinfo;
error = excel_newapp(0, 1, locale_neutral, 0, &app);
if (error
goto error;
error = excel_getproperty(app, &errorinfo, excel_appworkbooks, cavt_objhandle, &books);
if (error
{
ca_displayerrorinfo(app, error, error, &errorinfo);
goto error;}
// other code
.. .. ..error:
// handle error
.. .. ..}
getting help information
when labwindows/cvi generates wrapper functions, it extracts the activex help information from the servers type library and provides the help information in the generated function panel. if the servers type library indicates that more help is available in an external help file, then labwindows/cvi inserts appropriate links in the generated function panel and displays the help topic from the function panel. in order for the links to work in labwindows/cvi and visual basic, the help file should be installed on the system – many microsoft office servers such as excel, word, and outlook have external help files that are not installed by default. make sure you install these files to get detailed help. sometimes the servers are documented online, for example, on the microsoft developer network (msdn) for many microsoft activex servers and controls.
conclusion
this document described some common issues that visual basic users encounter when writing programs in labwindows/cvi to call activex servers. many of these issues also apply to users who program in other languages like c++, java, c#, and so on. for more comprehensive information about activex programming in labwindows/cvi, refer to the activex library reference in the labwindows/cvi help and the shipping activex example programs. you also can find useful information on the following sites:

http://forums.ni.com


http://www.ni.com/support/

related links:
ni discussion forums
ni technical support
microsoft developers network
building activex servers in labwindows/cvi
----------------------------------------------
此篇文章从博客转发
原文地址: Http://blog.gkong.com/more.asp?id=125285&Name=zjcsharp
10-09-20 11:38

工控新闻

更多新闻资讯