Chinaunix首页 | 论坛 | 博客
  • 博客访问: 14523528
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 21:04:03

下载本文示例代码
髡咧饕常?傻儿VB园 作者信箱:王文涛   作者在写《傻瓜打表》部件时,原本想提供打印预览功能,因当时眼界较窄,所知道的只有一个方法实现打印预览: 定义一个 Object 变量(如:ObjPrn),用该变量替换程序中的与打印有关的语句中的 Printer 对象,打印时,首先设置 Set ObjPrn = Printer 预览时设置 Set ObjPrn = frmPreV.Picture1   用上述方法虽然可以实现打印和预览,但是,显然对打印机和实现预览的图像控件的访问都是后期邦定的,这在效率上是不高的。打算使用多态技术,可是 Printer 对象和 Picturebox控件不是从一个类(VB中可引用的)派生的。因无法实现打印和预览的前期绑定,故没有提供打印预览功能。   一天,当再次阅读VB帮助中的多态章节时,突然想到了一个方法,使用该方法,只要两个类具有相同的部分接口(方法、属性及参数),即便这两个类毫不相干,也可以通过变相用多态技术提供对这两个类的前期绑定。 多态是干什么的?   MSDN说:多态意味着许多类可以提供同样的属性或者方法,而且调用者在调用这些属性或方法之前,不必知道某个对象属于什么类。 多态的意义之一就是,通过多态接口,对多个不同类的访问可以获得高效的前期绑定。   一般来说,如果几个类具有部分相同的属性、方法,但却不是用多态接口实现的(例如Printer和Form),将不能提供类似多态的性能。 但是,“软件”正如其名字中的“软”,是一个灵活的、可塑的东西,我们可以改变思维模式,换一个角度:没有多态接口的两个类(如Printer、Picturebox)如同两个人不同父,不是兄弟;但我们可以让其子同娶一家之女(另外具有多态接口的两个类),其子为连襟,其儿媳为姐妹,而通过其儿媳访问其本人具有相同的路径。   还以上例,其中的关键是:添加三个类,分别Printer之妻、Picturebox之妻、二女之父(在二女中要实现的、Printer和Picturebox共有的部分接口)。下面就用打印和预览为例,介绍该方法: 第一步、添加一个抽象类,在该类中定义共同的方法和属性。   如果方法名称是VB关键字,可以修改(如Line方法,本例中改为pLine方法);如果参数形式不符合VB语法,也可作相应修改(如本例中Line方法的参数,应为"(X1, -(X2,Y2),Forcolor,BF",显然,在VB中的参数不能用这种形式;还有Print方法,打印参数之间、后面可以跟逗号、分号等,也要相应改变,并且不能提供全部原来Print方法功能) : 类名:IMyPrinter,为简化,示例中仅包含作为示例的接口。 Public Property Get CurrentX() As Single End Property Public Property Let CurrentX(ByVal RHS As Single) End Property Public Sub EndDoc() End Sub Public Property Get Font() As stdole.Font End Property Public Property Set Font(ByVal RHS As stdole.Font) End Property Public Sub PLine(ByVal X1 As Single, ByVal Y1 As Single, ByVal X2 As Single, _       ByVal Y2 As Single, Optional ByVal HasB As Boolean = False, _       Optional ByVal HasF As Boolean = False) End Sub Public Function ScaleX(ByVal Width As Single, Optional ByVal FromScale As Variant, _       Optional ByVal ToScale As Variant) As Single End Function Public Function TextWidth(ByVal Str As String) As Single End Function Public Property Let Width(ByVal RHS As Long) End Property Public Property Get Width() As Long End Property Public Sub PPrint(Optional ByVal F0D1H2 As Integer = 0, Optional PrnInfo) End Sub 第二步、添加两个类,实现该接口,并分别提供Printer对象和Picturebox控件相应的功能。   下面仅以在Picturebox控件上实现该接口的类的部分代码作为示例:还需要添加一个实现预览的窗体(frmPreView),在上面添加一个Picturebox控件(pic) 类名:MyPic Implements IMyPrinter Dim frm As frmPreview Private pic As PictureBox Private Sub Class_Initialize()  Set frm = New frmPreview  Load frm  Set pic = frm.pic End Sub Private Sub Class_Terminate()  Set pic = Nothing  Unload frm  Set frm = Nothing End Sub Private Property Let IMyPrinter_CurrentX(ByVal RHS As Single)  pic.CurrentX = RHS End Property Private Property Get IMyPrinter_CurrentX() As Single  IMyPrinter_CurrentX = pic.CurrentX End Property Private Sub IMyPrinter_EndDoc()  frm.Show vbModal End Sub Private Property Get IMyPrinter_Font() As StdFont Dim F As StdFont  Set F = New StdFont  With pic.Font   F.Size = .Size   F.Name = .Name   F.Size = .Size   F.Bold = .Bold   F.Italic = .Italic   F.Strikethrough = .Strikethrough   F.Underline = .Underline   F.Weight = .Weight  End With Set IMyPrinter_Font = F End Property Private Property Set IMyPrinter_Font(ByVal RHS As StdFont)  With pic.Font   .Size = RHS.Size   .Name = RHS.Name   .Size = RHS.Size   .Bold = RHS.Bold   .Italic = RHS.Italic   .Strikethrough = RHS.Strikethrough   .Underline = RHS.Underline   .Weight = RHS.Weight  End With End Property Private Sub IMyPrinter_PLine(ByVal X1 As Single, ByVal Y1 As Single, ByVal X2 As Single, ByVal Y2 As Single, Optional ByVal HasB As Boolean = False, Optional ByVal HasF As Boolean = False)  If HasF Then "本例中没有提供颜色选项   pic.Line (X1, Y1)-(X2, Y2), , BF  ElseIf HasB Then   pic.Line (X1, Y1)-(X2, Y2), , B  Else   pic.Line (X1, Y1)-(X2, Y2)  End If End Sub Private Sub IMyPrinter_PPrint(Optional ByVal F0D1H2 As Integer = 0, Optional PrnInfo As Variant)  Select Case F0D1H2 "该参数为0:跟分号;1:跟逗号;2:无符号   Case 0    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo;    End If   Case 1    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo,    End If   Case 2    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo    Else     pic.Print    End If  End Select End Sub Private Function IMyPrinter_ScaleX(ByVal Width As Single, Optional ByVal FromScale As Variant, Optional ByVal ToScale As Variant) As Single  IMyPrinter_ScaleX = pic.ScaleX(Width, FromScale, ToScale) End Function Private Function IMyPrinter_TextWidth(ByVal Str As String) As Single  IMyPrinter_TextWidth = pic.TextWidth(Str) End Function Private Property Get IMyPrinter_Width() As Long  IMyPrinter_Width = pic.Width End Property Private Property Let IMyPrinter_Width(ByVal RHS As Long)  pic.Width = RHS End Property 第三步、在主类模块定义如下变量 Private cIMyPrn As IMyPrinter Private cPic As MyPic Private cPrn As MyPrn 在主类模块Class_Initialize事件中,添加: Set cPrn As New MyPrn Set cIMyPrn = cPrn 在主类模块中,将原来有关打印语句中的Printer替换为cIMyPrn。在实现预览的方法中,添加: Set cPic = New MyPic Set cIMyPrn = cMyPic 修改特殊类型的语句(如Line、Print,方法名和参数形式已经改变,将其改为符合cIMyPrn语法的语句) 预览结束后: Set cIMyPrn = cPrn Set cPic = Nothing   通过上面的方法,就可以用一个IMyPrinter变量,实现打印和预览的前期绑定当然,该方法未必是实现打印、预览的首选,还可以使用API方法,直接操纵设备场景来实现打印预览,但该方法的意义不在于此,其意义在于该方法拓展了VB中提供的多态技术的应用范围。 本文副标题中的所谓“高层次”不是作者层次高,而是编程方法和思路,不是面向底层、面向Win核心,而是在对象的高层、在编程语言和方法的较高层上实现多态。 髡咧饕常?傻儿VB园 作者信箱:王文涛   作者在写《傻瓜打表》部件时,原本想提供打印预览功能,因当时眼界较窄,所知道的只有一个方法实现打印预览: 定义一个 Object 变量(如:ObjPrn),用该变量替换程序中的与打印有关的语句中的 Printer 对象,打印时,首先设置 Set ObjPrn = Printer 预览时设置 Set ObjPrn = frmPreV.Picture1   用上述方法虽然可以实现打印和预览,但是,显然对打印机和实现预览的图像控件的访问都是后期邦定的,这在效率上是不高的。打算使用多态技术,可是 Printer 对象和 Picturebox控件不是从一个类(VB中可引用的)派生的。因无法实现打印和预览的前期绑定,故没有提供打印预览功能。   一天,当再次阅读VB帮助中的多态章节时,突然想到了一个方法,使用该方法,只要两个类具有相同的部分接口(方法、属性及参数),即便这两个类毫不相干,也可以通过变相用多态技术提供对这两个类的前期绑定。 多态是干什么的?   MSDN说:多态意味着许多类可以提供同样的属性或者方法,而且调用者在调用这些属性或方法之前,不必知道某个对象属于什么类。 多态的意义之一就是,通过多态接口,对多个不同类的访问可以获得高效的前期绑定。   一般来说,如果几个类具有部分相同的属性、方法,但却不是用多态接口实现的(例如Printer和Form),将不能提供类似多态的性能。 但是,“软件”正如其名字中的“软”,是一个灵活的、可塑的东西,我们可以改变思维模式,换一个角度:没有多态接口的两个类(如Printer、Picturebox)如同两个人不同父,不是兄弟;但我们可以让其子同娶一家之女(另外具有多态接口的两个类),其子为连襟,其儿媳为姐妹,而通过其儿媳访问其本人具有相同的路径。   还以上例,其中的关键是:添加三个类,分别Printer之妻、Picturebox之妻、二女之父(在二女中要实现的、Printer和Picturebox共有的部分接口)。下面就用打印和预览为例,介绍该方法: 第一步、添加一个抽象类,在该类中定义共同的方法和属性。   如果方法名称是VB关键字,可以修改(如Line方法,本例中改为pLine方法);如果参数形式不符合VB语法,也可作相应修改(如本例中Line方法的参数,应为"(X1, -(X2,Y2),Forcolor,BF",显然,在VB中的参数不能用这种形式;还有Print方法,打印参数之间、后面可以跟逗号、分号等,也要相应改变,并且不能提供全部原来Print方法功能) : 类名:IMyPrinter,为简化,示例中仅包含作为示例的接口。 Public Property Get CurrentX() As Single End Property Public Property Let CurrentX(ByVal RHS As Single) End Property Public Sub EndDoc() End Sub Public Property Get Font() As stdole.Font End Property Public Property Set Font(ByVal RHS As stdole.Font) End Property Public Sub PLine(ByVal X1 As Single, ByVal Y1 As Single, ByVal X2 As Single, _       ByVal Y2 As Single, Optional ByVal HasB As Boolean = False, _       Optional ByVal HasF As Boolean = False) End Sub Public Function ScaleX(ByVal Width As Single, Optional ByVal FromScale As Variant, _       Optional ByVal ToScale As Variant) As Single End Function Public Function TextWidth(ByVal Str As String) As Single End Function Public Property Let Width(ByVal RHS As Long) End Property Public Property Get Width() As Long End Property Public Sub PPrint(Optional ByVal F0D1H2 As Integer = 0, Optional PrnInfo) End Sub 第二步、添加两个类,实现该接口,并分别提供Printer对象和Picturebox控件相应的功能。   下面仅以在Picturebox控件上实现该接口的类的部分代码作为示例:还需要添加一个实现预览的窗体(frmPreView),在上面添加一个Picturebox控件(pic) 类名:MyPic Implements IMyPrinter Dim frm As frmPreview Private pic As PictureBox Private Sub Class_Initialize()  Set frm = New frmPreview  Load frm  Set pic = frm.pic End Sub Private Sub Class_Terminate()  Set pic = Nothing  Unload frm  Set frm = Nothing End Sub Private Property Let IMyPrinter_CurrentX(ByVal RHS As Single)  pic.CurrentX = RHS End Property Private Property Get IMyPrinter_CurrentX() As Single  IMyPrinter_CurrentX = pic.CurrentX End Property Private Sub IMyPrinter_EndDoc()  frm.Show vbModal End Sub Private Property Get IMyPrinter_Font() As StdFont Dim F As StdFont  Set F = New StdFont  With pic.Font   F.Size = .Size   F.Name = .Name   F.Size = .Size   F.Bold = .Bold   F.Italic = .Italic   F.Strikethrough = .Strikethrough   F.Underline = .Underline   F.Weight = .Weight  End With Set IMyPrinter_Font = F End Property Private Property Set IMyPrinter_Font(ByVal RHS As StdFont)  With pic.Font   .Size = RHS.Size   .Name = RHS.Name   .Size = RHS.Size   .Bold = RHS.Bold   .Italic = RHS.Italic   .Strikethrough = RHS.Strikethrough   .Underline = RHS.Underline   .Weight = RHS.Weight  End With End Property Private Sub IMyPrinter_PLine(ByVal X1 As Single, ByVal Y1 As Single, ByVal X2 As Single, ByVal Y2 As Single, Optional ByVal HasB As Boolean = False, Optional ByVal HasF As Boolean = False)  If HasF Then "本例中没有提供颜色选项   pic.Line (X1, Y1)-(X2, Y2), , BF  ElseIf HasB Then   pic.Line (X1, Y1)-(X2, Y2), , B  Else   pic.Line (X1, Y1)-(X2, Y2)  End If End Sub Private Sub IMyPrinter_PPrint(Optional ByVal F0D1H2 As Integer = 0, Optional PrnInfo As Variant)  Select Case F0D1H2 "该参数为0:跟分号;1:跟逗号;2:无符号   Case 0    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo;    End If   Case 1    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo,    End If   Case 2    If Not IsMissing(PrnInfo) Then     pic.Print PrnInfo    Else     pic.Print    End If  End Select End Sub Private Function IMyPrinter_ScaleX(ByVal Width As Single, Optional ByVal FromScale As Variant, Optional ByVal ToScale As Variant) As Single  IMyPrinter_ScaleX = pic.ScaleX(Width, FromScale, ToScale) End Function Private Function IMyPrinter_TextWidth(ByVal Str As String) As Single  IMyPrinter_TextWidth = pic.TextWidth(Str) End Function Private Property Get IMyPrinter_Width() As Long  IMyPrinter_Width = pic.Width End Property Private Property Let IMyPrinter_Width(ByVal RHS As Long)  pic.Width = RHS End Property 第三步、在主类模块定义如下变量 Private cIMyPrn As IMyPrinter Private cPic As MyPic Private cPrn As MyPrn 在主类模块Class_Initialize事件中,添加: Set cPrn As New MyPrn Set cIMyPrn = cPrn 在主类模块中,将原来有关打印语句中的Printer替换为cIMyPrn。在实现预览的方法中,添加: Set cPic = New MyPic Set cIMyPrn = cMyPic 修改特殊类型的语句(如Line、Print,方法名和参数形式已经改变,将其改为符合cIMyPrn语法的语句) 预览结束后: Set cIMyPrn = cPrn Set cPic = Nothing   通过上面的方法,就可以用一个IMyPrinter变量,实现打印和预览的前期绑定当然,该方法未必是实现打印、预览的首选,还可以使用API方法,直接操纵设备场景来实现打印预览,但该方法的意义不在于此,其意义在于该方法拓展了VB中提供的多态技术的应用范围。 本文副标题中的所谓“高层次”不是作者层次高,而是编程方法和思路,不是面向底层、面向Win核心,而是在对象的高层、在编程语言和方法的较高层上实现多态。 下载本文示例代码


改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态改变思路,从另一个角度使用多态
阅读(111) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~