




已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Visual Basic COM基础讲座之简介世上无难事,只要肯登攀,所以你要有信心成为一个COM程序员,而且你一定能。 事实上,我们每次设置文本编程控件的Text属性时,就已经在使用COM,同样在DAO数据控件运行MoveNext方法时,甚至在使用VB控制字时,也都是在使用COM。那么,什么是COM呢?首先,COM是一种通信的方式。例如,就像我们的电视遥控一样。当我们按下某个频道按钮时,电视频道立马切换;而当我们按下开关按钮时,电视立即关闭等等。其实,我们并不关心它们是怎样工作的,我们只知道按下按钮就能产生某个动作就可以了。程序的原理也是一样的。当改变文本编程控件的Text属性时,我们并不知道其中的原理,也许系统内部会调用几十个API函数也说不定?但对于用户来说,则只关心文本编程控件中显示的文本就可以了。其次,COM是一种重用代码的方式。使用COM的最大好处是一旦建立COM的通信方式后,可以方便地在任何地方使用多次。例如,当用户创建一个用于显示日期和时间的COM组件后,就可用于任何程序中的任何地方。不仅VB应用程序、Excel程序可以访问,而且C+应用程序也可以访问它。 所以,COM组件的代码可重用性是最主要的。再次,COM是基于实际对象的。用COM创建的大多数组件是基于实际对象的,这就意味着一旦组件被创建,其使用是相当容易的。试想一下,如果我们在计算机系统中再添加一个用户,又有哪种添加方式如Customer.Add那样简单,是添加数据处理代码包、算法,还是向应用程序添加较大的数据库DLL?很显然,COM就支持这种简单操作。所以,COM是一种通信方式、一种代码重用方式以及基于实际对象的。本教程的以后部分中将简单讨论COM和VB的相关内容,这包括类的创建,以及如何将类转换成一个实际对象。虽然,这里的内容太过简单,但却是以后COM编程的基础。VB COM基础讲座之创建第一个COM对象让我们直接来开始创建第一个真正的COM对象,它将被用于那些ActiveX程序中。具体步骤如下: 启动Visual Basic;我们将看到一个New Project对话框,其中有几个与ActiveX相关的选项图标。下面来解释一下:ActiveX DLL创建一个包含类的.DLL程序,这是我们将要采用的选项;ActiveX EXE创建一个包含类的.EXE程序,以后将讨论这个类型;ActiveX Control添加一个工程,允许自己创建用于toolbox中的控件。这里不去讨论它。ActiveX Document EXE创建一个基于Web页的.EXE程序,这里也不去讨论。ActiveX Document DLL创建一个基于Web页的.DLL程序,由于与我们的主题甚远,所以自然也不去讨论它。顺便说明一下,如果在工程列表中没有上述选项,那么你可能使用了Visual Basic的学习版。当然,在上述那么多选项中,我们真正感兴趣的是ActiveX DLLs和Active EXEs。等会再来讨论后一种,这里先看看第一种!选中ActiveX DLL项;单击OK按钮;这样,一个ActiveX DLL工程就建立好了。我们之所以创建ActiveX DLL是准备将它作为一个前端服务器,它基于Northwind数据库中的Customers表的(Northwind数据库是随Visual Basic一起发行的,位于VB98文件夹中)。这也就是说,我们后面一定会处理Customers信息,但那时我们仅仅需要对类的调用,而不想过多地停留在数据处理代码的纠缠中。当然,我们得首先创建这个类。虽然COM能使编程更容易一点,但这个类的构造还是比较困难的。尽管如此,在深入数据库之前,先来对ActiveX程序中的名称作一些修改。 将类的Name属性改为Customers;选择Project-Project Properties菜单,在弹出的对话框中,将工程名改为Northwind;现在再来使类与数据库相连:选择Project-References菜单;在弹出的对话框中,选择Microsoft ActiveX Data Objects 2.1 Library,单击OK按钮;该引用允许用户处理一个数据库,当然现在都使用COM对象来处理了。下面将围绕相应的记录集而展开:在我们的类中添加下列代码:Dim rs As Recordset这是一个用于访问数据库的记录集对象。当然,当其他开始使用该类时,我们希望记录集对象能和数据库建立连接,而当类使用结束后,与数据库的连接能断开。基于这种思想,其代码如下:在代码窗口中,将Object组合框中当前的(General)项改为Class;在右边的组合框中,确保当前项为Initialize;代码窗口中将出现:Private Sub Class_Initialize()End Sub当类刚开始时,所有这里面的代码都会被执行,类似于表单中的Form_Load事件。在Initialize事件中键入下列代码:Set rs = New Recordsetrs.ActiveConnection = Provider=Microsoft. & _ Jet.OLEDB.4.0;Data Source=C:Program Files & _ Microsoft Visual StudioVB98Nwind.mdb; & _ Persist Security Info=Falsers.Open select * from customers, , adOpenKeyset, adLockOptimistic这里不需要任何与该类相关的代码,它只是使用Visual Basic通用的ADO数据库处理代码,该类中的代码是用来如何与数据库建立连接的。需要说明的是,如果Northwind数据库Nwind.mdb不在C:Program FilesMicrosoft Visual StudioVB98文件夹,那么必须将ActiveConnection字符串内容作适当修改!当类开始时,rs对象负责与数据库建立连接,但当类对象结束后或程序关闭它时,我们应该使该连接断开。编程时,我们使用Terminate事件,它与Form_Unload非常相似的。下面来加入数据库关闭的代码:从Object组合框中选择Class,从Procedure组合框中选择Terminate;在Terminate事件中,添加下列代码:rs.CloseSet rs = Nothing这就是我们添加的又一段简单代码,它只是简单地关闭数据库,然后将rs设置为Nothing。这样,rs就会被有效删除。好了,本节就到这里。下一节中,我们将继续添加代码用来处理数据中的记录集。VB COM基础讲座之添加属性和方法下面,我们添加一个属性来让用户获取CustomerID字段的值,其相应的示例代码如下: Public Property Get CustomerID() As StringCustomerID = rs(CustomerID)End PropertyPublic Property Let CustomerID(NewValue As String)rs(CustomerID) = NewValueEnd Property显然,该属性的Get操作只是简单地返回CustomerID字段的值,相应地,Let操作是将CustomerID字段设置一个新值。换句话说,属性中有两个部分:getting和letting,事实上可能还有另外一个setting操作。但对于不同场合来说,我们总需要Get和Let来进行读和写的操作。这里所引起注意的是,在上述属性过程中,应该对某些值进行必要的检测。例如,在调用Let属性时,用户可能有如下操作:ObjectName.CustomerID = HALFI该Let属性操作后,CustomerID等于新的字符串HALFI。但当查看Northwind数据库内容时,我们会发现CustomerID字段的字符长度不能超过5。如果用户有这样的操作:ObjectName.CustomerID = HALFISTORE则出现数据库操作错误。虽然,可以通过错误句柄来处理这个问题,但是如果能在代码中检测NewValue的长度岂不更好?如果该值超过5个字符,我们既可以通过裁剪取共前5个字符,也可以忽略这个新的字符串而弹出一个错误提示。但这里,我们采用后一种措施。在我们的类中添加下列代码: Public Property Get CustomerID() As StringCustomerID = rs(CustomerID)End Property Public Property Let CustomerID(NewValue As String)If the length of NewValue is greater than fiveIf Len(NewValue) 5 Then. then raise an error to the programusing this classErr.Raise vbObjectError + 1, CustomerID, _Customer ID can only be up to five & _characters long!Else. otherwise, change the field valuers(CustomerID) = NewValueEnd IfEnd Property好了,在完成下列步骤之前,我们已经为添加方法花费了不少时间。在我们的类中添加下列代码:Public Sub Update()rs.UpdateEnd Sub该Update方法只是简单地调用记录集对象的Update方法来更新记录。下一步,我们将用一个很小的样例程序来测试这个属性和方法,在测试时还将使用特定的技巧来追踪类和程序的运行。VB COM基础讲座之类的测试现在就来测试前面创建的类。 按F5运行程序;在弹出的属性对话框中,选中Wait for Components to Start(启动工程时等待创建部件),然后按OK按钮;这时,类就会被激活,其他程序就可使用它的功能。再次运行Visual Basic另一个实例;创建一个新的Standard EXE工程;选择Project-References菜单;浏览对话框中可引用的列表项,可以发现一些额外的组件。选中Northwind列表项;Northwind就是前面创建的ActiveX工程。单击OK按钮;现在添加一些代码来使用上述工程:在Form1表单中添加一个命令按钮;为命令按钮添加下列代码:Dim Test As CustomersSet Test = New CustomersMsgBox Test.CustomerIDSet Test = Nothing该代码首先创建一个新的Customers对象,然后显示CustomerID信息,最后将Test对象置为Nothing,并关闭它。按F5键运行测试程序;需要说明的是,当运行时出现invalid reference错误提示时,肯定哪些地方有问题。这时可按下面步骤重新来一次:(1) 在测试工程中去掉Northwind引用;(2) 重新启动Northwind工程;(3) 在测试工程中添加Northwind引用,再运行!单击表单中的命令按钮;这时运行时可能需要几秒钟,毕竟还要做一些如数据库连接等工作。但是,除了一开始的停留外,后面的调用就快得多了。程序将显示包含ALFKI的消息对话框。关闭测试程序。现在,我们来看看程序背后究竟发生什么。将插入符移动到MsgBox Test.CustomerID这条语句上;按F9;该语句显示为红色,用来标记一个断点。当代码运行时,它会停留在这里。按F8将单步运行此语句,并移动到下一句代码上。按F5再次运行测试程序;单击命令按钮;流程将停留在MsgBox这条命令上。按F8,慢慢单步执行各条语句;将会看到系统在两个Visual Basic中来回切换,显示出不同属性的处理过程。结束后,关闭测试程序。下面再对前面的工程进行测试。这一次,我们不仅获取CustomerID的值,而且还设置这个值。将命令按钮的代码改为:Dim Test As CustomersSet Test = New CustomersTest.CustomerID = KARLYTest.UpdateMsgBox Test.CustomerIDSet Test = Nothing该代码首先设置CustomerID字段,然后更新记录集,最后显示出CustomerID属性,其结果应该是设置的KARLY。 假如愿意,仍然可以按F9高亮显示Test.CustomerID = 这条语句,然后按F8单步运行来查看其工作情况。至此,我们已经成功地创建并测试一个简单的基于数据库的类。但是,还没有对customerID的字符串长度作测试,如果其长度超过5个字符,看看会发生什么?下一步,我们将扩充并改进这个数据库类。首先添加类的几个特征:其他的属性、一些方法甚至一两个事件。 其相应的代码如下:Dim WithEvents rs As RecordsetPublic Event RecordsetMove()Private Sub Class_Initialize()Set rs = New Recordset rs.ActiveConnection = Provider=Microsoft. & _Jet.OLEDB.4.0;Data Source=C:Program Files & _Microsoft Visual StudioVB98Nwind.mdb; & _Persist Security Info=False rs.Open select * from customers, , adOpenKeyset, adLockOptimisticEnd SubPrivate Sub Class_Terminate()rs.CloseSet rs = NothingEnd SubPublic Property Get CustomerID() As StringCustomerID = rs(CustomerID)End PropertyPublic Property Let CustomerID(NewValue As String)If the length of NewValue is greater than fiveIf Len(NewValue) 5 Then. then raise an error to the programusing this class, by runningErr.Raise vbObjectError + OurErrorNumberErr.Raise vbObjectError + 1, CustomerID, _Customer ID can only be up to five & _ characters long!Else. otherwise, change the field valuers(CustomerID) = NewValueEnd IfEnd PropertyPublic Property Get CompanyName() As VariantCompanyName = rs(CompanyName)End PropertyPublic Property Let CompanyName(ByVal NewValue As Variant)rs(CompanyName) = NewValueEnd PropertyPublic Property Get ContactName() As VariantContactName = rs(ContactName)End PropertyPublic Property Let ContactName(ByVal NewValue As Variant)rs(ContactName) = NewValueEnd PropertyPublic Property Get ContactTitle() As VariantContactTitle = rs(ContactTitle)End PropertyPublic Property Let ContactTitle(ByVal NewValue As Variant)rs(ContactTitle) = NewValueEnd PropertyPublic Property Get Address() As VariantAddress = rs(Address)End PropertyPublic Property Let Address(ByVal NewValue As Variant)rs(Address) = NewValueEnd PropertyPublic Property Get City() As VariantCity = rs(City)End PropertyPublic Property Let City(ByVal NewValue As Variant)rs(City) = NewValueEnd PropertyPublic Property Get Region() As VariantRegion = rs(Region)End PropertyPublic Property Let Region(ByVal NewValue As Variant)rs(Region) = NewValueEnd PropertyPublic Property Get PostalCode() As VariantPostalCode = rs(PostalCode)End PropertyPublic Property Let PostalCode(ByVal NewValue As Variant)rs(PostalCode) = NewValueEnd PropertyPublic Property Get Country() As VariantCountry = rs(Country)End PropertyPublic Property Let Country(ByVal NewValue As Variant)rs(Country) = NewValueEnd PropertyPublic Property Get Phone() As Variant Phone = rs(Phone)End PropertyPublic Property Let Phone(ByVal NewValue As Variant)rs(Phone) = NewValueEnd PropertyPublic Property Get Fax() As VariantFax = rs(Fax)End PropertyPublic Property Let Fax(ByVal NewValue As Variant)rs(Fax) = NewValueEnd PropertyPublic Sub AddNew()rs.AddNewEnd SubPublic Sub Update()rs.UpdateEnd SubPublic Sub CancelUpdate()If rs.EditMode = adEditInProgress Or _rs.EditMode = adEditAdd Thenrs.CancelUpdateEnd IfEnd SubPublic Sub MoveNext()rs.MoveNextEnd SubPublic Sub MovePrevious()rs.MovePreviousEnd SubPublic Sub MoveFirst()rs.MoveFirstEnd SubPublic Sub MoveLast()rs.MoveLastEnd SubPublic Function FindByCustomerID(CustomerID As String) As BooleanUses the Find method to locate customerswith a matching CustomerID.Returns True value is customer(s) foundDim varBookmark As Variantrs.MoveFirstrs.Find (CustomerID= & CustomerID & )If rs.EOF = True ThenFindByCustomerID = Falsers.Bookmark = varBookmarkElseFindByCustomerID = TrueEnd IfEnd FunctionPublic Property Get EOF() As BooleanExample of a read-only propertyNo Property Lets hereEOF = rs.EOFEnd PropertyPublic Property Get BOF() As BooleanAnother example of a read-only propertyBOF = rs.BOFEnd PropertyPrivate Sub rs_MoveComplete(ByVal adReason As ADODB.EventReasonEnum, _ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, _ByVal pRecordset As ADODB.Recordset)Reacts to the recordset MoveCompletemethod - raises event with each moveRaiseEvent RecordsetMoveEnd Sub需要说明的是:迄今为止,我们仅仅是在一个类中添加代码。当然,也可以选择Project-Add Class菜单来向工程添加多个类,而且还可利用collections使这些类工作在一起。但是在这里,我们仍然想用一个类来处理一个数据表。将上述类的代码复制并粘贴到自己的类中,下一节将讨论该程序的编译。VB COM基础讲座之全面测试这一次,我们不用Visual Basic来测试前面的程序,而是先来编译: 选择File-Make Project1.exe菜单;择要保存的文件夹,单击OK按钮;退出Visual Basic;运行刚才编译过的.EXE文件; 当表单出现时,试试打开一个customer,然后对其修改并单击OK按钮。再打开刚才的customer,看看其资料是否被修改?结果应该是这样,因为ActiveX DLL会自动将结果保存在数据库中。现在,让我们静下来想一想刚才做过的事件。我们只用了几条简单的语句就建立了一个自己的数据库应用程序,虽然这里只使用了COM一点功能,但却使得应用程序变得如此容易。关闭已测试完的应用程序;如果上述过程比较顺利的话,那么我们再做这样的测试: 打开Northwind工程;假如对Northwind工程作了某些修改,那么还需要重新编译:选择File-Compile Northwind.dll菜单;选择和上次保存Northwind.dll相同的文件夹,以便覆盖原来的文件,单击OK按钮;需要说明的是,如果编译时出现错误,那肯定在程序中有一些不对的地方。关闭所有正在运行的程序,然后再重新试一试。编译后,退出Visual Basic;再次运行Project1.exe;天啦,居然会有错误信息,类已不再支持原来接口。这就是我们做的一种测试,当重新编译ActiveX工程时,使用它的程序就会被支解。解决上述问题的一种办法是将Project1文件打开并重新编译。但是假如工作组中有两百个员工,这就是说,我们得把重新编译好的工程和新的DLL分发到这两百个员工手上。 你能受得了吗?不,不能这样做。我们必须搞清楚错误产生的原因,以及弄明白为什么我们的工程不能和最新的DLL一起工作,难道是兼容性的问题吗?本教程的最后一部分将详细探讨这些内容。VB COM基础讲座之ActiveX EXEs到现在为止,本教程一直讨论基于ActiveX DLLs中的类的内容,但是没有一本教程不说明与DLL相似的ActiveX EXEs。 所以,想在这里实际编写一个ActiveX EXE工程。事实上,它和ActiveX DLL没有太大的区别,甚至没有区别。在启动Visual Basic后选择ActiveX EXE就可创建,然后像以前一样构造自己的类。但这里不想再作更详细的讨论,因为ActiveX EXE和ActiveX DLL除了在运行时有一些微小区别外,其他都相同。它们的区别首先表现在它们的进程空间的不同。所谓进程空间是用于运行、处理和存取的一块计算机内存。任何Windows程序,如Microsoft Word等,都有自己的进程空间,它很像程序的桌面那样。当使用ActiveX DLLs工程运行时,DLL是在使用它的程序的进程空间中运行的,而ActiveX EXE是在进程空间外面工作的。但是,ActiveX EXE还有自己的桌面。这究竟如何理解呢?假如,ActiveX DLL变得不稳定或意外受损时,使用它的应用程序常常出现蓝屏的死机现象,而在EXEs中却不会发生,因为它有自己的进程空间,即使被破坏,也仅仅是桌面受损,当然用户程序应该很好地去修复它。其次,它们的区别还表现在装载的速度上。由于DLL是直接装载到已存在的进程空间,所以它的速度非常快。而EXEs由于还要分配自己的进程空间,所以速度上相对慢一点。 上述两点区别可以说是它们真正的区别。总之,如果使用不同的Windows工具来实现相应的ActiveX组件,那么相应的工程类型就应该有所不同。例如,若使用MTS,则应创建DLL工程,若使用DCOM,则应创建EXE工程。当然,即使现在不理解这此缩写字母的含义,我们也不必担心。因为它们是针对高级用户的,并用于COM远程的工具组件。以后有机会再来给出相应的教程。这里再来分析第二点的区别。如果现在需要创建这样的一个程序,它不断地检测一个数据库是否有什么改变。那么我们想到的是在程序中使用一些timer(计时器),每隔10分钟激发一次并检测该数据库。但问题来了,在该进程空间的其他所有代码都要被停止运行直至数据库检测完毕。而ActiveX EXEs伟大之处,就在于它有自己的进程空间。所以在其中添加的计时器也只会工作在自己的进程空间中而不会影响其他使用它的程序。也就是说,对于前面的工程来说,若使用ActiveX EXE来检测数据库,则不会停止其他使用它的程序的运行;即使需要从其他程序中返回一个消息,也可以通过其他事件而获得。需要说明的是,运行代码远离正规程序而通过事件与使用的应用程序会话的方法称为异步处理。通常当需要对e-mail或数据库作定期检查时,或当运行一个长的报表以及计算大的统计数据时,我们就需使用这种异步处理方式。不怕你惊讶的话,我们可以将前面论述的内容总结成这样的一句话:ActiveX DLLs是在进程内运行,而ActiveX EXEs是在进程外运行。好了,下一节将创建并测试一个自己的ActiveX EXE工程,并使用大家还不太熟悉的异步处理技巧。然后,提出一个称为实例的有意义的概念,最后指明怎样获得更多的COM知识使自己达到一个新的水平。VB COM基础讲座之测试ActiveX EXEs本节将创建并测试自己的ActiveX EXE程序。 示例中将使用这样一个组件,它是一个有效的文件探测器。大约每隔60秒检测指定文件的存在性。如何该文件存在,该组件激发一个事件来调用应用程序,如果不存在,则另作处理。当然,如果将所有代码写到ActiveX DLL工程,则运行时程序代码将被挂起直到文件检测代码运行完毕为止。由于ActiveX EXE工程拥有自己的进程空间,代码运行时会自我协调、异步处理,从而不会使其他程序代码停顿。下面就来创建:新建一个ActiveX EXE工程;工程名设为File;添加的类名为FileCheck;下一步,我们需要构造一些用于每隔1分钟左右检测文件的代码。这里将在ActiveX EXE工程插入一个带有计时器的表单。但该表单不会被显示,因为我们只是使用上面的计时器控件每隔1分钟左右来检测文件,如果相应的文件被检测到,则激发一个事件。 选择Project-Add Form;在表单Form1中添加一个计时器;在表单代码中添加下列变量的声明:Public Filename As String该变量用于保存被监视的文件名。在表单代码中添加下列事件的声明:Public Event FileFound()该事件只有当前面的文件发现后才被激发。在Timer1代码中添加下列
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 张家口市中石化2025秋招面试半结构化模拟题及答案电气仪控技术岗
- 大唐电力通辽市2025秋招性格测评常考题型与答题技巧
- 2025年潜水科目考试题及答案
- 石嘴山市中石油2025秋招笔试模拟题含答案行测综合英语
- 七台河市中石油2025秋招网申填写模板含开放题范文
- 中国移动汉中市2025秋招半结构化面试模拟30问及答案
- 黄冈市中石化2025秋招面试半结构化模拟题及答案油田勘探开发岗
- 那曲市中石油2025秋招面试半结构化模拟题及答案油气储运与管道岗
- 岳阳市中石化2025秋招面试半结构化模拟题及答案炼化装置操作岗
- 上饶市中石化2025秋招面试半结构化模拟题及答案炼油工艺技术岗
- 食材配送服务方案投标方案(技术方案)
- JT-T-1180.2-2018交通运输企业安全生产标准化建设基本规范第2部分:道路旅客运输企业
- 中国省市县行政区划
- 一元二次方程-相似三角形-锐角三角函数复习
- 冰皮月饼的制作方法课件
- 在职党员到社区报到登记表“双报到”登记表
- 降低10炉脱硝系统液氨消耗量0
- 地下储藏室产权使用权转让协议
- 高考专题复习:小说专题训练人称的交替使用
- 大数据在高速公路收费稽查打逃方面的应用
- GB/T 9722-2006化学试剂气相色谱法通则
评论
0/150
提交评论