国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

Autodesk官方最新的.NET教程(七)(vb.net版)

2024-07-10 13:00:38
字體:
來源:轉載
供稿:網友
第7章 事件 
本章將討論autocad中的事件。我們將介紹事件處理函數的使用,特別是監視autocad命令的事件處理函數和監視被autocad命令修改的對象的事件處理函數。在解釋怎樣實現autocad的事件處理之前,我們將首先簡要地討論一下.net中的事件。 

第一部分  vb.net中的事件 
事件只是用來通知一個行為已經發生的信息。在objectarx中,我們使用反應器(reactor)來處理autocad的事件。而在autocad .net api中,objectarx反應器被換成了事件。 
事件處理函數(或者叫回調函數)是用來監視和反饋程序中出現的事件。事件可以以不同的形式出現。 
在介紹autocad .net api中的事件之前,讓我們先來簡單地了解一下代理。 

第1a部分  代理 
代理是一個存儲方法索引的類(概念與函數指針類似)。代理對方法是類型安全的(與c中的函數指針類似)。代理有特定的形式和返回類型。代理可以封裝符合這種特定形式的任何方法。 
代理的一個用途就是作為產生事件的類的分發器。事件是.net環境中第一級別的對象。雖然vb.net把事件處理的許多細節給隱藏掉了,但事件總是由代理來實現的。事件代理可以多次調用(就是它們可以存儲多于1個的事件處理方法的索引)。它們保存了用于事件的一個注冊事件處理的列表。一個典型的代理有以下的形式: 
public delegate event (sender as object, e as eventargs) 

第一個參數sender表示引發事件的對象。第二個參數e是一個eventargs參數(或者是一個派生的類),這個對象通常包含用于事件處理函數的數據。 

第1b部分 addhandler和removehandler語句 

要使用事件處理函數,我們必須把它與事件聯系起來。這要通過使用addhandler語句。addhandler和removehandler允許你在運行時連接、斷開或修改與事件聯系的處理函數。 
當我們使用addhandler語句時,我們要確定事件引發者的名字,并要使用addressof語句來確定事件處理函數,例如: 
addhandler myclass1.anevent, addressof ehandler 

前面我們說過要使用removehandler語句從事件處理函數中斷開事件(移除聯系)。語法如下所示: 
removehandler myclass1.anevent, addressof ehandler 

第2部分  處理.net中的autocad事件 

在objectarx中,我們使用反應器來封裝autocad事件。在autocad .net api中,我們可以使用事件來代替objectarx反應器。 
通常,處理autocad事件的步驟如下: 
1.       創建事件處理函數 
當一個事件發生時,事件處理函數(或稱為回調函數)被調用。任何我們想要處理的回應autocad事件的動作都在事件處理函數中進行。 
例如,假定我們只想通知用戶一個autocad對象已被加入。我們可以使用autocad數據庫事件”objectappended”來完成。我們可以編寫回調函數(事件處理函數)如下: 
sub objappended(byval o as object, byval e as objecteventargs) 
    messagebox.show("objectappended!") 
    ‘在這里加入一些代碼 
end sub  

函數中的第一個參數代表autocad數據庫。第二個參數代表objecteventargs類,它可能包含對處理函數有用的數據。 
2.       把事件處理函數與事件聯系起來 
為了開始監視動作,我們必須把事件處理函數與事件聯系起來。在這里,當一個對象加入到數據庫時,objectappended事件將會發生。但是,事件處理函數不會響應這個事件,除非我們把它與這個事件聯系起來,例如: 
         dim db as database 
db = hostapplicationservices.workingdatabase() 
addhandler db.objectappended, new objecteventhandler(addressof objappended) 


3.       斷開事件處理函數 
要終止監視一個動作,我們必須斷開事件處理函數與事件的聯系。當對象被加入時,我們想要停止通知用戶這個事件,我們要斷開事件處理函數與事件objectappended的聯系。 
removehandler db.objectappended, addressof objappended 

第3部分  使用事件處理函數來控制autocad的行為 
本章的目的是解釋autocad事件怎樣才能被用于控制autocad圖形中的行為。現在,讓我們使用前一章(第六章)的內容在autocad圖形中創建幾個employee塊索引。我們不想讓用戶能改變employee塊索引的位置,而對于其它的非employee塊索引的位置則沒有這個限制。我們將混合使用數據庫與文檔事件來做到這一點。 
首先,我們想要監視將要被執行的autocad命令(使用commandwillstart事件)。特別地,我們要監視move命令。另外,當一個對象要被修改時,我們應該被通知(使用objectopenedformodify事件),這樣我們可以確定它是否為一個employee塊索引。如果這時就修改對象可能是無效的,因為我們的修改可能會再次觸發事件,從而引起不穩定的行為。所以,我們要等待move命令的執行結束(使用commandended事件),這時就可以安全地修改對象了。當然,任何對塊索引的修改將會觸發objectopenedformodify事件。我們還需要設置一些全局變量來表明一個move命令在運行和被修改的對象是一個employee塊索引。 
注意:因為本章需要比較多的代碼來獲得想要的結果,所以我們不會解釋任何與事件處理無關的代碼,而只是將它們粘貼到事件處理函數中。這里的重點是成功創建和注冊事件處理函數。 
第一步:創建新工程 
我們以第六章的工程開始。請新加入一個類asdkclass2。我們還要加入四個全局變量。前兩個是boolean型的:一個用來表示我們監視的命令是否是活動的,另外一個用來表示objectopenedformodify事件處理函數是否該被忽略。 
'全局變量 
dim beditcommand as boolean 
dim bdorepositioning as boolean 
 
 
接下來,我們要聲明一個全局變量來表示一個objectidcollection,它用來存儲我們所選擇的要修改的對象的objectid。 
dim changedobjects as new objectidcollection() 

最后,我們要聲明一個全局變量來表示一個point3dcollection,它用來包含我們所選對象的位置(三維點)。 
dim employeepositions as new point3dcollection() 
第2步:創建第一個文檔事件處理函數(回調函數) 
現在我們要創建一個事件處理函數。當autocad命令開始執行的時候它會通知我們。我們要檢查globalcommandname的值是否為move。 
if e.globalcommandname = "move" then 
    'set the global variables 
    ‘ 
    ‘ 
    ‘'delete all stored information 
    ‘ 
    ‘ 
end if 
如果move命令開始執行的話,我們要相應地設置boolean變量beditcommand的值,這樣我們可以知道我們所監視的命令是活動的。同樣地,我們應該把另外一個boolean變量bdorepositioning設置為false來忽略objectopenedformodify事件處理函數。兩個變量設置好以后,在命令活動期間,我們必須要獲得所選塊索引的信息。 
我們還應該把兩個集合對象的內容清空。我們只關心當前選擇的對象。 
第3步: 創建數據庫事件處理函數(回調函數) 
無論什么時候一個對象被打開并要被修改時,數據庫事件處理函數會被調用。當然,如果這時我們監視的命令不是活動的,我們就應該跳過任何被這個回調函數調用的內容。 
if beditcommand = false then 
    return 
end if 
同樣地,如果我們監視的命令已經結束,而objectopenedformodify事件被另一個回調函數再次觸發的話,而這時有對象被修改時,我們要阻止所有由這個回調函數執行的動作。 
if bdorepositioning = true then 
    return 
end if 
這個回調函數剩余部分的代碼用來驗證我們是否正在處理employee塊索引。如果是的話,我們就獲取它的objectid和位置(三維點)。下面的代碼可以被粘貼到這個事件處理函數函數。 

public sub objopenedformod(byval o as object, byval e as objecteventargs) 
    if beditcommand = false then 
        return 
    end if 

    if bdorepositioning = true then 
        return 
    end if 

    dim objid as objectid 
    objid = e.dbobject.objectid 

    dim trans as transaction 
    dim bt as blocktable 
    dim db as database 
    db = hostapplicationservices.workingdatabase 

    trans = db.transactionmanager.starttransaction() 
    try 
        'use it to open the current object! 
        dim ent as entity = trans.getobject(objid, openmode.forread, false) 
        if typeof ent is blockreference then 'we use .net's rtti to establish type. 
            dim br as blockreference = ctype(ent, blockreference) 
            'test whether it is an employee block 
            'open its extension dictionary 
            if br.extensiondictionary().isvalid then 
                dim brextdict as dbdictionary = trans.getobject(br.extensiondictionary(), openmode.forread) 
                if brextdict.getat("employeedata").isvalid then 
                    'successfully got "employeedata" so br is employee block ref 

                    'store the objectid and the position 
                    changedobjects.add(objid) 
                    employeepositions.add(br.position) 
                    'get the attribute references,if any 
                    dim atts as attributecollection 
                    atts = br.attributecollection 
                    if atts.count > 0 then 
                        dim attid as objectid 
                        for each attid in atts 
                            dim att as attributereference 
                            att = trans.getobject(attid, openmode.forread, false) 
                            changedobjects.add(attid) 
                            employeepositions.add(att.position) 

                        next 
                    end if 
                end if 
            end if 
        end if 
        trans.commit() 
    finally 
        trans.dispose() 
    end try 
end sub 
第4步 創建第二個文檔事件處理函數(回調函數) 
當一個命令結束時,第三個事件處理函數被調用。同樣地,我們要檢查全局變量來驗證這個將要結束的命令是我們監視的命令。如果是我們監視的,那么我們要重置這個變量: 
if beditcommand = false then 
    return 
end if 

beditcommand = false 

這個回調函數執行的動作將會再次觸發objectopenedformodify事件。我們必須確定在這個回調函數中跳過了所有與此事件有關的動作。 
'設置標志來跳過openedformodify處理函數 
bdorepositioning = true 


這個回調函數的剩余代碼用來把employee塊索引和它的關聯屬性引用的當前(修改過的)位置與它們的初始位置作比較。如果位置改變了,我們在這個回調函數中把它們重置這初始的位置。下面的代碼可以被粘貼到這個事件處理函數中。 

public sub cmdended(byval o as object, byval e as commandeventargs) 
    'was our monitored command active? 
    if beditcommand = false then 
        return 
    end if 

    beditcommand = false 

    'set flag to bypass objectopenedformodify handler 
    bdorepositioning = true 

    dim db as database = hostapplicationservices.workingdatabase 
    dim trans as transaction 
    dim bt as blocktable 
    dim oldpos as point3d 
    dim newpos as point3d 
    dim i as integer 
    dim j as integer = 1 
    for i = 0 to changedobjects.count - 1 
        trans = db.transactionmanager.starttransaction() 
        try 
            bt = trans.getobject(db.blocktableid, openmode.forread) 
            dim ent as entity = ctype(trans.getobject(changedobjects.item(i), openmode.forwrite), entity) 
            if typeof ent is blockreference then 'we use .net's rtti to establish type. 
                dim br as blockreference = ctype(ent, blockreference) 
                newpos = br.position 
                oldpos = employeepositions.item(i) 

                'reset blockref position 
                if not oldpos.equals(newpos) then 
                    trans.getobject(br.objectid, openmode.forwrite) 
                    br.position = oldpos 
                end if 
            elseif typeof ent is attributereference then 
                dim att as attributereference = ctype(ent, attributereference) 
                 newpos = att.position 
                oldpos = employeepositions.item(i) 

                'reset attref position 
                if not oldpos.equals(newpos) then 
                    trans.getobject(att.objectid, openmode.forwrite) 
                    att.position = oldpos 
                end if 
            end if 
            bt.dispose() 
            trans.commit() 
        finally 
            trans.dispose() 
        end try 
    next 
end sub 

第5步  創建命令來注冊/斷開事件處理函數 
創建一個addevents命令,使用+=語句來把上面的3個事件處理函數連接到各自的事件。在這個命令中,我們還應該設置全局boolean變量: 
beditcommand = false 
bdorepositioning = false 
 
創建另外一個命令removeevents,使用removehandler語句把事件處理函數與事件斷開。 
第6步: 測試工程 
要測試這個工程,請使用create命令創建一個或多個employee塊索引。如果你要作比較的話,你也可以插入一些非employee的塊索引。 
在命令行中鍵入addevents命令來執行它。 
在命令行中輸入move命令,然后選擇你想要的塊索引。注意,當move命令結束時,employee塊索引(包括屬性)還留在原處。 
執行removeevents命令,然后在試一下move命令。注意,employee塊索引現在可以被移動了。 

附加的問題:添加一個附加的回調函數,當用戶改變employee塊索引的”name”屬性時,這個回調函數被觸發。 
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 申扎县| 东安县| 凤城市| 潢川县| 仁怀市| 奉化市| 东乡族自治县| 常山县| 肥西县| 涿州市| 海伦市| 张家口市| 永康市| 玉溪市| 宁陵县| 兰西县| 驻马店市| 孙吴县| 天峻县| 望都县| 绥棱县| 綦江县| 宿州市| 亳州市| 井冈山市| 兴隆县| 泗洪县| 台前县| 韶山市| 会昌县| 徐州市| 江城| 乌鲁木齐市| 富顺县| 淮安市| 怀远县| 平阳县| 射阳县| 右玉县| 固阳县| 射阳县|