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

首頁 > 編程 > .NET > 正文

Autodesk官方最新的.NET教程(七)(C#版)

2024-07-10 13:00:09
字體:
來源:轉載
供稿:網友
  • 本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
  • 第7章 事件 
    本章將討論autocad中的事件。我們將介紹事件處理函數的使用,特別是監視autocad命令的事件處理函數和監視被autocad命令修改的對象的事件處理函數。在解釋怎樣在c#中實現autocad的事件處理之前,我們將首先簡要地討論一下.net中的事件。 

    第一部分  c#中的事件 
    事件只是用來通知一個行為已經發生的信息。在objectarx中,我們使用反應器(reactor)來處理autocad的事件。而在autocad .net api中,objectarx反應器被換成了事件。 
    事件處理函數(或者叫回調函數)是用來監視和反饋程序中出現的事件。事件可以以不同的形式出現。 
    在介紹autocad .net api中的事件之前,讓我們先來簡單地了解一下代理。 
    第1a部分  代理 
    代理是一個存儲方法索引的類(概念與函數指針類似)。代理對方法是類型安全的(與c中的函數指針類似)。代理有特定的形式和返回類型。代理可以封裝符合這種特定形式的任何方法。 
    代理的一個用途就是作為產生事件的類的分發器。事件是.net環境中第一級別的對象。雖然c#把事件處理的許多細節給隱藏掉了,但事件總是由代理來實現的。事件代理可以多次調用(就是它們可以存儲多于1個的事件處理方法的索引)。它們保存了用于事件的一個注冊事件處理的列表。一個典型的代理有以下的形式: 
    public delegate event (object sender, eventargs e) 

    第一個參數sender表示引發事件的對象。第二個參數e是一個eventargs參數(或者是一個派生的類),這個對象通常包含用于事件處理函數的數據。 
    第1b部分 +=和-=語句 

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

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


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

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

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

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


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

    最后,我們要聲明一個全局變量來表示一個point3dcollection,它用來包含我們所選對象的位置(三維點)。 
          point3dcollection employeepositions = new point3dcollection(); 

    第2步:創建第一個文檔事件處理函數(回調函數) 
    現在我們要創建一個事件處理函數。當autocad命令開始執行的時候它會通知我們。我們要檢查globalcommandname的值是否為move。 
             if ( e.globalcommandname == "move" ) 
             { 
             } 

    如果move命令開始執行的話,我們要相應地設置boolean變量beditcommand的值,這樣我們可以知道我們所監視的命令是活動的。同樣地,我們應該把另外一個boolean變量bdorepositioning設置為false來忽略objectopenedformodify事件處理函數。兩個變量設置好以后,在命令活動期間,我們必須要獲得所選塊索引的信息。 
    我們還應該把兩個集合對象的內容清空。我們只關心當前選擇的對象。 
    第3步: 創建數據庫事件處理函數(回調函數) 
    無論什么時候一個對象被打開并要被修改時,數據庫事件處理函數會被調用。當然,如果這時我們監視的命令不是活動的,我們就應該跳過任何被這個回調函數調用的內容。 
             if ( beditcommand == false ) 
             { 
                return; 
             } 
    同樣地,如果我們監視的命令已經結束,而objectopenedformodify事件被另一個回調函數再次觸發的話,而這時有對象被修改時,我們要阻止所有由這個回調函數執行的動作。 
             if ( bdorepositioning == true ) 
             { 
                return; 
             } 
    這個回調函數剩余部分的代碼用來驗證我們是否正在處理employee塊索引。如果是的話,我們就獲取它的objectid和位置(三維點)。下面的代碼可以被粘貼到這個事件處理函數函數。 
          public void objopenedformod(object o, objecteventargs e) 
          { 
             if ( beditcommand == false ) 
             { 
                return; 
             } 

             if ( bdorepositioning == true ) 
             { 
                return; 
             } 

             objectid objid; 
             objid = e.dbobject.objectid; 

             transaction  trans;  
             database  db;  
             db = hostapplicationservices.workingdatabase; 

             trans = db.transactionmanager.starttransaction(); 

             using(entity ent  = (entity)trans.getobject(objid, openmode.forread, false)) 
             { 
                if ( ent.gettype().fullname.equals( "autodesk.autocad.databaseservices.blockreference" ) ) 
                { //we use .net//s rtti to establish type. 
                    blockreference br   = (blockreference)ent; 
                    //test whether it is an employee block 
                    //open its extension dictionary 
                    if ( br.extensiondictionary.isvalid ) 
                    { 
                       using(dbdictionary brextdict  = (dbdictionary)trans.getobject(br.extensiondictionary, openmode.forread)) 
                       { 
                          if ( brextdict.getat("employeedata").isvalid ) 
                          { 
                             //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 
                             attributecollection atts;  
                             atts = br.attributecollection; 
                             if ( atts.count > 0 ) 
                             { 
                                foreach(objectid attid in atts ) 
                                { 
                                   attributereference att; 
                                  using(att = (attributereference)trans.getobject(attid, openmode.forread, false)) 
                                   { 
                                      changedobjects.add(attid); 
                                      employeepositions.add(att.position); 
                                   } 
                                } 
                             } 
                          } 
                       } 
                    } 
                } 
             } 
             trans.commit(); 
          } 

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

             beditcommand = false; 

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

    這個回調函數的剩余代碼用來把employee塊索引和它的關聯屬性引用的當前(修改過的)位置與它們的初始位置作比較。如果位置改變了,我們在這個回調函數中把它們重置這初始的位置。下面的代碼可以被粘貼到這個事件處理函數中。 
          public void cmdended(object o  , commandeventargs e) 
          { 
             //was our monitored command active? 
             if ( beditcommand == false ) 
             { 
                return; 
             } 

             beditcommand = false; 

             //set flag to bypass openedformodify handler 
             bdorepositioning = true; 

             database db   = hostapplicationservices.workingdatabase; 
             transaction trans ; 
             blocktable bt;  
             point3d oldpos;  
             point3d newpos;  
             int i ; 
             for ( i = 0; i< changedobjects.count; i++) 
             { 
                trans = db.transactionmanager.starttransaction(); 
                using( bt = (blocktable)trans.getobject(db.blocktableid, openmode.forread) ) 
                { 
                    using(entity ent   = (entity)trans.getobject(changedobjects[i], openmode.forwrite)) 
                    { 
                       if ( ent.gettype().fullname.equals("autodesk.autocad.databaseservices.blockreference") ) 
                       { //we use .net//s rtti to establish type. 
                          blockreference br = (blockreference)ent; 
                          newpos = br.position; 
                          oldpos = employeepositions[i]; 

                          //reset blockref position 
                          if ( !oldpos.equals(newpos) ) 
                          { 
                             using( trans.getobject(br.objectid, openmode.forwrite) ) 
                             { 
                                br.position = oldpos; 
                             } 
                          } 
                       } 
                       else if ( ent.gettype().fullname.equals("autodesk.autocad.databaseservices.attributereference") ) 
                       { 
                          attributereference att = (attributereference)ent; 
                          newpos = att.position; 
                          oldpos = employeepositions[i]; 

                          //reset attref position 
                          if ( !oldpos.equals(newpos) ) 
                          { 
                             using( trans.getobject(att.objectid, openmode.forwrite)) 
                             { 
                                att.position = oldpos; 
                             } 
                          } 
                       } 
                    } 
                } 
                trans.commit(); 
             } 
          } 

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

    附加的問題:添加一個附加的回調函數,當用戶改變employee塊索引的”name”屬性時,這個回調函數被觸發。 
    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 扬州市| 东港市| 东乡| 江津市| 垣曲县| 全南县| 油尖旺区| 临夏市| 克拉玛依市| 梁山县| 丰都县| 绩溪县| 盐池县| 开化县| 甘孜县| 体育| 晴隆县| 虎林市| 安新县| 天津市| 师宗县| 连城县| 伊川县| 余庆县| 醴陵市| 雅安市| 永安市| 天祝| 榆树市| 卢氏县| 潢川县| 吉水县| 南投市| 施秉县| 化州市| 平南县| 梅州市| 兴安县| 鲁山县| 磐石市| 中山市|