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

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

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

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

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

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

二、 AutoCad對象的使用

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

   1.開始一個應(yīng)用程序

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


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


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

  Application對象是一系列對象的父對象,可以通過它的屬性設(shè)置來改變AutoCad的窗口設(shè)置。請看下面代碼:


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)題



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

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

   2.通過Document對象對圖形文件的操作

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

    Set acaddoc=Application.ActiveDocument

   請看下面的例子對文件的操作:


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

4.與用戶交互

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

Dim acadUtil as Object
Dim stPnt, enPnt As Variant    
Dim prompt1, prompt2 As String  
Set acadUtil=acaddoc.Utility   設(shè)置Utility對象
prompt1 = "起始點: " ‘代替from Point
prompt2 = "終止點: "  代替End Point
stPnt = acadUtil.GetPoint(, prompt1)
enPnt = acadUtil.GetPoint(stPnt, prompt2) 
獲得用戶輸入(既可輸入坐標(biāo)值,也可直接在屏幕上選點)
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對象的GetString方法結(jié)合,即可向AutoCad的狀態(tài)行寫入內(nèi)容:
  Dim yourname as String
      yourname = acadUtil.GetString(0, " 請輸入您的姓名: ")
  acaddoc.SetVariable "MODEMACRO", yourname & ", 你好!"



   5.對非圖形對象的操作

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

   ①把層名為"wall"的層凍結(jié),打開層名為"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"的新視圖

   可以通過ActiveX自動實現(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成為活動
                   空間
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


   以上例程是對Layers、Viewports對象的舉例,其他非圖形對象的引用與此類似。

   6.對選擇集的操作

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

   ①由用戶在屏幕上選擇實體

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


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

   ②使用過濾器(Filter)篩選實體

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" 所選實體為直線
actualCode(3) = -4
actualValue(3) = "AND>"

.SendKeys的妙用

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

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




三、 最終的補充說明

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

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

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



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

   2. 采用AutoCad r14.01版

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

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

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