2010年6月25日金曜日

.NET - 「画層の追加と削除」(AutoCAD 2011)

以前、画層の追加を試してみましたが、今回は画層の削除も試してみました。


Erase メソッドで画層は削除できるのですが、削除していい画層かどうかを確認しておかないと大変な事になってしまうので、注意が必要です。

例えば、「テスト」画層があって、その画層に線分などがあるのに、「テスト」画層を消しちゃったら図面がおかしくなっちゃいますよね。


削除していいかどうかは、Purge メソッドで確認することになります。(Purge メソッドを実行すると、削除できないオブジェクトはオブジェクトIDコレクションからなくなるので、それをもとに判断)

試しに作ってみたコードは こちら です。

2010年6月18日金曜日

.NET で気を付けること 「ドキュメントのロックと解除」

今日は、先週の .NET のトレーニングで教えてもらった、ドキュメントのロックと解除について書こうと思います。

モーダル ダイアログのときはいいのですが、モードレス ダイアログを使うときは、ドキュメントをロックしてから作業を行い、最後にロックを解除する必要があるそうです。

モードレス ダイアログがアクティブになると、元のドキュメントが非アクティブになり、そういうときはドキュメントをロックする必要があるそうです。

なので、コンテキスト メニューに自分のメニューを追加して実行する時もドキュメントをロックする必要があります。

それをしないと、複数の図面を操作している時とかにエラーになることがあるようです。(異常終了することも???)

以前、試しにダイアログを作ってみましたが、ロックのことは知りませんでした。
そのときは、コマンドを実行するたびモードレス ダイアログが表示されてしまって、モードレス ダイアログが表示されているかどうか確認する方法を知らなかったので、モーダル ダイアログにしていたので気がつきませんでした。

ということで、モードレス ダイアログやコンテキスト メニューなどを使ってプログラムを作成するときは気を付けましょう。


こんな感じでロックして
    Dim docLock As DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument()

作業終了後にこんな感じで解除します。
    docLoc.Dispose()



「.NET デベロッパ ガイド」にもこんな記述がありました。

------------------------------------------------------
ドキュメントのロックとロック解除


オブジェクトの変更要求や AutoCAD へのアクセスは、さまざまな状況で、いくつものアプリケーションから発生します。他の要求との競合を防ぐため、変更を加える前にドキュメントをロックする必要があります。特定の状況でドキュメントをロックできなかった場合、データベースの変更時にロック違反が発生します。次の場合に、ドキュメントのロックが必要になります。

  • アプリケーションでモードレス ダイアログ ボックスから AutoCAD とやり取りする
  • アプリケーションでカレント ドキュメント以外のロード済みドキュメントにアクセスする
  • アプリケーションが COM サーバとして使用されている
  • アプリケーションでコマンドを Session コマンド フラグに登録する

たとえば、現在のドキュメント以外のドキュメントにあるモデル空間またはペーパー空間に図形を追加する場合、ドキュメントをロックする必要があります。ロックするには、ロックする Database オブジェクトの LockDocument メソッドを使用します。LockDocument メソッドが呼び出されると、DocumentLock オブジェクトが返されます。

ロックしたデータベースの変更を終えたら、データベースをロック解除する必要があります。データベースをロック解除するには、DocumentLock オブジェクトの Dispose メソッドを呼び出します。DocumentLock オブジェクトで Using 文を使用することもできます。Using 文が終了するとデータベースがロック解除されます。

注: Session コマンド フラグを使用しないコマンドで作業する場合、変更前に現在のドキュメントのデータベースをロックする必要はありません。
------------------------------------------------------

2010年6月11日金曜日

.NET(サンプル プログラム) - 「寸法を特定の画層に作成する」(AutoCAD 2011)

イベントっていうので、コマンド実行時やコマンド終了時などなどにある処理を実行するっていうことができるみたいです。
なので、早速試してみました。

試しに作ってみたプログラムの動作はこんな感じです。

-------------------------------------------------------------
・ コマンド名は、ACVD_DrawDimOnDimLayer です。
  このコマンドを、図面ごとに一回だけ実行すると、以下のコマンドが実行されたときに自動的に動作します。
        DIMLINEAR
        DIMALIGNED
        DIMANGULAR
        DIMARC
        DIMRADIUS
        DIMDIAMETER
        DIMORDINATE
        DIMJOGGED

・ 「寸法」画層が存在しない場合は、「寸法」画層を作成する。

・ コマンド終了後、現在層が元に戻る。

・ ACVD_DrawDimOnDimLayer_Remove コマンドを実行すると、その図面ではこの動作は行わなくなります。
-------------------------------------------------------------

コードは こちらです。
dll ファイルは こちら です。

2010年6月4日金曜日

.NET の勉強 「表示、フリーズ、ロック の設定を反転する」(AutoCAD 2011)

以前、悩み事 : 画層のフリーズ状態を反転する簡単な方法は?(AutoCAD LT 2011) で画層のフリーズ状態を反転する簡単な方法はないかなぁ ということを書きました。


折角 .NET の勉強を始めたので、そのコマンドを作ってみました。(.NET なので、LT では使えませんが…)


書いたコードはこんな感じです。

        ' 画層の フリーズ や ON/OFF の設定を逆にするコマンド
        <CommandMethod("ACVD_Blog", "_ACVD_ToggleLayer", "ACVD_ToggleLayer", CommandFlags.Modal)> _
        Public Sub ACVD_ToggleLayer()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim trans As Transaction = db.TransactionManager.StartTransaction
            Dim laTbl As LayerTable = trans.GetObject(db.LayerTableId, OpenMode.ForRead)

            Try
                Dim prRes As PromptResult
                Dim pko As PromptKeywordOptions = New PromptKeywordOptions("")
                pko.Message = vbLf & "どの設定を反転しますか?"
                pko.Keywords.Add("On", "On", "表示(O)")
                pko.Keywords.Add("Freeze", "Freeze", "フリーズ(F)")
                pko.Keywords.Add("Lock", "Lock", "ロック(L)")
                pko.AllowNone = False

                prRes = ed.GetKeywords(pko)
                If prRes.Status <> PromptStatus.OK Then
                    Return
                End If

                For Each objId As ObjectId In laTbl
                    Dim laTblRec As LayerTableRecord = trans.GetObject(objId, OpenMode.ForWrite)

                    ' オプションとして「表示(O)」が選択されたとき
                    If prRes.StringResult.ToString = "On" Then
                        If laTblRec.IsOff = True Then
                            'MsgBox(laTblRec.Name & "画層はオフです")
                            laTblRec.IsOff = False
                        Else
                            'MsgBox(laTblRec.Name & "画層はオンです")
                            laTblRec.IsOff = True
                        End If
                    End If

                    ' オプションとして「フリーズ(F)」が選択されたとき
                    If prRes.StringResult.ToString = "Freeze" Then
                        If laTblRec.IsFrozen = True Then
                            laTblRec.IsFrozen = False

                        ' 現在層はフリーズできないので、現在層の場合は処理を行わないように設定
                        ElseIf laTblRec.ObjectId <> db.Clayer Then
                            laTblRec.IsFrozen = True
                        End If
                    End If

                    ' オプションとして「ロック(L)」が選択されたとき
                    If prRes.StringResult.ToString = "Lock" Then
                        If laTblRec.IsLocked = True Then
                            laTblRec.IsLocked = False
                        Else
                            laTblRec.IsLocked = True
                        End If
                    End If
                Next

                trans.Commit()

            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                Application.ShowAlertDialog(ex.ToString)

            Finally
                trans.Dispose()

            End Try

        End Sub


ビルドした ACAD Video Blog.dll は ここ からダウンロードできます。
これを NETLOAD コマンドでロードして、ACVD_ToggleLayer コマンドを実行すると、「どの設定を反転しますか? [表示(O)/フリーズ(F)/ロック(L)]:」 というオプションが表示されるので、オプションを入力すると、その設定が反転されます。

2010年6月3日木曜日

.NET の勉強 「ユーザ入力のプロンプト - GetString と GetPoint」(AutoCAD 2011)

前回は GetKeywords メソッドを使ってみましたが、ユーザ入力のプロンプトとして GetString メソッド や GetPoint メソッド というのもあるようなので、それらも試してみたいと思います。

で、GetString メソッドですが、オンライン ヘルプにあったサンプルはこんな感じです。


< CommandMethod("GetStringFromUser") > _
Public Sub GetStringFromUser()
  Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument

  Dim pStrOpts As PromptStringOptions = New PromptStringOptions(vbLf & _
                                                               "Enter your name: ")
  pStrOpts.AllowSpaces = True
  Dim pStrRes As PromptResult = acDoc.Editor.GetString(pStrOpts)

  Application.ShowAlertDialog("The name entered was: " & _
                              pStrRes.StringResult)
End Sub


これを実行すると、入力した文字がダイアログに表示されるのですが、それだけじゃおもしろくないので、入力した内容の MTEXT を作成するようにしてみました。
また、MTEXT の基点を GetPoint で取得するようにもしてみました。

        <CommandMethod("ACVD_Blog", "_ACVD_CreateMtext", "ACVD_CreateMtext", CommandFlags.Modal)> _
        Public Sub ACVD_CreateMtext()
            Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = acDoc.Database
            Dim ed As Editor = acDoc.Editor
            Dim trans As Transaction = db.TransactionManager.StartTransaction

            Try
                Dim pStrOpts As PromptStringOptions = New PromptStringOptions(vbLf & "文字を入力: ")
                pStrOpts.AllowSpaces = True

                Dim pStrRes As PromptResult = ed.GetString(pStrOpts)
                If pStrRes.Status <> PromptStatus.OK Then
                    Return
                End If

                Dim ppo As PromptPointOptions = New PromptPointOptions(vbLf & "基点を指定: ")
                ppo.AllowNone = False

                Dim pr As PromptPointResult = ed.GetPoint(ppo)
                If pr.Status <> PromptStatus.OK Then
                    Return
                End If


                Dim blkTbl As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim br As BlockTableRecord = trans.GetObject(blkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

                Dim mt As MText = New MText()
                mt.Location = pr.Value
                mt.TextHeight = 5.0
                mt.ColorIndex = 1
                mt.Contents = pStrRes.StringResult

                br.AppendEntity(mt)
                trans.AddNewlyCreatedDBObject(mt, True)
                trans.Commit()

            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                Application.ShowAlertDialog(ex.ToString)

            Finally
                trans.Dispose()
            End Try
         End Sub