AutoCAD .net 二次开发官方教程及源码C#版(4)-(源码下载)
第4章?數據庫基礎2:添加自定義數據
在這一章中,我們將創建一個新的字典對象,它用來表示我們雇員就職的 ‘Acme 公司‘(呵呵,當然是虛構的一家公司)的部門。這個“部門”字典對象將包含一個表示部門經理的記錄。我們還會加入代碼到雇員創建過程,這個過程會加入一個索引到雇員工作的部門。 ?????? 我們要說明的是如何在DWG文件中創建自定義數據,包括“每個圖形”的自定義數據和“每個實體”的自定義數據。“每個圖形”的自定義數據是指只在整個圖形中加入一次的數據,它表示對象可以引用的單一類型或特性。“每個實體”的自定義數據是指是為特定的對象或數據庫中的實體加入的數據。
在下面的示例中,我們將加入“每個圖形”的自定義數據到命名對象字典(簡稱NOD)。NOD存在于每一個DWG文件中。“每個實體”的自定義數據加入到一個名為“擴展字典”的字典(可選)中,它表示每一個雇員。每一個由DBObject派生的對象都擁有存儲自定義數據的擴展字典。而在我們的示例中將包含這種自定義數據如名字、薪水和部門。
?? ? ACME_DIVISION-自定義公司字典
????? ??? ?????銷售(Sales)?-部門字典
???????? ???? ?????????部門經理-部門條目
1)?????????????????? 我們首先要做的是定義一個新的函數,它用來在命名對象字典(NOD)中創建公司字典對象。為這個函數取名為CreateDivision(),,并使用命令屬性來定義CREATEDIVISION命令。
?public void CreateDivision()?
?{?
?????? Database db = HostApplicationServices.WorkingDatabase;?
?????? Transaction trans = db.TransactionManager.StartTransaction();?
?????? try?
?????? {?
????????????? //首先,獲取NOD……?
????????????? DBDictionary NOD = (DBDictionary)trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite);?
????????????? //定義一個公司級別的字典?
????????????? DBDictionary acmeDict;?
????????????? try?
????????????? {?
???????????????????? //如果ACME_DIVISION不存在,則轉到catch塊,這里什么也不做?
???????????????????? acmeDict = (DBDictionary)trans.GetObject(NOD.GetAt("ACME_DIVISION"), OpenMode.ForRead);?
????????????? }?
????????????? catch?
????????????? {?
???????????????????? //如果ACME_DIVISION不存在,則創建它并把它加入到NOD中……?
???????????????????? acmeDict = new DBDictionary();?
???????????????????? NOD.SetAt("ACME_DIVISION", acmeDict);?
???????????????????? trans.AddNewlyCreatedDBObject(acmeDict, true);?
????????????? }?
????????????? trans.Commit();?
?????? }?
?????? finally?
?????? {?
????????????? trans.Dispose();?
?????? }
}
請仔細閱讀一下上面的代碼塊的結構,可以通過注釋來了解相關的細節。特別要注意的是我們是如何用一個try-catch塊來處理ACME_DIVISION是否存在?如果ACME_DIVISION字典不存在,GetObject()將會拋出異常,catch塊被執行,它會創建一個新的字典。
運行這個函數來看它是否可行。可以使用數據庫查看工具來檢查字典是否已被加入(建議使用ARX SDK的ArxDbg工具)
2)?????????????????? 接下來,我們要在ACME_DIVISION字典中加入銷售(Sales)條目。銷售(Sales)條目同樣也是一個字典。由于銷售(Sales)字典與ACME_DIVISION字典的關系如同ACME_DIVISION字典與NOD,所以代碼是類似的。定義下面的代碼部分在ACME_DIVISION字典中創建一個名為’Sales’的字典。
代碼提示:
??????????? ?????? DBDictionary divDict;?
?????????????????? try?
?????? {?
????????????? divDict = (DBDictionary)trans.GetObject(acmeDict.GetAt("Sales"), OpenMode.ForWrite);?
?????? }?
?????? catch
?????? ?? …
3)?????????????????? 現在我們要在這個字典中加入一個特殊的記錄,它可以包含任意的自定義數據。我們要加入的數據類型為擴展記錄(XRecord),它可以包含任何東西,因此我們可以讓它包含ResultBuffer類的對象(就是有些人可能非常熟悉的‘resbuf’)。ResultBuffer可以存儲不同類型的預定義數據。擴展記錄存儲任意數目的ResultBuffer關系列表,因此可能會很大。下表是可以包含在ResultBuffer中一些數據類型(位于Database類的DxfCode枚舉中):
| Start | 0 | |
| Text | 1 | |
| XRefPath | 1 | |
| ShapeName | 2 | |
| BlockName | 2 | |
| AttributeTag | 2 | |
| SymbolTableName | 2 | |
| MstyleName | 2 | |
| SymTableRecName | 2 | |
| AttributePrompt | 3 | |
| DimStyleName | 3 | |
| LinetypeProse | 3 | |
| TextFontFile | 3 |
在下面的代碼部分,我們將創建只包含一個ResultBuffer的擴展記錄。這個ResultBuffer包含一個單一的的字符串值,它表示’Sales’部門的部門經理的名字。我們使用和加入字典一樣的方法加入擴展記錄。唯一的區別是擴展記錄與字典的不同:
???????????? mgrXRec = new Xrecord();?
? mgrXRec.Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, "Randolph P. Brokwell"));
????????????? try
????????????? {
???????????????????? mgrXRec = (Xrecord)trans.GetObject(divDict.GetAt("Department Manager"), OpenMode.ForWrite);
????????????? }
????????????? catch
????????????? {
???????????????????? mgrXRec = new Xrecord();
???????????????????? mgrXRec.Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, "Randolph P. Brokwell"));
???????????????????? divDict.SetAt("Department Manager", mgrXRec);
???????????????????? trans.AddNewlyCreatedDBObject(mgrXRec, true);
????????????? } 運行函數并使用數據庫查看工具來確定部門經理已被加入到’Sales’字典。 4)??? 我們已經定義了公司字典,現在我們要把每個雇員的數據加入到前一章定義的塊索引中。我們要加入的數據是:名字、薪水和雇員所屬的部門。要加入這些數據,我們要同前幾個步驟一樣使用擴展記錄。因為我們要加入三個條目,所以我們要使擴展記錄可以把這些數據聯系在一起。
一般來說,擴展記錄只能存在于字典中。而我們要為每個雇員加入這些數據(就是本章開頭所講的“每個圖形”的自定義數據和“每個實體”的自定義數據),那應該怎么做呢?答案就是:每一個對象或AutoCAD中的實體實際上都有一個名為’擴展字典(Extension Dictionary)’的可選字典。我們可以把擴展記錄直接加入到這個字典中。
?????? Real – 72000??????????????? 或者更多的薪水J?
?????? Text – “Sales”?????????????? 雇員所在的部門???????
?????? DBDictionary brExtDict? = (DBDictionary)trans.GetObject(br.ExtensionDictionary, OpenMode.ForWrite, false); 由于擴展字典也是字典,我們可以和第3步一樣在擴展字典中加入擴展記錄。請完成有關的代碼來創建和訪問塊索引的擴展字典,加入你在第4步中創建的擴展記錄,然后把擴展記錄加入到事務處理。
6)??? 返回到NOD……因為在NOD中創建公司字典只需要一次(就像創建Employee塊一樣),因此我們應該把CreateDivision函數的命令屬性去掉,而在CreateEmployeeDefinition()中調用這個函數。請自己完成這些改變。當所有這些都做完后,當CREATE命令第一次運行的時候,所有的函數都會被調用。
7)??? 下面的步驟和上面的無關。我們將創建一個函數來遍歷模型空間,以用來查找加入的Employee對象(這里其實是塊索引)的數目。在VB.NET 或C#中,我們可以把模型空間塊表記錄(ModelSpace BlockTableRecord)當作一個集合,這樣就可以使用For Each(C#是foreach)來遍歷它。請仔細研究一下下面的代碼片斷:VB.NET:
??????????? Dim id As ObjectId ‘? 首先,定義一個For循環要使用的ObjectId變量。?
??????????? For Each id In btr?
??????????????? Dim ent As Entity = trans.GetObject(id, OpenMode.ForRead, False) '打開當前的對象!
?????? foreach (ObjectId id in btr)?
????? {?
??????????? Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false);? //打開當前的對象!
????????????? Dim br As BlockReference = CType(ent, BlockReference)?
????????????? …
C#:
?????? If(ent.GetType() == typeof(BlockReference))?
????????????? BlockReference br = (BlockReference)ent;
請定義一個名為EmployeeCount()的函數,函數的結構如上所示,它用來統計模型空間中的塊索引的數目。這個函數不會輸出任何東西,但你可以使用逐步調試程序來查看整數變量的增加(每發現一個塊索引對象)。
Imports Autodesk.AutoCAD.ApplicationServices 在函數的內部:
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
第四章結束
下面的代碼片斷演示了怎樣獲取Employee對象的所有內容,包括ACME_DIVISION字典中的部門經理的名字。這部分要在后面的章節中使用,但因為它和本章有關,因此我們把它放在本章作介紹。如果有時間的話,請閱讀一下其中的代碼來看看它是怎么使用的。它可以被直接放到你的類中并可以運行。命令的名字是PRINTOUTEMPLOYEE。ListEmployee()函數接收一個ObjectId參數,它通過一個ref類型的字符串數組返回值(包含相應的雇員數據)。調用它的PrintoutEmployee()函數只是用來在命令行中輸出這些數據。
我們需要一個遍歷并顯示所有雇員數據的命令。
public?static?void ListEmployee(ObjectId employeeId, ref?string[] saEmployeeList)
{
?????? int nEmployeeDataCount = 0;?
?????? Database db = HostApplicationServices.WorkingDatabase;?
?????? Transaction trans = db.TransactionManager.StartTransaction(); //開始事務處理。?
?????? try?
?????? {?
????????????? Entity ent = (Entity)trans.GetObject(employeeId, OpenMode.ForRead, false); //打開當前對象!?
????????????? if (ent.GetType() == typeof(BlockReference))?
????????????? {
//不是所有的塊索引都有雇員數據,所以我們要處理錯誤?
???????????????????? bool bHasOurDict = true;?
???????????????????? Xrecord EmployeeXRec = null;?
???????????????????? try?
???????????????????? {?
??????????????????????????? BlockReference br = (BlockReference)ent;?
??????????????????????????? DBDictionary extDict = (DBDictionary)trans.GetObject(br.ExtensionDictionary, OpenMode.ForRead, false);?
??????????????????????????? EmployeeXRec = (Xrecord)trans.GetObject(extDict.GetAt("EmployeeData"), OpenMode.ForRead, false);?
???????????????????? }?
???????????????????? catch?
???????????????????? {
???????????????????? bHasOurDict = false; //出現了錯誤……字典或擴展記錄不能訪問?
???????????????????? }
??????????????????? if (bHasOurDict) //如果獲得擴展字典,而又有擴展記錄……?
???????????????????? {?
??????????????????????????? // 為雇員列表分配內存?
??????????????????????????? saEmployeeList = new String[4];?
??????????????????????????? //加入雇員的名字?
??????????????????????????? TypedValue resBuf = EmployeeXRec.Data.AsArray()[0];?
??????????????????????????? saEmployeeList.SetValue(string.Format("{0}\n", resBuf.Value), nEmployeeDataCount);?
??????????????????????????? nEmployeeDataCount += 1;?
??????????????????????????? //加入雇員的薪水?
??????????????????????????? resBuf = EmployeeXRec.Data.AsArray()[1];?
??????????????????????????? saEmployeeList.SetValue(string.Format("{0}\n", resBuf.Value), nEmployeeDataCount);?
??????????????????????????? nEmployeeDataCount += 1;?
??????????????????????????? //加入雇員所在的部門?
??????????????????????????? resBuf = EmployeeXRec.Data.AsArray()[2];?
??????????????????????????? string str = (string)resBuf.Value;?
??????????????????????????? saEmployeeList.SetValue(string.Format("{0}\n", resBuf.Value), nEmployeeDataCount);?
??????????????????????????? nEmployeeDataCount += 1;?
??????????????????????????? //現在,讓我們從公司字典中獲取老板的名字?
??????????????????????????? //在NOD中找到.?
??????????????????????????? DBDictionary NOD = (DBDictionary)trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead, false);?
????????????????????????????????????????? DBDictionary acmeDict = (DBDictionary)trans.GetObject(NOD.GetAt("ACME_DIVISION"), OpenMode.ForRead);?
??????????????????????????? //注意我們直接使用擴展數據...?
????????????????????????????????????????? DBDictionary salesDict = (DBDictionary)trans.GetObject(acmeDict.GetAt((string)EmployeeXRec.Data.AsArray()[2].Value), OpenMode.ForRead);?
??????????????????????????? Xrecord salesXRec = (Xrecord)trans.GetObject(salesDict.GetAt("Department Manager"), OpenMode.ForRead);?
??????????????????????????? //最后,把雇員的數據輸出到命令行?
??????????????????????????? resBuf = salesXRec.Data.AsArray()[0];?
??????????????????????????? saEmployeeList.SetValue(string.Format("{0}\n", resBuf.Value), nEmployeeDataCount);?
??????????????????????????? nEmployeeDataCount += 1;?
???????????????????? }?
????????????? }?
????????????? trans.Commit();?
?????? }?
?????? finally?
?????? {?
????????????? trans.Dispose();?
?????? }
}
?[CommandMethod("PRINTOUTEMPLOYEE")]
{?
?????? Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;?
?????? //聲明我們將在下面使用的工具...?
?????? Database db = HostApplicationServices.WorkingDatabase;?
???&nbs, p;, ?? Transaction trans = db.TransactionManager.StartTransaction();?
?????? try?
?????? {?
????????????? //首先,獲取塊表和模型空間塊表記錄
BlockTable bt = (BlockTable)trans.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead);?
????????????? BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);?
????????????? //現在,我們需要把內容輸出到命令行。這里可以有一個對象幫助我們:?
??????????????????????//下面的部分,我們將遍歷模型空間:?
????????????? foreach (ObjectId id in btr)?
????????????? {?
???????????????????? Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false); //打開當前對象!?
???????????????????? if (ent is BlockReference)?
???????????????????? {?
??????????????????????????? string[] saEmployeeList = null;//?這是正確的...定義新的列表。?
??????????????????????????? ListEmployee(id, ref saEmployeeList);?
??????????????????????????? if ((saEmployeeList.Length == 4))?
??????????????????????????? {?
?????????????????????????????????? ed.WriteMessage("Employee Name: {0}", saEmployeeList[0]);?
?????????????????????????????????? ed.WriteMessage("Employee Salary: {0}", saEmployeeList[1]);?
?????????????????????????????????? ed.WriteMessage("Employee Division: {0}", saEmployeeList[2]);?
?????????????????????????????????? ed.WriteMessage("Division Manager: {0}", saEmployeeList[3]);?
??????????????????????????? }?
???????????????????? }?
????????????? }?
?????? }?
?????? finally?
?????? {?
?????? }?????
}
轉載于:https://www.cnblogs.com/jdmei520/articles/1257346.html
總結
以上是生活随笔為你收集整理的AutoCAD .net 二次开发官方教程及源码C#版(4)-(源码下载)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python模拟app抢票_python
- 下一篇: c# 标准正太分布函数_机器学习中常见的