第 5 章 用戶互操作:提示和選擇背景提示通常包含一個描述性信息,伴隨一個停止以讓用戶理解所給的信息并輸入數(shù)據(jù)。數(shù)據(jù)可以通過多種方式被輸入,如通過命令行、對話框或autocad編輯窗口。給出的提示要遵循一定的格式,格式要與一般的autocad提示相一致,這一點(diǎn)是非常重要的。例如,關(guān)鍵字要用“/”號分隔并放在方括號“[]”中,缺省值要放在“<>”內(nèi)。對于一個autocad用戶來說,堅(jiān)持統(tǒng)一的格式將會減少信息理解錯誤的產(chǎn)生。當(dāng)用戶在autocad命令行中選擇一個實(shí)體時,實(shí)體是使用選擇機(jī)制被選擇的。這種機(jī)制包括一個提示,用來讓用戶知道選擇什么并怎樣選擇(如,窗口或單一實(shí)體),然后是一個停頓。試一下諸如pine這種命令來看一下提示的顯示,pedit來看一下使用單一實(shí)體或多線來進(jìn)行選擇。練習(xí)prompts:提示:在本章中,我們將提示輸入雇員名字、職位、薪水和部門來創(chuàng)建一個雇員塊索引對象。如果輸入的部門不存在,我們將提示輸入部門經(jīng)理的名字來創(chuàng)建一個新的部門。在我們繼續(xù)之前,讓我們試著重用以前的代碼。為了進(jìn)行選擇,我們將提示用戶在一個窗口中進(jìn)行選擇或選擇一個實(shí)體,而我們只顯示選擇集中的雇員對象。在前面的章節(jié)中,我們創(chuàng)建了一個名叫“earnest shackleton”的雇員,名字被存儲為“employeeblock”塊定義(塊表記錄)中的mtext。如果我們多次插入這個塊,那么我們看到的都是同一個雇員的名字。我們怎樣才能自定義這個塊以使每次插入這個塊的時候顯示不同雇員的名字?這就要使用塊屬性的功能了。屬性是存儲在每一個塊索引實(shí)例中的文本,并被作為實(shí)例的一部分來被顯示。屬性從存儲在塊表記錄中的屬性定義中繼承相關(guān)的屬性。屬性:讓我們來把mtext實(shí)體類型改變?yōu)閷傩远x。在createemployeedefinition()函數(shù)中,把下面的代碼替換 ‘ 文本:dim text as mtext = new mtext()text.contents = "earnest shackleton"text.location = center 為 '屬性定義dim text as attributedefinition = new attributedefinition(center, "noname", "name:", "enter name", db.textstyle)text.colorindex = 2 試著使用test命令來測試一下createemployeedefinition()函數(shù): <commandmethod("test")> _ public function test() createemployeedefinition() end function 你現(xiàn)在應(yīng)該可以使用insert命令來插入employeeblock塊并對每一個實(shí)例確定一個雇員名。當(dāng)你插入employee塊時,請注意一下塊插入的位置。它是正好被放置在所選點(diǎn)還是有些偏移?試試怎樣修復(fù)它。(提示:檢查塊定義中的圓心)修改createemployee ()以重用 1)讓我們來修改createemployee()函數(shù),以讓它可以接收名字、薪水、部門和職位并返回創(chuàng)建的雇員塊索引的objectid。函數(shù)的形式如下(你可以改變參數(shù)順序) public function createemployee(byval name as string, byval division as string, byval salary as double, byval pos as point3d) as objectid 2) 移除上面函數(shù)中的commandmethod屬性”create”,這樣它就不再是用來創(chuàng)建雇員的命令。3) 修改函數(shù)的代碼,這樣就可以正確地設(shè)置塊索引的名字、職位、部門和薪水和它的擴(kuò)展字典。
替換
dim br as new blockreference(new point3d(10, 10, 0), createemployeedefinition()) 為 dim br as new blockreference(pos, createemployeedefinition())
btr.appendentity(br) '加入索引到模型空間trans.addnewlycreateddbobject(br, true) '讓事務(wù)處理知道 為 dim attref as attributereference = new attributereference() '遍歷雇員塊來查找屬性定義dim empbtr as blocktablerecord = trans.getobject(bt("employeeblock"), openmode.forread) dim id as objectid for each id in empbtr dim ent as entity = trans.getobject(id, openmode.forread, false) '打開當(dāng)前的對象! if typeof ent is attributedefinition then ' '設(shè)置屬性為屬性索引中的屬性定義 dim attdef as attributedefinition = ctype(ent, attributedefinition) attref.setpropertiesfrom(attdef) attref.position = new point3d(attdef.position.x + br.position.x, _ attdef.position.y + br.position.y, _ attdef.position.z + br.position.z) attref.height = attdef.height attref.rotation = attdef.rotation attref.tag = attdef.tag attref.textstring = name end ifnext btr.appendentity(br) '把索引加入模型空間 '把屬性索引加入到塊索引br.attributecollection.appendattribute(attref) '讓事務(wù)處理知道trans.addnewlycreateddbobject(attref, true)trans.addnewlycreateddbobject(br, true) 研究一下上面的代碼,看看是怎樣把屬性定義中除顯示用的文本字符串外的屬性復(fù)制到屬性索引的。屬性被加入到塊索引的屬性集合中。這就是你怎樣來為每一個實(shí)例自定義雇員名字。5)不要忘記返回雇員塊索引的objectid,但要在提交事務(wù)處理之后才能返回: trans.commit()return br.objectid 6) 測試createemployee。加入一個test命令來測試createemployee: <commandmethod("test")> _ public function test() createemployee("earnest shackleton", "sales", 10000, new point3d(10, 10, 0))end function 修改createdivision()以重用:讓我們來修改createdivision ()函數(shù),以讓它可以接收部門名字、經(jīng)理名字并返回創(chuàng)建的部門經(jīng)理擴(kuò)展記錄的objectid。如果部門經(jīng)理已經(jīng)存在,則不改變經(jīng)理的名字。1) 如果你先前在createemployeedefinition()中調(diào)用了createdivision(),請把它注釋掉,因?yàn)槲覀冊谶@里不需要創(chuàng)建一個部門2) 改變createdivision()的形式讓它接收部門和經(jīng)理的名字并返回一個objectid。 public function createdivision(byval division as string, byval manager as string) as objectid 3) 修改上面函數(shù)的代碼創(chuàng)建部門的名字和經(jīng)理:
mgrxrec.data = new resultbuffer(new typedvalue(dxfcode.text, "randolph p. brokwell")) 為 mgrxrec.data = new resultbuffer(new typedvalue(dxfcode.text, manager)) 不要忘了返回部門經(jīng)理這個擴(kuò)展記錄的objectid,但要在提交事務(wù)處理后才返回。 trans.commit()'返回部門經(jīng)理這個擴(kuò)展記錄的objectidreturn mgrxrec.objectid現(xiàn)在把在中createemployeedefinition調(diào)用的createdivision函數(shù)給注釋掉。4) 現(xiàn)在通過使用test命令來測試調(diào)用createdivision函數(shù)。使用arxdbg工具來檢查條目是否已被加入到“acme_division”下的命名對象字典。 createdivision("sales", "randolph p. brokwell") 使用create命令來創(chuàng)建雇員: 我們將加入一個名為create的新命令,此命令用來提示輸入雇員的詳細(xì)資料來創(chuàng)建雇員塊索引。讓我們來看一下這個命令是怎樣使用的。1) 讓我們加入一個名為create的新命令,并聲明幾個常用的變量和一個try-finally塊。 <commandmethod("create")> _ public sub createemployee() dim db = hostapplicationservices.workingdatabase dim ed as editor = application.documentmanager.mdiactivedocument.editor dim trans as transaction = db.transactionmanager.starttransaction() try trans.commit() finally trans.dispose() end try end sub 2) 讓我們來為雇員定義可以用作為提示缺省值的常數(shù)。注意,布爾值gotposition是用來判斷用戶是否已輸入職位。. 雇員名 - 類型 :string -缺省值 “earnest shackleton”. 雇員所在部門名 - 類型:string -缺省值“sales”. 薪水 -類型:double (non-negative and not zero) -缺省值10000. 職位 -類型:point3d -缺省值(0,0,0) 把這些常數(shù)加入到try語句后面: dim empname as new string("earnest shackleton") dim divname as new string("sales") dim salary as new double() : salary = 10000 dim position as new point3d(0, 0, 0) '布爾值用來判斷用戶是否已輸入職位 dim gotposition as new boolean() : gotposition = false 3) 現(xiàn)在讓我們提示用戶輸入值。我們先使用promptxxxoptions類來初始化要顯示的提示字符串。 '提示輸入每個雇員的詳細(xì)資料dim prname as promptstringoptions = new promptstringoptions("enter employee name <" & empname & ">")dim prdiv as promptstringoptions = new promptstringoptions("enter employee division <" & divname & ">")dim prsal as promptdoubleoptions = new promptdoubleoptions("enter employee salary <" & salary & ">")dim prpos as promptpointoptions = new promptpointoptions("enter employee position or") 注意,提示字符串用尖括號來顯示變量的值。這是autocad用來提示用戶這個值為缺省值。4) 當(dāng)提示用戶輸入職位時,我們也提供了一個關(guān)鍵字列表選項(xiàng),如名字、部門和薪水。如果用戶想要在選擇一個點(diǎn)的時候改變?yōu)槠渌担梢赃x擇那個關(guān)鍵字。一個命令提示的例子如下:command: createenter employee position or [name/division/salary]: 要創(chuàng)建一個雇員,用戶會選擇一個點(diǎn)而其它的值被設(shè)置為缺省值。如果用戶要改變其它的值,如名字,他可以輸入”n”或全名”name”,然后輸入名字:command: createenter employee position or [name/division/salary]:nenter employee name <earnest shackleton>: 如果用戶想要再次選擇缺省的名字,他可以按回車鍵。讓我們創(chuàng)建用于職位提示的關(guān)鍵字列表: '加入用于職位提示的關(guān)鍵字prpos.keywords.add("name")prpos.keywords.add("division")prpos.keywords.add("salary") '設(shè)置提示的限制條件prpos.allownone = false '不允許沒有值 5) 現(xiàn)在讓我們聲明promptxxxresult變量來獲取提示的結(jié)果: 'prompt resultsdim prnameres as promptresultdim prdivres as promptresultdim prsalres as promptdoubleresultdim prposres as promptpointresult 6) 直到用戶成功輸入一個點(diǎn)后,循環(huán)才結(jié)束。如果輸入錯誤的話,我們會提示用戶并退出函數(shù):判斷用戶是否輸入了關(guān)鍵字,我們通過檢查promptresult的狀態(tài)來進(jìn)行: '循環(huán)用來獲取雇員的詳細(xì)資料。當(dāng)職位被輸入后,循環(huán)終止。while (not (gotposition)) '提示輸入職位 prposres = ed.getpoint(prpos) '取得一個點(diǎn) if prposres.status = promptstatus.ok then gotposition = true position = prposres.value elseif prposres.status = promptstatus.keyword then '獲取一個關(guān)鍵字 '輸入了name關(guān)鍵字 if prposres.stringresult = "name" then '獲取雇員名字 prname.allowspaces = true prnameres = ed.getstring(prname) if prnameres.status <> promptstatus.ok then return end if '如果獲取雇員名字成功 if prnameres.stringresult <> "" then empname = prnameres.stringresult end if end if else '獲取職位時發(fā)生錯誤 ed.writemessage("***error in getting a point, exiting!!***" + vbcrlf) return end if '如果獲取一個點(diǎn)end while 7) 上面的代碼只提示輸入名字,請加入提示輸入薪水和部門的代碼。 8) 完成提示輸入后,我們將使用獲得的值來創(chuàng)建雇員。 '創(chuàng)建雇員 createemployee(empname, divname, salary, position) 9) 現(xiàn)在來檢查部門經(jīng)理是否已存在。我們通過檢查nod中部門的擴(kuò)展記錄中的經(jīng)理名字來進(jìn)行。如果檢查到的是一個空字符串,那么我們會提示用戶輸入經(jīng)理的名字。注意,通過修改createdivision()函數(shù),獲取經(jīng)理的名字變得簡單了。 dim manager as string = new string("") '創(chuàng)建部門 '給經(jīng)理傳入一個空字符串來檢查它是否已存在 dim depmgrxrec as xrecord dim xrecid as objectid xrecid = createdivision(divname, manager) '打開部門經(jīng)理擴(kuò)展記錄 depmgrxrec = trans.getobject(xrecid, openmode.forread) dim val as typedvalue for each val in depmgrxrec.data dim str as string str = val.value if str = "" then '經(jīng)理沒有被設(shè)置,現(xiàn)在設(shè)置它 '先提示輸入經(jīng)理的名字 ed.writemessage(vbcrlf) dim prmanagername as promptstringoptions = new promptstringoptions("no manager set for the division! enter manager name") prmanagername.allowspaces = true dim prmanagernameres as promptresult = ed.getstring(prmanagername) if prmanagernameres.status <> promptstatus.ok then return end if '設(shè)置經(jīng)理的名字 depmgrxrec.data = new resultbuffer(new typedvalue(dxfcode.text, prmanagernameres.stringresult)) end if next 10) 測試create命令 選擇集:現(xiàn)在讓我們來創(chuàng)建一個命令,當(dāng)用戶在圖形中選擇一個雇員對象時,它會顯示雇員的詳細(xì)資料。我們會使用上一章中創(chuàng)建的listemployee()函數(shù)在命令行中輸出雇員的詳細(xì)資料。下面是你必須遵循的步驟:
調(diào)用“l(fā)istemployees”命令
調(diào)用editor的getselection()函數(shù)來選擇實(shí)體
dim res as promptselectionresult = ed.getselection(opts, filter)
上面的filter用來過濾選擇集中的塊索引。你可以創(chuàng)建如下的過濾列表:
dim fillist() as typedvalue = {new typedvalue(dxfcode.start, "insert")}dim filter as selectionfilter = new selectionfilter(fillist)
從選擇集中獲取objectid數(shù)組:
'如果選擇失敗則什么也不做 if not res.status = promptstatus.ok then return dim ss as autodesk.autocad.editorinput.selectionset = res.value dim idarray as objectid() = ss.getobjectids() 5. 最后,把選擇集中的每個objectid輸入到listemployee()函數(shù)來獲取一個雇員詳細(xì)資料的字符串?dāng)?shù)組。把雇員的詳細(xì)資料輸出到命令行。例如: '獲取saemployeelist 數(shù)組中的所有雇員 for each employeeid in idarray listemployee(employeeid, saemployeelist) '把雇員的詳細(xì)資料輸出到命令行 dim employeedetail as string for each employeedetail in saemployeelist ed.writemessage(employeedetail) next ed.writemessage("----------------------" + vbcrlf) next