【正文】
象都將Iunknown作為缺省接口,但也有少數(shù)例外。VBA中要求這些非Iunknown缺省接口,可以在ArcCatalog和ArcMap應(yīng)用程序級別對象上找到。運行時綁定ID。編譯時執(zhí)行綁定綁定就是處理器定位給定對象指針的函數(shù)的過程。 假設(shè)支持詢問的方法,客戶就調(diào)用IDispatch::Invoke方法,該方法再調(diào)用被詢問的方法,并向客戶返回狀態(tài)和任何參數(shù)值以完成調(diào)用。ESRI對象庫中的對象類沒有實現(xiàn)Idispatch接口,也就是說這些對象庫不能在latebinding腳本語言中使用,如JavaScript或VBScript,因為這些語言要求被訪問的COM服務(wù)都支持Idispatch接口。 所有的ActiveX控件都支持Idispatch接口,也就是說,可以在腳本語言環(huán)境中用AO提供的各種不同的ActiveX控件訪問服務(wù)。實現(xiàn)該接口的可實例化類必須實現(xiàn)所有繼承的類接口。例如,一個客戶程序支持一指定輸出格式的數(shù)據(jù)輸出功能,利用組件目錄可以查找不同輸出格式的所有數(shù)據(jù)輸出類。組件目錄支持COM的可延展性,它允許客戶程序員創(chuàng)建并使用某一特殊目錄的類。十八、COM and the Registry COM使用Windows系統(tǒng)注冊表保存組成COM系統(tǒng)的各部分信息,類、接口、DLLs、EXEs、類型庫等,都有一個唯一的標(biāo)識(GUID).十九、自動化(Automation) 自動化是個別對象或整個程序用來通過一種latebound語言提供訪問其封裝功能。由于AO不支持Idispathc接口,所以不能單獨使用于自動化控制器。但由于自動化控制器實例和ArcMap實例在不同的進程中運行,所以這種方法存在問題。第二節(jié) AO開發(fā)一、代碼標(biāo)準(zhǔn)(Coding Standards) 編寫代碼時遵循一定的標(biāo)準(zhǔn)風(fēng)格有利于代碼維護,特別是在團隊作業(yè)中。例如,用VB開發(fā)時,建議定義類型時,以ESRI對象庫為前綴,如:。附錄“讀對象模型圖”詳細(xì)介紹了類圖,并展示了尋找對象的許多技巧。五、組件幫助(Component Help) 在組件幫助文檔中可以找到所有接口和可實例化類的幫助。 ,這個文檔已編譯成HTML文檔。六、代碼向?qū)В–ode Wizards) 在VB、VC++。這各所有的開發(fā)環(huán)境的索引不同,VB同時有基于0和1的索引。八、訪問集合要素(Accessing Collection Elements) 當(dāng)順序訪問集合中的要素時,最好是用一個枚舉接口(enumerator interface)。對象可能創(chuàng)建一個新的枚舉器,或高效返回一個存在的枚舉器。為確保指針在集合的頭部,客戶在使用前應(yīng)復(fù)位枚舉器。COM不支持接口異常外傳的方法調(diào)用,但支持COM異常。它們用來通知程序框架實現(xiàn)該接口的類支持一些特殊的功能。十二、客戶端存儲(Clientside Storage) 相比方法調(diào)用有些AO方法更期望指針指向合法的對象。假定要獲得一個多邊開(polygon)的外接框,要用到IPolygon的QueryEnvelope方法。該方法會修改傳遞過去的envelope,并返回修改后的值。如果方法名字是GetEnvelope,那么就不需創(chuàng)建(該對象已經(jīng)創(chuàng)建好)。C++程序員可以看作讓客戶傳遞某一資源的屬主給服務(wù)端(使用putref_XXX方法)。 現(xiàn)假設(shè)一窗體上有兩個文本框控件,Text1和Text2。第二三兩種情況也行,是由于沒有指定其屬性項,VB就用0 DISPID查找屬性項。如果將引用的真實對象變量Text2賦給變量Text1會發(fā)生什么情況呢?如果只有一個propput方法肯定不行,因此要借助propputref方法。如果不這樣做,將導(dǎo)致死循環(huán)。 Check to see that the map is different than what is currently connected If (Not ViewEvents Is ) Then 39。十五、Database Considerations 如果不用database編寫程序,必須遵循以下規(guī)則以確保代碼完美性。 如果用程序編輯數(shù)據(jù)(即不用ArcMap中的編輯工具),必須遵循下面的規(guī)則,確保自定義對象的行為(如網(wǎng)絡(luò)拓樸的維護或自定義要素的方法)能正確引用,以響應(yīng)程序?qū)?shù)據(jù)庫的修改;確保所作修改在多用戶編輯(長事務(wù))下進行。十七、編輯操作(Edit Operations) 將修改組織成編輯操作,等同于調(diào)用IworkspaceEdit接口的StarteditOperation和StopEditOperation方法之間的過程。如果使用ArcSDE上存儲的數(shù)據(jù),必須創(chuàng)建至少一個編輯操作。在編輯會話中,只有返回的對象在內(nèi)存中不存在時,不可循環(huán)光標(biāo)才創(chuàng)建新對象。二十、標(biāo)記修改后的對象(Marking changed objects) 修改了一個對象之后,應(yīng)調(diào)用Store方法對其標(biāo)記。 update cursors 和insert cursors是在載入時初始化數(shù)據(jù)庫的bulk cursor APIs。二十二、Shape和ShapeCopy的幾何屬性(Shap and ShapeCopy geometry property) 使用Feature對象的Shape和ShapeCopy屬性來獲得要素的幾何信息。 AO中需要的類型庫在ArcGISP安裝文件夾下,如COM類型庫在COM文件夾中,許多文件中都包含類型庫信息,如EXEs、DLLs、OCXs和OLBs(object libraries)。不同之處已作標(biāo)記一、用戶界面標(biāo)準(zhǔn) 預(yù)載窗體時不要載入太多,以3到4個為宜;使位圖文件、圖標(biāo)和相關(guān)文件時利用資源文件(.res)而不是外部文件; 當(dāng)變量引用只在類加載才設(shè)置時,使用創(chuàng)建器和銷毀器設(shè)置。 上表為VB工程中各種要素命名標(biāo)準(zhǔn)的建議。另外用上表建議的暗示模塊類型三個字母作為前綴為窗體(forms)、類(classes)、標(biāo)準(zhǔn)模塊(standard modules)。使用左表提供的三個字母為前綴暗示控件類型。 使用Public和Private聲明模塊級別變量,用Dim聲明局部變量。任何時候都不要使用Global。 盡量每行只聲明一個變量,除非為每個變量指定了類型 下面一行使得count變量被聲明為Variant類型,和期望的不一樣:Dim count,max As Long 下面一行聲明count和max變量為期望的Long類型:Dim count As Long, max As Long 下面兩行同樣聲明count和max為Long類型,而且更具易讀性:Dim count As LongDim max As Long三、括號(Parentheses) 用括號,使操作符優(yōu)先,使比較語句更易讀 Result=((x*24)/(y/12))+42 If ((Not pFoo Is Nothing) And (Counter 200)) Then四、條件語句順序(Order of conditional determination) VB和C、C++等語言不一樣,它會判斷條件的所有部分,即使第一部分為False。 ‘當(dāng)pFoo值為Null時,下面一句會導(dǎo)致錯誤 If ((Not pFoo Is Nothing) And (TypeOf Is Ibar)) Then End If ‘正確的測試代碼如下 If (Not pFoo Is Nothing) Then If (TypeOf Is IBar) Then ‘Perform action on Ibar thing of Foo End If End If五、縮進(Indentation) 用兩個空格或兩個空格的制表符寬度縮進六、默認(rèn)屬性(Default properties) 除非最通用情況下,最好不要使用默認(rèn)屬性,這樣會降低靈活性七、模塊調(diào)用中的引用(Intermodule referencing) 訪問調(diào)用模塊中的數(shù)據(jù)或函數(shù)時,最好用模塊名限定其引用,這樣代碼更具有易讀性,運行時綁定效率也更高。 With frmHello .Caption = “Hello world” .Font = “Playbill” .Left = ( .Width) / 2 .Top = ( .Height) / 2 End With九、矩陣(Arrays)使用矩陣時,不要改變其基數(shù)0(系統(tǒng)默認(rèn)值)為其它值。MyArray = GetSomeArrayFor I = LBound(myArray) To UBound(myArray) MsgBox cstr(myArray(i))Next I十、位邏輯操作符(Bitwise operations) And,Or和Not都是邏輯操作符,確保其判斷條件都是Boolean值(當(dāng)然,正確的邏輯語句除外)十一、類型后綴(Type suffixes) 除非為了從32位數(shù)中區(qū)分16位數(shù),盡量不要在變量或函數(shù)名中使用類型后綴(如myString$或者Right$(myString))。十三、模糊類型匹配(Ambiguous type matching) 對于模糊類型匹配,用顯式轉(zhuǎn)換操作符(如CSng,CDbl,CStr)進行轉(zhuǎn)換,不要依靠VB系統(tǒng)決定使用什么類型。十五、錯誤處理(Error handling) 使用OnError處理錯誤,對每個函數(shù)中的錯誤檢查,用OnError跳轉(zhuǎn)到單個錯誤處理處,處理運行過程中可能遇到的所有異常。 VB中的錯誤處理不同COM中一般的錯誤處理(參考“Working with HRESULTs’”部分)。事件函數(shù)是在其它地方簡單派發(fā)以達到重用功能。在要保留太多不可視的窗體,因為窗體會消耗系統(tǒng)資源;注意引用一個窗體級別變量時會裝載窗體;設(shè)置不用的對象值為Nothing,以釋放占用的內(nèi)存;使用Class_Initialize() 和 Class_Terminate()分配、回收資源。用Do While…Loop和Do Until…Loop代替,因為這樣可以有條件地跨出結(jié)構(gòu)。 VB虛擬機以DLL形式封裝,在要執(zhí)行VB代碼的機器上必須安裝,即使已將代碼編譯成本地代碼。二十、與IUnknown接口交互 關(guān)于VB中的接口機制二十一、訪問AO(Accessing ArcObjects) 下面是關(guān)于AO中創(chuàng)建實例和查詢接口操作的一些特殊用法。如果使用ArcMap或ArcCatalog中內(nèi)置的VBA,則系統(tǒng)已經(jīng)引用了大多數(shù)通用的ESRI對象庫。 現(xiàn)在以Point對象和IPoint接口為例,設(shè)置點坐標(biāo)的一種方法是調(diào)用IPoint接口的PutCoords方法,并傳入坐標(biāo)值。這段代碼很清晰,如果在同一工程中引用其它的對象庫時用庫名加接口名就更清晰了,如: Dim pPt As 用這種方式,即使在工程中又引用了另外一個IPoint接口,也不會混淆引用的是哪一個。對于像Point這樣通用的可實例化類,也可以用文件庫名加類名的方式,如 Set pPt = New 最后一行調(diào)用了PutCoord方法。 (Coclass是ponent object class的縮寫)二十二、使用HRESULTs(Working with HRESULTs) 所有的COM方法都通過其返回的HRESULT值暗示調(diào)用是否成功,接口以外不會發(fā)生任何異常。在VB中調(diào)用的方法不會返回HRESULTs值,那么VB是如何產(chǎn)生異常的呢?答案就在于VB虛擬機。如果能從COM錯誤對象中獲得任何有價值的錯誤信息,虛擬機就將該信息存儲在VB的Err對象中。 在VB中實現(xiàn)接口時,好的習(xí)慣是當(dāng)遇到錯誤時就產(chǎn)生一個HRESULT錯誤通知調(diào)用者遇到了一個錯誤。 ‘Defined in Module Const E_NOTIMPL = amp。這種情況下應(yīng)該調(diào)用一個錯誤處理函數(shù)處理該錯誤。下面是一段簡單的錯誤處理代碼,能捕捉到函數(shù)中的任何錯誤,并通知用戶。 Private Sub Test() On Error GoTo ErrorHandler ‘Do something here Exit Sub ‘Must exti sub here before error handler ErrorHandler: MsgBox “Error In Application – Description” amp。對于接口引用,要聲明一個接口變量,并用Set語句將接口引用賦給屬性。 對屬性是接口的,可以用引用賦值,也可以用值賦值。 Dim pEnv As IEnvelope Set pEnv = ‘Get extent property of view , , True ‘Shrink envelope = pEnv ‘Set By Value extent back on IactiveView Dim pFeatureLayer as IFeatureLayer Set pFeatureLayer = New FeatureLayer 39。Set ByRef a class into layer 有些屬性是只讀(readonly)的,有些是只寫(writeonly)的,有些則是可讀寫(readwrite)的。如果試圖使用一個屬性,但忘記使用Set關(guān)鍵字,那VB編譯將失敗,或者顯示數(shù)據(jù)成員未找到的消息。二十四、使用方法(Working with methods) 方法執(zhí)行了一些動作,可能返回值也可能不返回。例如,下面的代碼中,EditSelection返回了一個枚舉特征的接口。Holds the selection Dim pID As New UID 39。Get the sel