.NET APIを使用してAutoCAD用のプラグインを作成する(パート3-レイヤーの操作)

これは、AutoCAD用の一連のプラグインの別の記事です。 ドキュメント内のレイヤーを使用した基本操作について説明します。



public static string disclaimer = "          AutoCAD.   –      .";
      
      





1.一般的な情報



この記事のすべての読者は、レイヤーとは何かをよく知っているでしょう。 プリミティブレベルでは、開発者にとって重要な共通機能を持つ要素を描画するためのコンテナと考えることができます。



レイヤーは、図面を作成するエンジニアだけでなく、プログラマーの生活を大幅に簡素化できます。 たとえば、同じレイヤーにあるすべての要素を必要に応じて非常にすばやく非表示にしてから、作業領域に再表示できます。



この記事のフレームワークでは、基本的な情報が必要になります。これは主にここから収集できますmirror



1.1。 レイヤー番号ゼロ


AutoCADドキュメントには、常に少なくとも1つのレイヤーが含まれています-ゼロ(名前「0」)は削除できません。 多くの場合、このレイヤーは非常に便利です。たとえば、他のレイヤーを削除する場合です。



1.2。 現在のレイヤー


ドキュメントのレイヤーの1つは最新でなければなりません。 図面に追加されたすべてのオブジェクトは、その上に配置されます(少なくともプリミティブ-物事はブロックでは多少複雑です)。



1.3。 レイヤーのプロパティ


AutoCADの(ゼロを含む)レイヤーには3つのプロパティがあります。



これらのプロパティはすべてバイナリです(各プロパティはyes / noフラグと見なすことができます)。



on 」フラグ 、レイヤーの可視性を担当します。 このフラグをオフにすると、レイヤーにあるすべての要素が図面に表示されなくなります。



凍結フラグは、レイヤーの可視性にも関与します。 その効果は、「オン」フラグに似ています。 ドキュメントに示されているように、このプロパティにより、非常に大きな図面のパフォーマンスが向上します。

注意:
個人的に、私は大きな図面で作業したことも、このプロパティを使用したこともありません。


ロック 」フラグは、レイヤーの編集を担当します。 このフラグが設定されている場合、レイヤー上にあるすべての要素は、変更(移動、削除など)ができなくなります。 さらに、ロックされたレイヤーに新しい要素を追加することはできません。



レイヤーのプロパティは、AutoCADから制御できます。 次の図では、「レイヤー」パネルは緑の濃い色で強調表示され、レイヤーのドロップダウンリストは紫色で強調表示されます。 )









注意:
これらのスイッチは本当に注意を払う価値があります。プラグインを作成するとき、すべてが最初に取得されるとは限らず、「手動制御」を使用する必要がある場合もあります。

注意:
一部のサイトでは、この画像は緑と紫ではなく、ライムとヘリオトロープであると主張しています

...

私はだと思います。


1.4。 レイヤー管理


レイヤーを使用した最も単純なアクションについては、前の段落で説明しました。 より複雑な操作(たとえば、レイヤーの作成または削除)を行うには、レイヤープロパティパネルを使用する必要があります。これは、 LAYERコマンドによって呼び出されるか、レイヤーパネルの対応するアイコンをクリックします(前のセクションの図でオレンジ色で示されています)。 このパネルは次のように表示されます。









特に興味深いのは、フレーム内で強調表示されたボタンのセクションです。 最初のボタンは新しいレイヤーを作成し、3番目のボタンは可能であれば既存のレイヤーを削除します。



削除できません:



レイヤーを削除する前に、これらの条件が満たされていることを確認する必要があります。



注意:
実際、削除が禁止されているレイヤーのリストはやや長くなっています。











残念ながら、この投稿著者はDefpointsまたはXrefに依存するレイヤーを扱う必要がなかったので、これらの基本的な質問の研究は簡単な宿題として読者に任せます。 ^ __ ^


それはすべて理論です。練習を開始できます。



2.プラグインを書く



2.1。 新しいプラグインプロジェクトを作成する


サイクルの最初の記事はこれに捧げられました。 .NET Framework 3.5は、次の例で.NET Frameworkの必須バージョンとしてリストされています。



コードフレームワークをすぐに追加できます。
 using System; using Autodesk.AutoCAD.Runtime; using Autodesk.Windows; namespace MyAutoCADDll { public class Commands : IExtensionApplication { //        AutoCAD  "TestCommand" [CommandMethod("TestCommand")] public void MyCommand() { } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } }
      
      





2.2。 必要なライブラリへのリンクを追加する


この例では、 AcMgd.dllAcDbMgd.dllの 2つのAutoCAD .NET APIライブラリが必要です (いつものように、 CopyLocal



を無効にすることを忘れないでください)。



2.3。 新しいレイヤーを追加する


ドキュメントに存在するすべてのレイヤーは、レイヤーリストに保存されます。 図面に新しいレイヤーを追加するには、このリストに新しい要素を追加するだけです。



ただし、操作は単純ですが、多くのコードが取得されます。



コード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; namespace HabrPlug_Layers { public class Commands : IExtensionApplication { //        AutoCAD  "TestCommand" [CommandMethod("TestCommand")] public void MyCommand() { //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) { //     LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; //        LayerTableRecord acLyrTblRec = new LayerTableRecord(); acLyrTblRec.Name = "HabrLayer"; //       acLyrTbl.Add(acLyrTblRec); //      tr.AddNewlyCreatedDBObject(acLyrTblRec, true); //   tr.Commit(); } } } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } }
      
      





プラグインをロードして「TestCommand」コマンドを実行すると、新しいレイヤーが図面に表示されます。











上記のコードでは、描画オブジェクトを操作するときによく見られる2つの重要な構造を使用しました。

a)ドキュメントのブロック;
 using (DocumentLock docloc = acDoc.LockDocument())
      
      





Autocadのドキュメントによると、オブジェクトの変更やAutoCADへのアクセスのリクエストは、あらゆるコンテキストで、あらゆるアプリケーションから実行できます。 他の要求との競合を防ぐために、プログラマはドキュメントを変更する前にロックされていることを確認する必要があります。 場合によっては、ドキュメントデータベースを変更するときにエラーが発生します。



データベースに必要なすべての変更が完了したら、 DocumentLock



オブジェクトのDispose()



メソッドを使用してロックを解除する必要があります。 DocumentLock



オブジェクトの宣言using



ブロックを使用することもできます。この場合、ブロックを終了すると、データベースは自動的にロック解除されます。 ( ソースミラー



注意:
私の経験では、using構文を使用すると、 Dispose()



メソッドの呼び出しを忘れる可能性がなくなるため、はるかに便利です。
b)トランザクション呼び出し。
 using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) … tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; … tr.AddNewlyCreatedDBObject(acLyrTblRec, true); … tr.Commit();
      
      





ドキュメントmirror )は、セグメント、円、ポリラインなどのオブジェクトを操作するとき、または識別子テーブルとそのレコードを操作するときは、読み取りまたは書き込みのためにオブジェクトを開く必要があることを示しています。



この要件を無視しようとしても、良い結果は得られません-非常に不快なエラー(デバッグの観点を含む)が発生する可能性があります。



トランザクションの操作にはいくつかの主要な段階があります。

  1. 新しいトランザクションを開始する
  2. 読み取りまたは書き込みのためにオブジェクトを開く。
  3. オブジェクトが初めて作成された場合(ドキュメントにまだない場合)-ドキュメントデータベースに追加します。
  4. トランザクション固定;
  5. トランザクションの完了。


これらの項目はすべて、上記のリンクのドキュメントで詳細に説明されています。



DocumentLock



場合と同様に、トランザクションの操作を終了した後にDispose()



メソッドを呼び出すか、usingコンストラクトを使用する必要があります。



ドキュメントのロックとトランザクションを理解したので、残りのコードの解析に進むことができます。



まず 、必要な名前空間を接続します。



Autodesk.AutoCAD.Runtime



- IExtensionApplication



タイプとCommandMethod



コンストラクトを使用します。

Autodesk.AutoCAD.DatabaseServices



- Document



およびDocumentLock



タイプを使用します。

Autodesk.AutoCAD.Runtime



- Database



Transaction



LayerTable



OpenMode



、およびLayerTableRecord



タイプを使用します。



次に 、ドキュメントをロックしてトランザクションを開始します。



 //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) {
      
      





第三に、ドキュメントレイヤーテーブルへのリンクを取得します。



 LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
      
      





GetObject()



メソッドは、入力として、開くオブジェクトのIDとアクセスレベルの2つのパラメーターを受け入れます。 このドキュメントのデータベースのLayerTableId



プロパティを使用して、ドキュメントレイヤーテーブルのIDを見つけることができます。 レイヤーテーブルを変更する(新しいレイヤーを追加する)必要があるため、「書き込み」アクセスレベル( OpenMode.ForWrite



)を使用します。 最後に、 GetObject()



メソッドは、タイプ "object"( object



)の値を返します。この値は、必要なタイプ( LayerTable



)に明示的にキャストする必要があります。



4番目に 、新しいレイヤーを作成します。



 LayerTableRecord acLyrTblRec = new LayerTableRecord(); acLyrTblRec.Name = "HabrLayer";
      
      





レイヤー(または、レイヤーのドキュメントテーブル内の対応するエントリ)は、 LayerTableRecord



LayerTableRecord



。 そのコンストラクターは値を受け入れないため、作成後にすべての初期化を行う必要があります。



この例では、新しいレイヤーの名前のみを変更しましたが、必要に応じて、可視性( IsOff



プロパティ)または編集可能( IsLocked



プロパティ)などの他のパラメーターも設定できます。



5番目に、ドキュメントレイヤーテーブルに新しいレイヤーを追加します。



 acLyrTbl.Add(acLyrTblRec);
      
      





レイヤーテーブルは、 IEnumerable



インターフェイスが実装されるクラスです。 新しい要素を追加するには、 Add()



メソッドを使用します。



6番目に、ドキュメントデータベースに新しいレイヤーを追加します。



 tr.AddNewlyCreatedDBObject(acLyrTblRec, true);
      
      





このレイヤーはトランザクションが開始される前に存在しなかったため、ドキュメントデータベースに追加する必要があることを明示的に示す必要があります。 これが行われない場合、エントリは追加されません。



重要な詳細: AddNewlyCreatedDBObject



関数は、ドキュメントレイヤーテーブルにレイヤーを追加した後ではなく、前に呼び出す必要があります。 これらの操作を入れ替えようとしても、レイヤーは追加されません。 これについては、調和の取れた論理的な説明はありません。 知識のある人がコメントの手がかりを共有してくれたら嬉しいです。



7番目に 、トランザクションをコミットします。



 tr.Commit();
      
      





GetObject()



メソッドを使用してトランザクション中に開かれた要素が変更された場合、これらの変更をドキュメントデータベースに保存するには、 Commit()



メソッドを呼び出してトランザクションをコミットする必要があります。 そうでない場合、変更は保存されず、ドキュメントはトランザクションが開始された時点で存在していた状態のままになります。



最後に 、トランザクションを終了し、ドキュメントのロックを解除します。



  } }
      
      





ここにあるのは、usingを使用することの重要なプラスです! 特にトランザクションをコミットしてドキュメントをロック解除するために、これを2回行う必要があるため、 Dispose()



メソッドの呼び出しを忘れることは非常に簡単です。 また、usingコンストラクトを使用すると、 Dispose()



メソッドが自動的に呼び出されます。



2.4。 現在のレイヤーを設定


Clayer



データベースのClayer



プロパティを使用して、現在のドキュメントレイヤーを取得し、新しいレイヤーを設定できます。



コード:
 acCurDb .Clayer = acLyrTbl["HabrLayer"];
      
      





トランザクションをコミットする直前に、前の例にこの行を挿入してください。


2.5。 プロパティを変更し、レイヤーの名前を変更する


レイヤーのプロパティを変更するには、レイヤーテーブルで対応するエントリを開きます。



コード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; namespace HabrPlug_Layers { public class Commands : IExtensionApplication { //        AutoCAD  "TestCommand" [CommandMethod("TestCommand")] public void MyCommand() { //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) { //     LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; //        LayerTableRecord acLyrTblRec = new LayerTableRecord(); acLyrTblRec.Name = "HabrLayer"; //       acLyrTbl.Add(acLyrTblRec); //      tr.AddNewlyCreatedDBObject(acLyrTblRec, true); //   tr.Commit(); } } } //        AutoCAD  "NewCommand" [CommandMethod("NewCommand")] public void NewCommand() { //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) { //     LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; //        -    if (acLyrTbl.Has("HabrLayer") == false) { return; } //      LayerTableRecord acLyrTblRec = tr.GetObject(acLyrTbl["HabrLayer"], OpenMode.ForWrite) as LayerTableRecord; //     acLyrTblRec.Name = "test"; acLyrTblRec.IsOff = true; acLyrTblRec.IsLocked = true; //   tr.Commit(); } } } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } }
      
      





レイヤーを使用する操作の前に、ドキュメントレイヤーテーブルのHas()



メソッドを使用しHas()



、レイヤーHas()



存在することを確認しておくと役立ちます。



プラグインをダウンロードし、TestCommandコマンドを実行してからNewCommandコマンドを実行すると、作成したレイヤーが非表示になり、ブロックされ、名前が変更されていることがわかります。 今では誰も彼を見つけることができません。











2.6。 レイヤー除去


レイヤーの削除は、変更のようなものです。 レイヤーテーブルの対応するエントリに対して、 Erase()



メソッドは次のように呼び出されます。



 acLyrTblRec.Erase(true);
      
      





ただし、最初のセクションで説明した制限に留意することが重要です。 削除できません:



現在最新のレイヤーを削除する場合、削除する前に、他のレイヤーを現在のゼロにする必要があります。



オブジェクトが存在するレイヤーを削除する必要がある場合は、レイヤーを削除する前に、これらのオブジェクトをすべて削除するか、別のレイヤーに転送する必要があります。



レイヤーの削除の詳細については、ドキュメントを参照してください(「 AutoCADエンティティの作成と編集>レイヤー、色、線種の使用>レイヤーの操作>レイヤーの消去 」セクション)。



Kean Walmsleyブログには、レイヤーに配置されたすべてのオブジェクトを検索するためのテンプレートがあります。 この例に基づいて、レイヤーからすべてのオブジェクトを削除する関数を作成できます。



いずれにせよ、レイヤーを削除する前に、操作の正確性を検証し、 try ... catch



構造で削除自体をフレーム化することはtry ... catch







コード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; namespace HabrPlug_Layers { public class Commands : IExtensionApplication { //        AutoCAD  "TestCommand" [CommandMethod("TestCommand")] public void MyCommand() { //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) { //     LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; //        LayerTableRecord acLyrTblRec = new LayerTableRecord(); acLyrTblRec.Name = "HabrLayer"; //       acLyrTbl.Add(acLyrTblRec); //      tr.AddNewlyCreatedDBObject(acLyrTblRec, true); //   tr.Commit(); } } } //        AutoCAD  "TestCommand" [CommandMethod("NewCommand")] public void NewCommand() { //       Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //   using (DocumentLock docloc = acDoc.LockDocument()) { //   using (Transaction tr = acCurDb.TransactionManager.StartTransaction()) { //     LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable; //        -    if (acLyrTbl.Has("HabrLayer") == false) { return; } //       acCurDb.Clayer = acLyrTbl["0"]; // ,         ObjectIdCollection acObjIdColl = new ObjectIdCollection(); acObjIdColl.Add(acLyrTbl["HabrLayer"]); acCurDb.Purge(acObjIdColl); if (acObjIdColl.Count > 0) { //      LayerTableRecord acLyrTblRec = tr.GetObject(acObjIdColl[0], OpenMode.ForWrite) as LayerTableRecord; try { //   acLyrTblRec.Erase(true); //   tr.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception Ex) { //    - ,    Application.ShowAlertDialog(":\n" + Ex.Message); } } } } } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } }
      
      





このコードでは、 Purge()



メソッド以外のすべてにすでに精通しています。 操作の原理はドキュメントに記載されています 。オブジェクトのコレクションを分析し、出力で誰も参照していないオブジェクトのみを残します。



検討した例では、 Purge()



メソッドは、1つのオブジェクト(削除されたレイヤー)のみが存在するコレクションに対して呼び出されます。 誰もこのレイヤーを参照していない場合、 Purge()



メソッドを呼び出した後、コレクションに残り、削除を続行できます。 Purge()



メソッドの呼び出しが空のコレクションを返す場合、削除されたレイヤーへのリンクがあります-これらはおそらくその上に置かれたオブジェクトです。



プラグインをダウンロードしてTestCommandコマンドを実行し、次にNewCommandコマンドを実行すると、作成したレイヤーが図面から削除されていることがわかります。











2.7。 ロックされたレイヤーの調光を防ぐ


結論として、レイヤーに関連する別のパラメーターについてお話したいと思います。



デフォルトでは、AutoCADのロックされたレイヤーは暗く表示されます。 可能な最大の調光は90%です(下図の長方形のように)。











調光の度合いを変更するには、 LAYLOCKFADECTL変数を使用します。 その値は、レイヤーコントロールパネルの対応するスライダーで設定されます(図の緑色の丸で囲まれています)。



プラグイン内のLAYLOCKFADECTL変数の値を変更するには、 SetSystemVariable



関数を使用できます。



 Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("LAYLOCKFADECTL", 0);
      
      





このコードの結果、ロックされたレイヤーの調光は無効になります。



LAYLOCKFADECTL変数を変更する前に、プラグインの処理が完了した後に変数を元の状態に戻すために、現在の値を保存する必要があります。



コード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; namespace HabrPlug_Layers { public class Commands : IExtensionApplication { //         int old_LAYLOCKFADECTL = 0; //     public void Initialize() { //       old_LAYLOCKFADECTL = System.Convert.ToInt32(Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("LAYLOCKFADECTL")); //        0 Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("LAYLOCKFADECTL", 0); } //    AutoCAD public void Terminate() { //      ,       Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("LAYLOCKFADECTL", old_LAYLOCKFADECTL); } } }
      
      





残念ながら、 Terminate()



メソッドは常に正しく機能するとは限らず、元の値が復元されない場合があります。 しかし、少なくとも私たちは試しました。)



今のところすべてです。 次回は、単純なオブジェクトとブロックの作成について書きます。



All Articles