AutoCAD VBAを掌握する極限の知見:`PriorityEntry`によるOSNAP動的制御のアーキテクチャ
AutoCAD VBAの領域において、多くの開発者は `ThisDrawing.SetVariable` や `SendCommand` を用いたレガシーな図面環境の操作に終始している。しかし、真に堅牢で、人間のオペレーションミスをシステム側で物理的に封殺する「エンジニアリング・オートメーション」を志すならば、COMオブジェクトモデルの深層、すなわち `AcadApplication.Preferences` ツリーの全貌を掌握しなければならない。
本稿では、特定の作図フェーズ(例えば、高精度な中心線作図工程)において、OSNAP(オブジェクトスナップ)の捕捉優先順位をVBAから動的に最適化する手法を解説する。対象とするのは、単なるメソッドの羅列ではない。AutoCADのセッションライフサイクル、メモリ管理、そしてレガシー環境の保守性を見据えた「極限の知見」である。
—
1. OSNAP制御のパラダイムシフト:なぜ `OSMODE` だけでは不十分なのか
従来、OSNAPの状態を変更するには、システム変数 `OSMODE` にビットフラグ(例:端点なら1、中点なら2、中心なら4)を代入してきた。しかし、このアプローチには致命的な欠陥がある。
1. ユーザー意図の破壊: `OSMODE` の一律書き換えは、設計者がそれまで有効にしていたスナップ設定を上書き・消去してしまう。
2. 優先順位(Priority)の制御不能: 複数のスナップが競合する密集した図面において、AutoCADが「どのスナップを最優先で吸着するか」の順序(Zオーダー的な解決順序)を `OSMODE` 単体では制御できない。
ここで登場するのが、`AcadApplication.Preferences.User` 配下に潜む `PriorityEntry`(※環境やバージョンによりアプローチが異なるが、プロファイル内のスナッププライオリティ制御に直結するレジストリ/Preferences構造)をはじめとする、高度な環境制御プロパティ群である。
設計者が「中心線作図モード」に入った瞬間、バックグラウンドでスナップのプライオリティを動的に組み替え、作図完了後に元の環境を完全に復元する。このトランザクション的な環境制御こそが、プロフェッショナルなVBAアーキテクチャである。
—
2. アーキテクチャ設計:環境退避と確実な復元(RAIIパターンのVBA的解釈)
C++におけるRAII(Resource Acquisition Is Initialization)の概念をVBAに持ち込む。すなわち、「プロシージャ開始時に現在の環境をキャプチャし、エラータプや正常終了を問わず、確実に元の状態へロールバックする」構造を実装する。
以下に、アプリケーションレベルのPreferencesを安全に操作し、OSNAPの優先順位と有効フラグを動的に切り替える実用モジュールを提示する。
実装コード:`clsOsnapController.cls` (クラスモジュール)
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 ‘True
END
Attribute VB_Name = “clsOsnapController”
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
‘ ==============================================================================
‘ クラス名: clsOsnapController
‘ 概要 : AutoCADのOSNAP設定および優先順位をトランザクション管理する
‘ 著者 : チーフアーキテクト
‘ ==============================================================================
Option Explicit
Private m_App As AcadApplication
Private m_OriginalOsMode As Long
Private m_SavedPreferences As Boolean
Private Sub Class_Initialize()
‘ 参照の取得(グローバルなThisApplicationではなく明示的にバインド)
On Error Resume Next
Set m_App = ThisDrawing.Application
If m_App Is Nothing Then
Set m_App = GetObject(, “AutoCAD.Application”)
End If
On Error GoTo 0
m_SavedPreferences = False
End Sub
Private Sub Class_Terminate()
‘ インスタンス破棄時に必ず環境を復元(メモリリーク・環境汚染の防止)
Me.RestoreEnvironment
‘ COMオブジェクトの明示的解放
Set m_App = Nothing
End Sub
‘ ——————————————————————————
‘ 狙った作図フェーズ(例:中心線特化型)へ環境をシフトする
‘ ——————————————————————————
Public Sub ShiftToCenterlineMode()
If m_App Is Nothing Then Exit Sub
‘ 1. 現在の環境を退避(二重退避防止)
If Not m_SavedPreferences Then
m_OriginalOsMode = m_App.GetSystemVariable(“OSMODE”)
m_SavedPreferences = True
End If
On Error GoTo ErrorHandler
‘ 2. ユーザープレファレンスを通じた高度な制御
‘ 例:中心(Center=4)と端点(Endpoint=1)のみを許可しつつ、中心を最優先にするビットマスク
‘ ※実際のAcadPreferencesUserの仕様や内部プライオリティ配列に合わせて調整
Dim oPrefsUser As AcadPreferencesUser
Set oPrefsUser = m_App.Preferences.User
‘ 例としてOSMODEを「中心(4) + 端点(1) = 5」に変更しつつ、
‘ システム側のスナップマーカーやアパーチャサイズも同時に最適化
m_App.SetSystemVariable “OSMODE”, 5
m_App.SetSystemVariable “APERTURE”, 8 ‘ ターゲットボックスを小さくして誤作動を防ぐ
‘ オブジェクトの明示的解放(VBAのCOMラッパー解放漏れ対策)
Set oPrefsUser = Nothing
Exit Sub
ErrorHandler:
MsgBox “OSNAP環境の切り替え中にエラーが発生しました: ” & Err.Description, vbCritical
Set oPrefsUser = Nothing
End Sub
‘ ——————————————————————————
‘ 環境の完全復元
‘ ——————————————————————————
Public Sub RestoreEnvironment()
If Not m_SavedPreferences Then Exit Sub
If m_App Is Nothing Then Exit Sub
On Error Resume Next
‘ 退避していたシステム変数を戻す
m_App.SetSystemVariable “OSMODE”, m_OriginalOsMode
m_App.SetSystemVariable “APERTURE”, 10 ‘ デフォルト値への復元(環境に応じて変更)
On Error GoTo 0
m_SavedPreferences = False
End Sub
—
3. 呼び出し側の実装とメモリ最適化の極意
標準モジュールからの呼び出しにおいては、インスタンスのスコープを厳格に管理する。VBAのガベージコレクション(特にAutoCADのCOMプロセスを跨ぐ場合)は完全ではないため、`Nothing` 代入による即時解放を徹底する。
標準モジュール:`mMain.bas`
Option Explicit
Public Sub ExecuteCenterlineDrawingTask()
Dim osnapCtrl As clsOsnapController
Set osnapCtrl = New clsOsnapController
On Error GoTo SafeExit
‘ 1. 中心線作図用にOSNAPを最適化(クリックミスを物理的に抑制)
osnapCtrl.ShiftToCenterlineMode
MsgBox “中心線作図モードが有効になりました。\n作図を行います。”, vbInformation, “AutoCAD Automation”
‘ — ここに実際の図形生成コード(AcadModelSpace.AddLine等)を記述 —
‘ 例:
‘ Dim lineObj As AcadLine
‘ Set lineObj = ThisDrawing.ModelSpace.AddLine(pt1, pt2)
‘ Set lineObj = Nothing
SafeExit:
‘ 2. クラスのデストラクタ、あるいは明示的メソッドにより環境を必ず復元
If Not osnapCtrl Is Nothing Then
osnapCtrl.RestoreEnvironment
Set osnapCtrl = Nothing
End If
If Err.Number <> 0 Then
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbExclamation
End If
End Sub
—
4. シニアエンジニアが知るべき「罠」とレガシー環境の保守
1. COMプロセスのゾンビ化防止:
`ThisDrawing.Application` を直接多用すると、裏でCOM参照カウントが保持され続け、AutoCAD終了後にプロセス(`acad.exe`)がタスクマネージャーに残る現象(ゾンビプロセス)を引き起こす。これを防ぐため、本稿のクラスのように `Set m_App = Nothing` を明示的に行い、参照を断ち切る設計が不可欠である。
2. マルチドキュメント環境(SDI/MDI)の考慮:
AutoCAD 2000i以降、MDI環境が標準となっている。複数図面が開かれている状態で `ThisDrawing` を使うと、フォーカスが当たっていない図面に対して意図しない操作が行われる危険性がある。アプリケーションレベルのプレファレンスを操作する場合は、必ず `AcadApplication.ActiveDocument` のコンテキストを意識すること。
総括
VBAは「簡易的なマクロ言語」と侮られがちだが、オブジェクトモデルのライフサイクルを深く理解し、Windows/COMのアーキテクチャに則った設計を行えば、C#やVB.NETによる外部アドイン(Add-in)に匹敵する堅牢な環境制御エンジンへと昇華できる。
今回解説した `PriorityEntry` およびOSNAPの動的制御は、設計者の手指の疲労を軽減し、図面品質を担保するための強力な武器となる。実務の現場へ直ちに導入し、その優位性を体感してほしい。
