你當(dāng)前的位置>>主頁(yè)>>AutoCAD知識(shí)>>AutoCAD二次開(kāi)發(fā)
 
           應(yīng)用Automation技術(shù)進(jìn)行AutoCad的開(kāi)發(fā)

Autodesk公司的AutoCad軟件廣泛的應(yīng)用于建筑、機(jī)械等設(shè)計(jì)領(lǐng)域。眾所周知,AutoCad是一種極其靈活的應(yīng)用系統(tǒng),用戶可以通過(guò)編程的方式對(duì)其進(jìn)行定制。在以往的AutoCad系統(tǒng)開(kāi)發(fā)中,最常用的是AutoLisp和ADS,但AutoLisp不如編程語(yǔ)言方便,在開(kāi)發(fā)較大項(xiàng)目時(shí)力不從心,而ADS雖由功能強(qiáng)大的C語(yǔ)言編制,但較為復(fù)雜,不適應(yīng)當(dāng)前可視化編程的需要。幸運(yùn)的是,在最新推出的AutoCad r14版本中,Autodesk公司對(duì)AutoCad本身加入了ActiveX自動(dòng)化服務(wù)功能(ActiveX Automation server capabilities),使得用戶可以通過(guò)可視化編程工具,如Visual Basic、Delphi等對(duì)AutoCad進(jìn)行系統(tǒng)開(kāi)發(fā),極大的提高了工作效率。在最近為建筑公司開(kāi)發(fā)的一套建筑施工三維演示系統(tǒng)中,我們采用AutoCad為平臺(tái),Visual Basic為編程工具,成功的應(yīng)用ActiveX對(duì)AutoCad進(jìn)行了二次開(kāi)發(fā)。本文將從編程實(shí)踐的角度對(duì)使用VB對(duì)AutoCad控制的技術(shù)及遇到的問(wèn)題進(jìn)行簡(jiǎn)要的說(shuō)明。

   一、 AutoCad的對(duì)象模型(AutoCad Object Model)

   如果一個(gè)應(yīng)用程序支持自動(dòng)化,那么其他應(yīng)用程序就可以通過(guò)其暴露的對(duì)象(Object)對(duì)其自動(dòng)操作。在本例中,我們開(kāi)發(fā)的程序?yàn)榭蛻魴C(jī),AutoCad是服務(wù)器,應(yīng)用程序正是通過(guò)對(duì)AutoCad暴露的各級(jí)對(duì)象進(jìn)行操作而控制AutoCad工作的。對(duì)象本身包含自己的方法和屬性。通過(guò)方法可以實(shí)現(xiàn)對(duì)象的一些操作,而對(duì)象狀態(tài)信息的收集或改變則是通過(guò)屬性完成。例如,直線是AutoCad中的一個(gè)對(duì)象,它的屬性可以是線形、起始點(diǎn)坐標(biāo)、所在層等性質(zhì),方法則有拷貝、鏡像等操作。

   理解AutoCad的對(duì)象模型是對(duì)其編程的基礎(chǔ)。AutoCad以層次結(jié)構(gòu)組織對(duì)象。在頂層是Application對(duì)象(即AutoCad 本身),其他對(duì)象均為Application對(duì)象的子對(duì)象。在Application對(duì)象下面是Preferences(優(yōu)先設(shè)置)和Document(文檔)對(duì)象,通過(guò)Preferences對(duì)象可以對(duì)AutoCad Tools>Preferences菜單項(xiàng)中的幾乎每一個(gè)選項(xiàng)進(jìn)行訪問(wèn)和修改,以獲取或改變AutoCad的優(yōu)先設(shè)置。Document對(duì)象是控制AutoCad圖形文件的直接對(duì)象,它代表某一個(gè)裝入的CAD圖形文件(一般設(shè)為當(dāng)前激活的文件)。Document對(duì)象下面有Model Space(模型空間)和Paper Space(圖紙空間)對(duì)象及Blocks(塊)、Layers (層)、Plot(出圖)、Selectionsets(選擇集)、 views(視圖)、 utility(功能)等一系列對(duì)象(集合),其含義與AutoCad中相似。Model Space是當(dāng)前圖形文件中圖形實(shí)體,如直線、圓、多義線等的集合,每個(gè)實(shí)體即是一個(gè)對(duì)象,可通過(guò)屬性和方法改變實(shí)體或生成新實(shí)體。

   對(duì)非圖形實(shí)體,如層(layer)、線形(line type)等的訪問(wèn)則通過(guò)訪問(wèn)Document對(duì)象下面的相應(yīng)的集合類(lèi)型的子對(duì)象,如Layers 、LineTypes等來(lái)實(shí)現(xiàn)。集合類(lèi)型的對(duì)象可以使用VB中所有的集合操作方法。Plot對(duì)象提供了訪問(wèn)Plot對(duì)話框中各選項(xiàng)的橋梁,使應(yīng)用程序具有用不同方式控制AutoCad出圖的能力。Utility對(duì)象使用戶在AutoCad命令行與CAD交互成為可能,通過(guò)它可以處理整型、浮點(diǎn)型、字符型等用戶輸入,還可以接受點(diǎn)(Point)或角(Angle)等AutoCad的特殊量。

二、 AutoCad對(duì)象的使用

   在本節(jié)中,將結(jié)合我做項(xiàng)目得到的一些經(jīng)驗(yàn)以例程的方式對(duì)AutoCad的常用對(duì)象及其使用進(jìn)行討論。

   1.開(kāi)始一個(gè)應(yīng)用程序

   如前所述,Application對(duì)象位于AutoCad層次對(duì)象結(jié)構(gòu)的頂層,它代表AutoCad本身,用戶的應(yīng)用程序也理所當(dāng)然從Appliction對(duì)象的建立開(kāi)始。


Dim acadapp As Object   建立Application對(duì)象
Dim acaddoc As Object   建立Document對(duì)象
Dim mospace As Object   建立Model Space 對(duì)象
On Error Resume Next
Set acadapp = GetObject(, "autocad.application")  ‘若AutoCad       
                  已啟動(dòng),則直接得到  
If Err Then
  Err.Clear
  Set acadapp = CreateObject("autocad.application")  ‘若
            AutoCad未啟動(dòng),則運(yùn)行它
  If Err Then
   MsgBox Err.Description
   Exit Sub
  End If
End If
acadapp.Visible = True ‘使AutoCad可見(jiàn)
Set acaddoc = acadapp.ActiveDocument  ‘設(shè)acaddoc為當(dāng)前
               圖形文件
Set mospace = acaddoc.ModelSpace ‘設(shè)mospace為當(dāng)前圖形
                  文件的模型空間


 
以上程序段是應(yīng)用程序初始化的過(guò)程,一般對(duì)AutoCad圖形文件的操作,主要是與Application、Document和Model Space等對(duì)象發(fā)生關(guān)系。

  Application對(duì)象是一系列對(duì)象的父對(duì)象,可以通過(guò)它的屬性設(shè)置來(lái)改變AutoCad的窗口設(shè)置。請(qǐng)看下面代碼:


acadapp.Top=100   設(shè)置AutoCad窗口的位置
  acadapp.Left=200
  acadapp.Height=1000  調(diào)整AutoCad窗口的大小
  acadapp.Width=800
  acadapp.Caption="my first application"  設(shè)置AutoCad窗口的 
                    標(biāo)題



   通過(guò)Application對(duì)象的方法還可以方便的調(diào)入ADS或ARX程序,以利于各類(lèi)程序的集成。其例程為:

    Dim arxname As string
    acadapp.LoadARX arxname ‘a(chǎn)rxname即為調(diào)入的arx程序名(帶  路徑)

   2.通過(guò)Document對(duì)象對(duì)圖形文件的操作

   Document對(duì)象提供了大多數(shù)AutoCad的文件功能,可以通過(guò)它實(shí)現(xiàn)對(duì)文件的更新(New)、打開(kāi)(Open)、輸出(Export)、輸入(Import)等操作,一般要先把Document對(duì)象設(shè)為Application對(duì)象的 ActiveDocument屬性,以返回當(dāng)前圖形文件。

    Set acaddoc=Application.ActiveDocument

   請(qǐng)看下面的例子對(duì)文件的操作:


Dim dwgname As String
dwgname = "c:\acadr14\sample\campus.dwg"
If Dir(dwgname) <> "" Then
   acaddoc.Open dwgname   打開(kāi)一個(gè)CAD文件
Else
   acaddoc.new("acad")  以acad.dwt為模板建立一個(gè)新
              文件
End If
Document對(duì)象還提供了兩個(gè)十分有用的方法——SetVariable 和 GetVariable,通過(guò)它們可以得到或改變AutoCad的系統(tǒng)變量。
如:acaddoc.SetVariable "Orthomode", 1 打開(kāi)正交模式
dim cadver As String
cadver=acaddoc.Getvariable("Acadver")  獲取AutoCad的版本號(hào)

4.與用戶交互

   Utility對(duì)象提供了與用戶在命令行交互的途徑,可以讓用戶輸入數(shù)字、字符串及角度、點(diǎn)坐標(biāo)等參量。下面說(shuō)明如何應(yīng)用Utility交互替代AutoCad命令中的提示:

Dim acadUtil as Object
Dim stPnt, enPnt As Variant    
Dim prompt1, prompt2 As String  
Set acadUtil=acaddoc.Utility   設(shè)置Utility對(duì)象
prompt1 = "起始點(diǎn): " ‘代替from Point
prompt2 = "終止點(diǎn): "  代替End Point
stPnt = acadUtil.GetPoint(, prompt1)
enPnt = acadUtil.GetPoint(stPnt, prompt2) 
獲得用戶輸入(既可輸入坐標(biāo)值,也可直接在屏幕上選點(diǎn))
Dim startPoint(0 To 2) As Double 
Dim endPoint(0 To 2) As Double  
startPoint(0) = stPnt(0)      
startPoint(1) = stPnt(1)      
startPoint(2) = stPnt(2)    
endPoint(0) = enPnt(0)    
endPoint(1) = enPnt(1)    
endPoint(2) = enPnt(2)   
moSpace.AddLine startPoint, endPoint 利用用戶輸入生成直線
把系統(tǒng)變量設(shè)置SetVariable與Utility對(duì)象的GetString方法結(jié)合,即可向AutoCad的狀態(tài)行寫(xiě)入內(nèi)容:
  Dim yourname as String
      yourname = acadUtil.GetString(0, " 請(qǐng)輸入您的姓名: ")
  acaddoc.SetVariable "MODEMACRO", yourname & ", 你好!"



   5.對(duì)非圖形對(duì)象的操作

   非圖形對(duì)象如層(Layers)、視圖(Viewports)、坐標(biāo)系(UCSs)、塊 (Blocks)等與圖形實(shí)體集合ModelSpace、PaperSpace同是Document對(duì)象的子對(duì)象,它們本身既是對(duì)象,又是對(duì)象的集合,如Layers是當(dāng)前打開(kāi)的圖中所有層的集合,使用Add方法來(lái)建立新層,并可以遍歷所有層,通過(guò)改變其屬性達(dá)到關(guān)閉(Off)、凍結(jié)層(Freeze)的目的.

   ①把層名為"wall"的層凍結(jié),打開(kāi)層名為"beam"的層,并設(shè)為當(dāng)前層

Dim tlayer as Object
  For Each tlayer In acaddoc.Layers
    If tlayer.Name = "wall" Then
     tlayer.Freeze = acTrue 
    Else If tlayer.Name="beam" Then
     tlayer.LayerOn = acTrue 
     Set acaddoc.ActiveLayer = tlayer 
    End If
  Next


  ②創(chuàng)建名為"myview"的新視圖

   可以通過(guò)ActiveX自動(dòng)實(shí)現(xiàn)變換視圖角度及縮放全圖。

Public Sub changeview(ByVal x, ByVal y, ByVal z)
Dim newDirection(0 To 2) As Double
Dim vport As Object
acaddoc.ActiveSpace = acModelSpace ‘使ModelSpace成為活動(dòng)
                   空間
Set vport = acaddoc.Viewports.Add("newview") ‘建立新視圖
newDirection(0) = x
newDirection(1) = y
newDirection(2) = z ‘視圖的視角方向
vport.Direction = newDirection
acaddoc.ActiveViewport = vport ‘把新視圖激活
acaddoc.ActiveViewport.ZoomAll ‘全圖顯示
End Sub


   以上例程是對(duì)Layers、Viewports對(duì)象的舉例,其他非圖形對(duì)象的引用與此類(lèi)似。

   6.對(duì)選擇集的操作

   在對(duì)AutoCad的編程中,選擇集占有十分重要的地位,對(duì)編程者而言,并不清楚圖中包含什么實(shí)體,只有通過(guò)用戶的選擇或通過(guò)過(guò)濾條件把所需的實(shí)體加入選擇集,再對(duì)選擇集中的實(shí)體進(jìn)行操作。下面例程給出了兩種篩選建立選擇集的方法,把圖中所有在層"wall"上的直線亮顯。

   ①由用戶在屏幕上選擇實(shí)體

  Dim tempset as Object
  Dim obj as Object
  Set tempset = acaddoc.SelectionSets.Add("newset") 建立新選擇集
tempset.SelectOnScreen   ‘用戶在屏幕上選擇
  For Each obj In tempset  ‘遍歷選擇集中的實(shí)體
   If obj.EntityName="AcDbLine" And obj.Layer="wall" Then
     obj.HighLight(True) 亮顯實(shí)體
   End IF
  Next


   這種選擇方式給用戶較大的自由,但不能保證選擇集內(nèi)包含所有我們期望的實(shí)體,若要精確過(guò)濾出所需實(shí)體,應(yīng)該給選擇集加入條件。

   ②使用過(guò)濾器(Filter)篩選實(shí)體

Dim actualCode(3) As String
Dim actualValue(3) As String
Dim groupcode As Variant
Dim groupValue As Variant
Dim extminpt(2) As Double
Dim extmaxpt(2) As Double
Dim tsset As Object
Dim tobj As Object
actualCode(0) = -4
actualValue(0) = " actualCode(1) = 8   
   保證 Layer是"wall"
actualValue(1) = "wall"
actualCode(2) = 100
actualValue(2) = "AcDbLine" 所選實(shí)體為直線
actualCode(3) = -4
actualValue(3) = "AND>"

.SendKeys的妙用

   AutoCad的ActiveX雖然強(qiáng)大,但不是所有問(wèn)題都可以通過(guò)它解決。要在VB中使用AutoCad對(duì)象沒(méi)有的方法,就須用到VB中的過(guò)程SendKeys。通過(guò)SendKeys把AutoCad的命令行如同批處理一樣送到AutoCad中自動(dòng)執(zhí)行,在效果上與使用對(duì)象的方法是相同的。另外,還可以使用簡(jiǎn)單的AutoLisp語(yǔ)言增強(qiáng)AutoCad命令行的功能。下例是執(zhí)行break命令而編寫(xiě)的過(guò)程。其中的(handent"***")是從Lisp語(yǔ)言中借來(lái)的,可以直接在命令行通過(guò)實(shí)體句柄(Handle)來(lái)確定實(shí)體。

SendKeys "{esc}", True
  SendKeys "{esc}", True ‘避免以前命令的干擾
  SendKeys "_break" & "{enter}", True 
  SendKeys "{(}" & "handent" & """" & wallhandle & """" & "{)}" & "{enter}", True ‘選擇要斷開(kāi)的實(shí)體(wallhandle為其句柄)
  SendKeys Format(cood1(0)) & "," & Format(cood1(1)) & "{enter}", True
  SendKeys Format(cood2(0)) & "," & Format(cood2(1)) & "{enter}", True ‘cood1與cood2是實(shí)體上斷開(kāi)點(diǎn)的坐標(biāo)




三、 最終的補(bǔ)充說(shuō)明

   1. 盡量采用迭代的方法遍歷集合

   如前所述,對(duì)CAD的編程中涉及大量的集合操作,下面的代碼段與迭代法效果相同,但效率較低。

Dim I As Integer
   For I=0 To sset.Count-1  
    sset(I).HighLight(True)
   Next I



   在創(chuàng)建自己的集合時(shí),關(guān)鍵字盡量采用Handle值,以便查找,并可通過(guò)HandletoObject方法將Handle值轉(zhuǎn)化為實(shí)體(Object)

   2. 采用AutoCad r14.01版

   Autodesk公司在r14版中加入了ActiveX Automation,但尚不完善。在隨后推出的14.01版中,Autodesk公司解決了r14版的不少錯(cuò)誤,使得應(yīng)用程序運(yùn)行更為流暢、穩(wěn)定。如果要進(jìn)行AutoCad的ActiveX編程,建議采用VB5.0和AutoCad r14.01。

   3. 關(guān)于ActiveX的資源

   國(guó)內(nèi)有不少介紹ActiveX編程及AutoCad的資料,但迄今還未發(fā)現(xiàn)有完整討論AutoCad的ActiveX編程的書(shū)籍,目前最容易得到的資料就是Autodesk公司編寫(xiě)的隨機(jī)幫助,其中有一章“ActiveX Automation",有全部對(duì)象的方法、屬性說(shuō)明。
民眾工作室.制作      版權(quán)所有