CorelDraw插件开发教程(8):变量和对象
Category:COREL插件原创: 刘肖健 创意之代码 1周前
CorelDraw插件开发教程(8):变量和对象
刘肖健
浙江工业大学工业设计研究院
11. 数据类型:变量和对象
11.1 变量
VBA的常用数据类型有:
Double:实数
Integer:整数
Long:长整数
Boolean:布尔型数
String:字符串
当我们在程序中使用常数时,比如90,它有可能是实数、整数、字符串,为了指示数据类型,通常在常数后面加个符号,如90#表示实数90,Double型数据,$表示String型数据;%表示Integer型数据;&表示Long型数据。
定义变量用Dim语句:
Dim x As Double : x=3.14
Dim i As Integer : i=50
Dim R As Long : R=255
Dim myName as String : myName=”Bill”
Dim blackOrNot as Boolean : blackOrNot=True
有关变量定义的一些说明:
1)变量的定义可以放在程序的任何位置,这个跟C语言不一样,不要求必须放在前面先把所有变量都定义完了再开始执行性的语句。
2)一个变量名只能定义一次,否则出错,系统提示“变量重定义”。所以不能在循环内部定义变量,因为每次执行循环都会对同一个变量进行定义,重定义了。
3)变量的命名有一定的规则,请查看VBA帮助文档。
4)变量命名要避开关键字。关键字包括Dim、Sub、For等系统已经“占用”的字,以及Sin、Cos等已经存在的函数名。
5)变量可以不定义而直接用,如果没赋值,则其值默认为是等于0的数值量。所以,一个被敲错的变量名会被系统当做一个新变量,且其值为零,但系统不会指出这一错误。为了避免变量名敲错查找困难,可以强制要求所有变量必须定义才能使用,否则就报错。具体方法是在程序文档的第一行加一句:
Option Explicit
有了这句,整个文档的变量必须都要先定义才能使用。
变量的作用范围:
1)子程序(Sub)和函数(Function)内部定义的变量(即内部变量),只能在Sub和Function内部使用。所以可以在不同的Sub或Function内部定义名称一样的变量,而不会得到“变量重定义”的系统报错。
2)一个文档(窗体或模块)中,在所有Sub和Function外面定义的变量(即外部变量),可以在整个文档中通用,各Sub和Function都可以使用它,如在一个Function中为一个变量赋值,可以在另一个Function中使用这个值。
3)内部变量可以与外部变量重名,此时只有内部变量起作用。
4)如果想在一个文档(窗体或模块)中使用另一个文档中定义的变量,则该变量必须被定义为“公有型”,语句格式是用Public代替Dim,如:Public bmpHeight As Double
11.2 对象
对象可以简单理解为“复杂”的变量。除了整数、实数、字符串等常见数据类型外,在制作界面时会遇到对话框、按钮、输入框等复杂数据,在设计过程中会遇到图形、曲线、色彩、页面等复杂的数据,它们称为对象。
我们前面的例子中遇到最多的对象就是Shape:
Dim s1 As Shape
Set s1 = ActiveLayer.CreateEllipse2(x, y, r, r, 90#,90#, False)
定义一个变量为某对象数据类型,与常规变量的定义一样,也是用Dim语句。但对象类变量不能直接用等号“=”赋值,而是要在前面增加关键字“Set”。
对象跟一般的变量不一样,它可以带有自己“下属”的变量、对象、函数、子程序。
上述语句中的另一个对象ActiveLayer,它是一个CorelDraw内部定义的Layer型对象,用于指代当前绘图层。大部分直接创建图形的函数(如CreateEllipse2)都是Layer型对象的下属函数。
当我们在界面上建立了一个按钮,并取了名,就定义了一个CommandButton类型的对象,可以通过下述方法观察该对象“下属”的内容:
1)在任何位置键入对象名,如前面定义的按钮对象DrawCirclePage;
2)在对象名后键入点号“.”,则该对象的下属内容会自动跳出,按字母顺序排列:
可以看到,这里的很多下属变量都是按钮的属性,如高度(Height)、宽度(Width)、位置(Left/Top)、色彩(BackColor)、文字(Caption)、图片(Picture)等。这些属性可以在属性窗口修改,也可以在程序中用代码修改。
下面编写一个简单的“逃跑按钮”小游戏,来解释如何在事件子程序中修改对象下属变量。
这个游戏程序是这样运行的:界面上有一个按钮,点击它会启动单击事件(Click)并弹出对话框显示“Bingo!”。但是当鼠标掠过该按钮时会启动鼠标移动事件(MouseMove),该事件将改变按钮的位置,将其改到对话框界面上的一个随机位置。如此,鼠标的位置就会落空,导致点不到按钮,除非按钮位置改变后刚好鼠标还在其上。
这个程序的代码非常简单,按5.4节所述的方法为所创建的Button_Escape按钮添加Click和MouseMove事件,然后写入如下代码:
Private Sub Button_Escape_Click()
MsgBox “Bingo!”
End Sub
Private Sub Button_Escape_MouseMove(ByVal Button AsInteger, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Button_Escape.Top = Rnd * (Escape.Height – 2 *Button_Escape.Height)
Button_Escape.Left = Rnd * (Escape.Width -Button_Escape.Width)
End Sub
按钮的“逃跑”动作通过修改按钮对象的Top和Left两个变量实现。Top是指按钮与对话框上边界的距离,Left是指按钮与对话框左边界的距离,以像素计算。Escape是对话框(对象)的名称,Escape.Height和Escape.Width分别为对话框的高度和宽度。
运行后出现如下对话框:
当鼠标划过按钮时,按钮就会“逃跑”,随机出现在另一个位置上。
11.3 CorelDraw的常用对象
这里简单介绍一下CorelDraw常用的几个对象。
1)Application
Application对象是指当前的CorelDraw软件。如果我们想知道当前使用的CorelDraw版本,可以用如下代码获得:
MsgBox Application.Version
上述代码会弹出一个对话框,告诉你当前的软件版本号:
你可能会觉得知道版本号没什么意义,但是对程序是有意义的,因为不同的CorelDraw版本的VBA库略有不同,有的插件在X3运行良好,但是在X7或X8上运行就会出错。下述代码是根据版本号来调用不同子程序的示例:
Dim cdrVersion As String
cdrVersion = Left(Application.Version, 2)
If cdrVersion = “13” Then
‘调动X3版插件功能
DrawCircleRow_Ver13
ElseIf cdrVersion = “15” Then
‘调用X5版插件功能
DrawCircleRow_Ver15
End If
If CInt(cdrVersion) <= 12 Then
MsgBox “本插件仅用于CorelDraw X3以上版本。”
Exit Sub
End If
在上述代码中,我们为“画一行圆”这个子程序准备了若干个版本的函数,它们的名称分别为DrawCircleRow_Ver13、DrawCircleRow_Ver15等。Application.Version是一个字符串,它的最前面两个数字就是大的版本号,后面还有些数字表示该版本下的各种小的改进版。我们只需要知道大的版本号即可,所以用Left函数把字符串的最前面两个字符提取出来。Left函数的用法可以查阅VBA语法帮助得到。
由于CorelDraw 12以前的版本区别比较大,所以插件不适用于12以前的老版。这时就不针对每个版本分别响应了,而是把用Left提取出来的两个字符(如“13”)转换成整数,然后再判断它的大小,如果小于或等于12,就弹出对话框给出提示,然后终止程序。
注意,字符串12和整数12是两个不同类型的数据,前者是String型,后者是Integer型。字符串12代表两个字符,跟“ab”、“*&”一样,仅仅是两个字符而已。字符是没有大小的,只有整数才能比较大小,所以使用CInt函数把字符串强制转换成对应的整数。
2)Document
Application对象用到的场合并不多,除了版本号之外,能常用到的有它的如下两个成员(下属)对象:
Application.ActiveDocument
Application.Documents(n)
Application对象的这两个成员对象在使用时都可以不带前面的Application对象名。ActiveDocument是指当前文档;Documents(n)是指处于打开状态的第n个文档。
Application.Documents.Count则是指当前打开的文档数量。
Document对象用于指代.cdr文档。下述代码先告诉用户当前打开了几个文档,然后关闭第一个打开的文档。
Dim n as Integer
n= Application.Documents.Count
Application.Documents(n).Close
3)Page
Page是Document对象的成员,指文档中的页面。以下代码增加一个新页面,为其重新命名并修改其宽高:
Dim myPage As Page
Set myPage = ActiveDocument.AddPages(1)
myPage.Name = “TestPage”
‘设置当前文档的长度单位为毫米(默认是英寸)
ActiveDocument.Unit = cdrMillimeter
myPage.SizeHeight = 210
myPage.SizeWidth = 297
4)Layer
图层(Layer)是页面(Page)的子对象,也是页面的下一级组织结构。大部分直接画图的命令,如画矩形、画圆、画自由曲线等都是Layer的下属成员函数,因为画图形必须选定画在哪个图层上。
观察自动记录下来的代码可以发现,默认的图形都是创建在一个名为ActiveLayer的图层上。ActiveLayer也是Page的子对象,它可以直接使用,前面不用带它的父对象Page。
5)Shape
Shape对象是用的最多的CorelDraw VBA对象,它用于指代一个图形、一张图片、一个群组等。前面已经见过很多Shape对象的用法,此处不再赘述,后面还会有更多案例。
6)Fill
Fill是Shape的子对象,用于表示图形的填充特性。我们在一个Shape对象名后面的Fill后敲一个点号“.”,就会看到各种填充模式的列表:
“Apply”开头的函数都是各种填充模式,中最后一个ApplyUniformFill是最常见的单色平涂。各种填充模式的具体用法可以查阅CorelDraw VBA的帮助文档。
7)Color
Color是一个图形的色彩信息,获取一个平涂图形的色彩可以用如下代码:
Dim myColor As Color
Set myColor = ActivePage.Shapes(1).Fill.UniformColor
如果Shape图形不是平涂填充的,则其UniformColor对象为空,上面的代码myColor会得到一个不存在的对象。获得图形的色彩对象后,如果想知道色彩的进一步数据,比如获取该色的GRB值或HSB值,可以用如下代码实现:
Dim clrRed As Long, clrGreen As Long, clrBlue As Long
clrRed = myColor.RGBRed
clrGreen = myColor.RGBGreen
clrBlue = myColor.RGBBlue
MsgBox “RGB Color:” & clrRed & “,” &clrGreen & “,” & clrBlue
8)Curve
Curve是Shape对象的子对象,它用于表示Shape图形对象中的曲线,如边界线或内部曲线。
9)SubPath
SubPath是Curve对象的子对象。因为一个Shape对象的Curve有可能有多条曲线构成,如一个内部开了一个洞的矩形,这个Shape的Curve就包含两条SubPath。
用下面的代码可以弹出对话框显示这个图形里的SubPath数。
MsgBox ActivePage.Shapes(1).Curve.SubPaths.Count
上述代码中,ActivePage.Shapes(1)是指当前页面中最新创建的图形:新图形的编号排第一,如果又创建了一个图形,则刚才的图形变成Shapes(2)。如果我们想找到页面中第一个建立的图形应该怎么办呢?
很简单,它是ActivePage.Shapes(ActivePage.Shapes.Count),ActivePage.Shapes.Count是当前页面中的图形总数,也就是最末一个编号,也就是最先创建的图形的当前编号。
下面的代码可以显示一个Subpath围成的面积大小,如果不是封闭的,则显示零。
MsgBox ActivePage.Shapes(1).Curve.SubPaths(1).Area
10)Node
Node是SubPath曲线的节点。CorelDraw的曲线是用三次贝塞尔曲线表达,Node即贝塞尔曲线的节点。要想了解有关贝塞尔曲线及其节点的技术细节,可以查阅计算机图像学的相关资料。
下述代码可以在图形的第一条SubPath的每个节点上画一个小圆圈,标识节点的位置:
Dim i As Integer, n As Integer
Dim x As Double, y As Double
Dim sp As SubPath, myNode As Node
Set sp = ActivePage.Shapes(1).Curve.SubPaths(1)
n = sp.Nodes.Count
For i = 1 To n
Set myNode =sp.Nodes(i)
x =myNode.PositionX
y =myNode.PositionY
ActiveLayer.CreateEllipse2x, y, 5, 5
Next
代码执行效果如下图所示:
上述曲线的每个节点上都被画了一个小圆圈。
11)Segment
Segment是SubPath的子对象,指SubPath中两个相邻的Node之间的那一段曲线。上图的曲线有5个Node,它包含4个Segment。
Segment对象已经深入到曲线形态的图形学底层,通过Segment可以获得很多曲线的特征数据,如节点处的切向、法向、控制点位置等。比如我们要判断一条曲线上是否有尖点,只要测试每一个Node在前后两个Segment处的切向方向是否一致即可,如果不一致,则表示该处有尖点,否则曲线在该处光滑。
http://mip.i3geek.com