| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7178 人关注过本帖, 6 人收藏
标题:[转载]Visual Basic COM 讲座
只看楼主 加入收藏
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
结帖率:78.95%
收藏(6)
 问题点数:0 回复次数:39 
[转载]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编程的基础。

在本节中,我们来实践一下。首先创建一个COM对象,然后使用它,最后再想法改进。

   首先进行下面两步:

   运行Visual Basic;选择 "Standard EXE"工程类型;由于COM对象是基于类的,而类实际上是程序包,就像模块中的代码一样。所以:

   选择"Project"->"Add Class Module";当相应的对话框出现后,选择"'Class Module",然后单击"Open"按钮。

   这样,在桌面上显示一个表单,以及包含在工程Project1中的Class1。

   下面再将空的类的类名更改:

   在类的属性窗口中,将类的Name属性改成CDog。

   需要说明的是,为了区别起见,每个对象名的前面都有相应的前缀,例如Text Box对象前是"txt"、Form前是"frm"、类前可以大写字母"C"或小写字母"cls",但这里使用前者。

   下面我们添加一些代码来测试一下:

   在CDog类通用声明部分中,添加变量的声明:

Public Name As String
   然后,打开Form1;

   在表单中添加一个命令按钮;

   打开代码窗口,为该命令按钮添加下列代码:

  Dim MyDog As CDog
   Set MyDog = New CDog
   MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   Set MyDog = Nothing
   下面就来解释上述代码的含义:

Dim MyDog As CDog
   该行语句是用来通知Visual Basic为CDog对象设置一个位空间,但这时还不能使用该对象,必须等到下条语句为止:

  Set MyDog = New CDog
   它是用来创建CDog的实例。这就意味着前面空的MyDog模板变成了现在可以使用的CDog对象。

  MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   上述代码的第一行是用来设置MyDog的Name变量,同时第二行语句是用来将该变量的内容显示在消息对话框中。最后:

  Set MyDog = Nothing
   用来将MyDog对象简单的置空。

   按F5键运行并测试。

   怎么样?但同时,我们可能不禁要问,标准模块和类模块究竟有什么不同?我们再来看看下面的示例:

   将命令按钮的代码变成:

  Dim MyDog As CDog
   Set MyDog = New CDog
   Dim MyDog2 As CDog
   Set MyDog2 = New CDog
   MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   MyDog2.Name = "Sadie Moore"
   MsgBox MyDog2.Name
   Set MyDog = Nothing
   Set MyDog2 = Nothing
   与最前面的代码不同的是,这里的代码实际上是定义两个对象MyDog和MyDog2,这两个对象是基于CDog的相互独立的两个对象。

   按F5键运行并测试。

   结果怎样?这一次是不是有两个对话框出现?一个显示"Billy Moore",另一个显示"Sadie Moore"。
上述定义的每个对象中除了Name外,没有任何实际的属性,因此下面过程就来添加:

   打开前面的Class1;

   声明下面的公共变量:

  Public Age As Integer
   打开前面的Form1;

   将命令按钮的代码变成:

  Dim MyDog As CDog
   Set MyDog = New CDog
   Dim MyDog2 As CDog
   Set MyDog2 = New CDog
   MyDog.Name = "Billy Moore"
   MyDog.Age = 4
   MsgBox MyDog.Name & " is " & MyDog.Age & " years old"
   MyDog2.Name = "Sadie Moore"
   MyDog2.Age = 7
   MsgBox MyDog2.Name & " is " & MyDog2.Age & " years old"
   Set MyDog = Nothing
   Set MyDog2 = Nothing
   这些代码和前面差不多,只不过这里使用了Age变量。

   按F5键运行并测试。

   应该出现显示name和age内容的两个消息对话框。

   现在再试着将其中一个对象的age值设置成1,000或者30,000。看看结果如何?程序照样正常运行,这是因为定义的整型变量最大值可达32,767,但是实际中的狗(Dog)是不会有30,000岁的。

   那么,这种情况应该怎样处理呢?

搜索更多相关主题的帖子: Basic COM Visual 讲座 
2007-04-15 18:12
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

在本节中,我们来实践一下。首先创建一个COM对象,然后使用它,最后再想法改进。

   首先进行下面两步:

   运行Visual Basic;选择 "Standard EXE"工程类型;由于COM对象是基于类的,而类实际上是程序包,就像模块中的代码一样。所以:

   选择"Project"->"Add Class Module";当相应的对话框出现后,选择"'Class Module",然后单击"Open"按钮。

   这样,在桌面上显示一个表单,以及包含在工程Project1中的Class1。

   下面再将空的类的类名更改:

   在类的属性窗口中,将类的Name属性改成CDog。

   需要说明的是,为了区别起见,每个对象名的前面都有相应的前缀,例如Text Box对象前是"txt"、Form前是"frm"、类前可以大写字母"C"或小写字母"cls",但这里使用前者。

   下面我们添加一些代码来测试一下:

   在CDog类通用声明部分中,添加变量的声明:

Public Name As String
   然后,打开Form1;

   在表单中添加一个命令按钮;

   打开代码窗口,为该命令按钮添加下列代码:

  Dim MyDog As CDog
   Set MyDog = New CDog
   MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   Set MyDog = Nothing
   下面就来解释上述代码的含义:

Dim MyDog As CDog
   该行语句是用来通知Visual Basic为CDog对象设置一个位空间,但这时还不能使用该对象,必须等到下条语句为止:

  Set MyDog = New CDog
   它是用来创建CDog的实例。这就意味着前面空的MyDog模板变成了现在可以使用的CDog对象。

  MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   上述代码的第一行是用来设置MyDog的Name变量,同时第二行语句是用来将该变量的内容显示在消息对话框中。最后:

  Set MyDog = Nothing
   用来将MyDog对象简单的置空。

   按F5键运行并测试。

   怎么样?但同时,我们可能不禁要问,标准模块和类模块究竟有什么不同?我们再来看看下面的示例:

   将命令按钮的代码变成:

  Dim MyDog As CDog
   Set MyDog = New CDog
   Dim MyDog2 As CDog
   Set MyDog2 = New CDog
   MyDog.Name = "Billy Moore"
   MsgBox MyDog.Name
   MyDog2.Name = "Sadie Moore"
   MsgBox MyDog2.Name
   Set MyDog = Nothing
   Set MyDog2 = Nothing
   与最前面的代码不同的是,这里的代码实际上是定义两个对象MyDog和MyDog2,这两个对象是基于CDog的相互独立的两个对象。

   按F5键运行并测试。

   结果怎样?这一次是不是有两个对话框出现?一个显示"Billy Moore",另一个显示"Sadie Moore"。
上述定义的每个对象中除了Name外,没有任何实际的属性,因此下面过程就来添加:

   打开前面的Class1;

   声明下面的公共变量:

  Public Age As Integer
   打开前面的Form1;

   将命令按钮的代码变成:

  Dim MyDog As CDog
   Set MyDog = New CDog
   Dim MyDog2 As CDog
   Set MyDog2 = New CDog
   MyDog.Name = "Billy Moore"
   MyDog.Age = 4
   MsgBox MyDog.Name & " is " & MyDog.Age & " years old"
   MyDog2.Name = "Sadie Moore"
   MyDog2.Age = 7
   MsgBox MyDog2.Name & " is " & MyDog2.Age & " years old"
   Set MyDog = Nothing
   Set MyDog2 = Nothing
   这些代码和前面差不多,只不过这里使用了Age变量。

   按F5键运行并测试。

   应该出现显示name和age内容的两个消息对话框。

   现在再试着将其中一个对象的age值设置成1,000或者30,000。看看结果如何?程序照样正常运行,这是因为定义的整型变量最大值可达32,767,但是实际中的狗(Dog)是不会有30,000岁的。

   那么,这种情况应该怎样处理呢?


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:15
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

属性操作很像公共变量,但属性还有更多的控制。

   常用属性通常包括"Get(获取)"和"Let(设置)"两种。这两项操作能规定一个主要属性,就像下面的代码片段:

  Private intAge As Integer
    Public Property Get Age() As Integer
    Age = intAge
   End Property

   Public Property Let Age(ByVal vNewValue As Integer)
    intAge = vNewValue
   End Property
   上述代码的工作方式极像Age变量的操作。当像下面语句操作变量时,

MyDog.Age = 4
   就好比运行Let属性,并将4赋给vNewValue。当像下面语句操作变量时,

MsgBox MyDog.Age
   是获取属性,就好比运行Get属性,并将相应的值由intAge返回。因此,我们可以这样认为:

   所谓Get属性,就是运行后获取某个值;

   所谓Let属性,就是运行后让某个属性等于某个值;

   但至此为止,我们仅仅说明属性工作方式与标准变量极为相似,还没有来得及对属性进行更多的控制。所以,下面就来讨论。

   打开上一节的工程,对CDog类进行如下修改:

   从CDog类中去掉Age变量;

   添加下列代码:

  FACE="Courier" SIZE=2>

   Private intAge As Integer
   Public Property Get Age() As Integer
    Age = intAge
   End Property

   Public Property Let Age(ByVal vNewValue As Integer)
    If vNewValue <= 50 Then
     intAge = vNewValue
    End If
   End Property

   与前面的代码相比,这里只是对Let属性代码作稍加修改。下面对其作小小的测试,假想用户试图想使:

MyDog.Age=30
   也就是运行Let属性,使vNewValue等于30。代码中,还检测vNewValue是否小于或等于50。显然,30是符合要求的,因此实例中的intAge值等于30。但如果超过50,则什么也不会发生,属性退出且没有任何赋值。当然,我们也可以对此给出相应的错误代码或是显示一个提示对话框。

   切换到Form1后面的代码窗口;

   在设置Age属性代码处的第一行语句中单击鼠标,并按F9;

   MyDog.Age = 4

   在获取Age属性代码处的第一行语句中单击鼠标,并按F9;

   MsgBox MyDog.Name & " is " & MyDog.Age & " years old"

   现在让我们测试一下:

   按F5运行程序;

   单击Command按钮;

   代码应该中断在按F9添加的断点的代码行上。

   当代码中断后,按F8单步运行并观察结果;

   现在明白它们是怎样工作的吗?注意Age属性的"get"和"let"是怎样运行的?

   在下一节中,我们不仅要讨论使用更多属性的方式,而且还讨论如何随意创建它们。


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:19
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

有时候,为了更好地处理类往往需更多的属性。例如,假如你有四种不同的客户群:集团、较大、较小和新的客户类型,或者一个用于搜索的类中有三种不同的搜索方式:软盘、硬盘和网络。那么,能不能最好从选项列表中选择一个,而不是用不能理解的数字或文本来设置相关属性?

   我想,答案是肯定的。因为这种处理就称为"枚举"。

   打开上一节的工程,让我们添加一些代码。

   在CDog类中添加下列代码:

  Public Enum CoatType

    BigAndShaggy = 1

    ShortCrewCut = 2

    PoodleStyleAfro = 3

    Unknown = 4

   end Enum
   关键词"Enum"就是用来定义枚举的,换句话说,它是可能选项的列表。各选项都有相应的数字,也就是说BigAndShaggy表示1,ShortCrewCut等于2,等等。

   需要注意的是,当将枚举项相关信息添加在数据库中时,其相应的数值是非常有用的。由于"BigAndShaggy"实际代表的是数值1,所以可以直接将其插入到数据库的数值字段中。这就意味着,可以方便使用字符串来维护数据库。

   所以,我们来创建一个Dog的Coat类型列表,并另外定义一个属性,将这些类型添加在CDog类中。

   在类中声明下列变量:

   Private udtCoat As CoatType

   这个定义的私有变量用来保存即将添加的Coat类型属性,注意到udtCoat变量既不是字符串也不是整型,而是我们自己定义的枚举类型CoatType。

   当类CDog打开时,选择"Tools"菜单中的"Add Procedure"命令,弹出相应的对话框;

   Name编辑框中键入Coat;

   选中"Property"选项按钮,然后单击[OK]。

   系统自动产生下列代码框架:

  Public Property Get Coat() As Variant

   End Property

   Public Property Let Coat(ByVal vNewValue As Variant)

   End Property
   但我们需要的却不是这个框架。代码中,"Variant"变量类型是能接收和处理任何类型数据。在我们定义的CDog类中,最后的属性是Age,它只能接受整型。但现在需要属性能接收CoatType列表中的数据类型,因此需要作下列修改:

   将产生的代码中所有的"Variant"改成"CoatType";

   然后,添加一些实际处理属性的代码。

   在属性的Get过程中,添加下列代码:

Coat = udtCoat
   在属性的Let过程中,添加下列代码:

udtCoat = vNewValue
   切换到Form1;

   将Command按钮的代码改为:

Dim MyDog As CDog
Set MyDog = New CDog
MyDog.Name = "Billy"
   现在开始键入:MyDog.Coat =

   奇迹出现了,当你敲下"="键时,出现一个含有可能选项的列表,从中我们可以选择一个。

   完成代码的键入:MyDog.Coat = ShortCrewCut

   下一步,我们将获取Coat属性的值。假如现在就来简单地在消息对话框中显示属性值,则只需返回选择项的值就可以了。例如,若选择了ShortCrewCut,其属性一定返回2。不信,可以试一试!

   但这里采用另外一种方法,它是用If-Then语句判断Coat:

   在Command按钮已有的代码后面添加下列代码:

  If MyDog.Coat = BigAndShaggy Then

    MsgBox "You have a big, bouncy, bushy pup!"

   ElseIf MyDog.Coat = PoodleStyleAfro Then

    MsgBox "Your pooch is pretty, petit and pooch-like!"

   ElseIf MyDog.Coat = ShortCrewCut Then

    MsgBox "Your dog is full of oomph, oomph and more oomph!"

   ElseIf MyDog.Coat = Unknown Then

    MsgBox "I have no idea about your dog. I don't think " & _

        "you do either!"

   End If
   这里的代码只是简单判断Coat属性值,并显示相应的消息对话框。当然,这里也可以使用"Select Case"语句。

   最后,我们添加最后一条语句来释放计算机内存:

   在Command按钮已有的代码后面添加下列代码:

Set MyDog = Nothing
   按F5运行程序,并单击Command按钮测试一下。

   结果怎样?


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:19
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

前面已经接触到类的变量、属性以及枚举,但我们怎样才能更好的利用它们呢?

   显然,子过程就是其中的一种方式,它几乎出现所有的Visual Basic程序中,所以这里来举例说明。

   在CDog类中添加下列代码:

  Public Sub Bark()

    MsgBox "Woof! Woof!"

   End Sub
   这里的子过程是最常见的,我们可以简单地使用MyDog.Bark来调用它。

   下面来试一试:

   将表单Form1的Command按钮的代码改成:

  Dim MyDog As CDog

   Set MyDog = New CDog

   MyDog.Name = "Billy"

   MyDog.Bark

   Set MyDog = Nothing
   需要说明的是,在键入"MyDog."会弹出相应的列表,各列表项前面都有不同颜色的小图标区分不同的类型。例如Bark子过程项前面的是黄绿色的,属性是灰色和蓝色的,这样能帮助我们识别Bark是MyDog对象的一个方法。

   按F5运行并测试。

   事实上,除了子过程外,我们也可以在代码中添加函数。这里我们就不举例了,你可以自己尝试一下。因为函数和一般子过程除了能在一个类中外,其工作也是相同的。但不要忘记,所有子过程和函数都可以有自己的参数。

   现在,让我们设想一下,在类中有一个Sleep方法。当我们想要cat睡觉或dog打盹时,每次都得调用这个方法。

   但是,我们怎么知道这些小东西什么时候醒来?这是一个非常有趣的问题,其答案是使用事件(event)。

   当我们在文本编辑框中键入字符时就会产生Change事件,而当我们单击命令按钮时就会产生Click事件。同样,想知道这些小东西什么时候醒来,就需使用下一节所着重讨论的Awake事件。


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:20
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

相对来说,事件的使用是比较简单的。在使用前,我们必须先定义该事件,这就意味着通知Visual Basic什么事件被调用。一个事件可能有自己的参数,例如,一个Command按钮有一个Click(单击)事件,它没有参数。另外,文本编辑框有一个KeyPress事件,它通过一个叫"KeyAscii"的值来处理相关内容。

   定义一个事件是在一个类的通用声明部分添加类似下面的代码:

Public Event MyEventName(PossArguments As String, Etc As Variant)
   然后在代码调用RaiseEvent方法来激发一个事件。就像下面的代码一样:

RaiseEvent MyEventName("PossArgs", "Etc")
   为了更好地说明上述添加和激发事件的过程,我们举一个例子。首先,定义一个事件:

   在CDog类的通用声明部分添加下列代码:

Public Event Awake()
   在CDog类中添加Sleep子过程:

Public Sub Sleep()

  Dim i As Long
  For i = 1 To 1000000
   DoEvents: DoEvents: DoEvents
   exit
   RaiseEvent Awake
End Sub

   代码中,一开始做一些1000000次无用的循环,计算机短暂停顿后,Sleep子过程激发Awake事件。

   但Awake事件产生后,我们应该让程序作相应的反应呢?当然,利用命令按钮是最简单的,只要在代码窗口的列表中选择命令按钮对象。

   但是那样的话,我们必然需要一个控件,而且所见的内容都在表单上。这里我们纯粹使用相应的代码,并且是不可见的。

   当然用代码来接收事件,还需要额外的操作:

   在表单代码窗口中的通用声明部分,添加下列代码:

Dim WithEvents MyDog As CDog
   该代码不同于以前的MyDog声明,它有个关键词WithEvents用来通知Visual Basic该对象可以按收任何事件,而且该对象必须接收事件。

   删除命令按钮中的所有代码;并在Command1中添加下列代码:

Set MyDog = New CDog
MyDog.Name = "Billy"
MyDog.Bark
MyDog.Sleep
   该代码简单地将MyDog设置成CDog的一个新的实例,设置Name后,调用Bark,最后运行Sleep子过程。

   现在添加一些代码来相应Awake事件。

   在Form代码窗口中,从对象下拉列表中选择"MyDog";

   在"MyDog"的"Awake"事件中,添加下列代码:

  Private Sub MyDog_Awake()

    MsgBox "Your pooch has awoken!"

   End Sub
   好了,现在就可以测试了。

   按F5运行程序;

   单击Command按钮;

   这样,当小狗Bark后,开始打盹,最后结束时还被你叫醒。真是神奇!


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:20
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

还记得我们是怎么将一个类添加到标准的Visual Basic工程中的?

   是的,一流的COM体系的最大特点是其代码的可重用性。

   换句话说,如果用Visual Basic创建一个用于财务管理的类,那么该类不仅可以通过其他程序来访问,而且还可用于其他合作者的应用程序。比如,一张Excel电子数据表可能就需要这样的数据,或者一个C++程序员可能需要获取他人最新工程的一些信息,等等。

   但是,当我们将所需要的类添加到标准的Visual Basic应用程序中,或是再编译成最终的EXE程序时,其他人仍然不能在程序内部处理类或属性。

   解决这个问题的方法是将所有的类投放到其他人的各自程序中,这称为"COM-enabled"。

   换句话说,假如类有AnnualProfitsToDate属性,一旦该属性得到后,类就会遍历公司的数据库,然后进行相应的一些计算,最后返回一个数值,该值单位可能是英磅、美元、日元或是其它。

   现在,若Excel用户需要对数据库进行上述处理,则只需简单地提供"类程序",而不是真正的代码。该程序释放类和AnnualProfitsToDate属性,允许其他用户将其插入到程序中去。同样,我们也不必告诉C++程序员如何进行人工统计(尽管他能够处理),只需要提供给这个程序就可以了。这样,就减少了大家许多工作。

   这种在Visual Basic工程中添加类后,还将类放进各自程序中的方法,称为ActiveX组件方法。

   在这种方法中,ActiveX程序中的所有功能都可以被其他支持ActiveX的程序语言来处理。换句话说,AnnualProfitsToDate属性既可被Excel、C++得到,也可被Access等其他程序处理。

   那么,如何创建一个用来处理我们的类的ActiveX程序呢?


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:24
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

让我们直接来开始创建第一个真正的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 Recordset

   rs.ActiveConnection = "Provider=Microsoft." & _

             "Jet.OLEDB.4.0;Data Source=C:\Program Files\" & _

             "Microsoft Visual Studio\VB98\Nwind.mdb;" & _

             "Persist Security Info=False"

   rs.Open "select * from customers", , adOpenKeyset, adLockOptimistic
   这里不需要任何与该类相关的代码,它只是使用Visual Basic通用的ADO数据库处理代码,该类中的代码是用来如何与数据库建立连接的。

   需要说明的是,如果Northwind数据库Nwind.mdb不在C:\Program Files\Microsoft Visual Studio\VB98文件夹,那么必须将ActiveConnection字符串内容作适当修改!

   当类开始时,rs对象负责与数据库建立连接,但当类对象结束后或程序关闭它时,我们应该使该连接断开。

   编程时,我们使用Terminate事件,它与Form_Unload非常相似的。从名称来看,它们都有一个"n",但更相似的地方是当相应的对象关闭后,它们都会被激发。

   下面来加入数据库关闭的代码:

   从Object组合框中选择"Class",从Procedure组合框中选择"Terminate";

   在"Terminate"事件中,添加下列代码:

  rs.Close

   Set rs = Nothing
   这就是我们添加的又一段简单代码,它只是简单地关闭数据库,然后将rs设置为Nothing。这样,rs就会被有效删除。

   好了,本节就到这里。下一节中,我们将继续添加代码用来处理数据中的记录集。


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:25
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

下面,我们添加一个属性来让用户获取CustomerID字段的值,其相应的示例代码如下:

  Public Property Get CustomerID() As String
    CustomerID = rs("CustomerID")
   End Property

   Public Property Let CustomerID(NewValue As String)
    rs("CustomerID") = NewValue
   End 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 String
    CustomerID = rs("CustomerID")
   End Property
   Public Property Let CustomerID(NewValue As String)
    'If the length of NewValue is greater than five
    If Len(NewValue) > 5 Then
     '... then raise an error to the program
     'using this class
     Err.Raise vbObjectError + 1, "CustomerID", _"Customer ID can only be up to five " & _"characters long!"
    Else
     '... otherwise, change the field value
     rs("CustomerID") = NewValue
    End If
   End Property
   好了,在完成下列步骤之前,我们已经为添加方法花费了不少时间。

   在我们的类中添加下列代码:

  Public Sub Update()
    rs.Update
   End Sub
   该Update方法只是简单地调用记录集对象的Update方法来更新记录。

   下一步,我们将用一个很小的样例程序来测试这个属性和方法,在测试时还将使用特定的技巧来追踪类和程序的运行。


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:26
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 

现在就来测试前面创建的类。

   按F5运行程序;在弹出的属性对话框中,选中"Wait for Components to Start"(启动工程时等待创建部件),然后按[OK]按钮;

   这时,类就会被激活,其他程序就可使用它的功能。

   再次运行Visual Basic另一个实例;

   创建一个新的"Standard EXE"工程;

   选择"'Project"->"References"菜单;

   浏览对话框中可引用的列表项,可以发现一些额外的组件。

   选中"Northwind"列表项;

   Northwind就是前面创建的ActiveX工程。

   单击[OK]按钮;

   现在添加一些代码来使用上述工程:

   在Form1表单中添加一个命令按钮;为命令按钮添加下列代码:

  Dim Test As Customers
   Set Test = New Customers
   MsgBox Test.CustomerID
   Set 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 Customers
   Set Test = New Customers
   Test.CustomerID = "KARLY"
   Test.Update
   MsgBox Test.CustomerID
   Set Test = Nothing
   该代码首先设置"CustomerID"字段,然后更新记录集,最后显示出CustomerID属性,其结果应该是设置的"KARLY"。

   假如愿意,仍然可以按F9高亮显示"Test.CustomerID =" 这条语句,然后按F8单步运行来查看其工作情况。

   至此,我们已经成功地创建并测试一个简单的基于数据库的类。但是,还没有对customerID的字符串长度作测试,如果其长度超过5个字符,看看会发生什么?

下一步,我们将扩充并改进这个数据库类。

   首先添加类的几个特征:其他的属性、一些方法甚至一两个事件。 其相应的代码如下:

  Dim WithEvents rs As Recordset
   Public 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 Studio\VB98\Nwind.mdb;" & _"Persist Security Info=False"
    rs.Open "select * from customers", , adOpenKeyset, adLockOptimistic
   End Sub

   Private Sub Class_Terminate()
    rs.Close
    Set rs = Nothing
   End Sub

   Public Property Get CustomerID() As String
    CustomerID = rs("CustomerID")
   End Property

   Public Property Let CustomerID(NewValue As String)
    'If the length of NewValue is greater than five
    If Len(NewValue) > 5 Then
     '... then raise an error to the program
     'using this class, by running
     'Err.Raise vbObjectError + OurErrorNumber
     Err.Raise vbObjectError + 1, "CustomerID", _"Customer ID can only be up to five " & _ "characters long!"

    Else
     '... otherwise, change the field value
     rs("CustomerID") = NewValue
    End If
   End Property


/images/2011/147787/2011051411021524.jpg" border="0" />
2007-04-15 18:28
快速回复:[转载]Visual Basic COM 讲座
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017092 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved