【上級】AcadApplication.GetInterfaceObjectによる「AcCmColor」操作:ACI(インデックスカラー)を超えたTrueColorの完全制御
AutoCAD VBA開発において、画層やオブジェクトの色を変更する際、多くの開発者がいまだに `ColorIndex`(ACI: AutoCAD Color Index、1〜255のインデックスカラー)に依存しています。
しかし、現代のBIM/CIM連携、GISデータのインポート、コーポレートカラー(DICやPANTONE)を厳密に適用しなければならない設計現場において、わずか256色への丸め処理(近似色への強制変換)は許容されません。
TrueColor(RGB)やカラーブックによる精密な色彩管理を行うには、`IAcadAcCmColor` インターフェースを持つオブジェクトの制御が不可欠です。しかし、このオブジェクトはVBA標準の `New` キーワードではインスタンス化できません。
本稿では、`AcadApplication.GetInterfaceObject` を駆使し、AutoCADのバージョン依存性を排除しながら、極めて堅牢かつ高速に `AcCmColor` を完全制御するアーキテクチャを伝授します。
—
1. なぜ `New` できないのか?COM境界を越える `AcCmColor` の真実
AutoCADのカラーシステムは、コア部分が C++(ObjectARX)の `AcCmColor` クラスとして実装されています。VBA(ActiveAPI)からこれにアクセスするには、COMラッパーを経由する必要があります。
‘ ❌ このコードはコンパイルエラーになるか、実行時エラーを引き起こす
Dim col As New AcadAcCmColor
`AcadAcCmColor` は、AutoCADのタイプライブラリに定義されているものの、コクラス(CoClass)として直接インスタンス化することが許可されていません。これを動的に生成するためには、AutoCAD本体(`AcadApplication`)に対して、COMインターフェースを介したオブジェクトの生成を要求する必要があります。
それが、`AcadApplication.GetInterfaceObject` メソッドです。
バージョン依存(ProgID)の壁
`GetInterfaceObject` を呼び出すには、ProgID(プログラムID)を文字列で指定する必要があります。ここに致命的な罠が存在します。
- AutoCAD 2013-2014: `AutoCAD.AcCmColor.19`
- AutoCAD 2015-2016: `AutoCAD.AcCmColor.20`
- AutoCAD 2017-2019: `AutoCAD.AcCmColor.21` (または `.22` / `.23`)
- AutoCAD 2021-2024: `AutoCAD.AcCmColor.24`
- AutoCAD 2025: `AutoCAD.AcCmColor.25`
ProgIDを `”AutoCAD.AcCmColor.24″` のようにハードコーディングしたツールは、AutoCADのバージョンが上がった瞬間、あるいはクライアントPCの環境が異なった瞬間に「オートメーションエラー(オブジェクトの作成に失敗しました)」を吐いて即死します。
プロフェッショナルな設計では、実行中のAutoCADインスタンスからメジャーバージョンを動的に取得し、ProgIDを動的に生成する「ファクトリパターン」を導入しなければなりません。
—
2. 堅牢なカラー管理のアーキテクチャ設計
実務に耐えうるツールを構築するため、以下の3つのレイヤーで設計を行います。
┌────────────────────────────────────────────────────────┐
│ 外部データ (CSV/Excel) │
│ (RGB値, カラーブック名, カラー名) │
└───────────────────────────┬────────────────────────────┘
▼
┌────────────────────────────────────────────────────────┐
│ ColorFactory (バージョン依存の吸収) │
│ – AcadApplication.Version の解析 │
│ – 適切な ProgID で AcCmColor を1度だけ生成 │
└───────────────────────────┬────────────────────────────┘
▼
┌────────────────────────────────────────────────────────┐
│ カラープロセッサ (描画処理) │
│ – RGB / ACI / BookColor の判定と適用 │
│ – 大量オブジェクトの一括処理(COMキャッシュ) │
└────────────────────────────────────────────────────────┘
設計上の最重要注意事項:ループ内での `GetInterfaceObject` は厳禁
`GetInterfaceObject` は、COMのサービスロケーターを呼び出し、プロセス外(またはスレッド境界を越えて)オブジェクトをアクティベートする、極めてオーバーヘッドの大きい処理です。
1万個のハッチングの色を変更するために、ループ内で毎回 `GetInterfaceObject` を呼び出すと、処理時間は数十倍に膨れ上がります。
カラーオブジェクトは、「一度生成したインスタンスを使い回す(再利用する)」、あるいは「必要最小限の数だけプールする」のが鉄則です。
—
3. プロダクションコード:`AcCmColor` 完全制御モジュール
以下に、実生産環境でそのまま使用できる、極めて堅牢なVBAコードを示します。
エラー処理、バージョン自動判定、RGB・ブックカラー(DIC等)への完全対応、そしてパフォーマンスへの配慮をすべて盛り込んでいます。
標準モジュール(例:`ModColorManager`)に配置して使用してください。
Option Explicit
‘ ==============================================================================
‘ 業務自動化プロフェッショナル向け:AcCmColor完全制御モジュール
‘ ==============================================================================
Private m_cachedColorObj As Object ‘ キャッシュされたAcCmColorインスタンス
”’
”’
Private Function GetColorProgID() As String
Dim verStr As String
Dim majorVer As String
Dim dotPos As Integer
‘ AcadApplication.Version は “24.1s (LMS Tech)” のような文字列を返す
verStr = ThisDrawing.Application.Version
dotPos = InStr(verStr, “.”)
If dotPos > 0 Then
majorVer = Left(verStr, dotPos – 1)
Else
majorVer = “24” ‘ フォールバック(AutoCAD 2021-2024相当)
End If
GetColorProgID = “AutoCAD.AcCmColor.” & majorVer
End Function
”’
”’
Public Function GetColorObject() As Object
On Error GoTo Err_Handler
If m_cachedColorObj Is Nothing Then
Dim progId As String
progId = GetColorProgID()
‘ COMインターフェースを介してオブジェクトを生成
Set m_cachedColorObj = ThisDrawing.Application.GetInterfaceObject(progId)
End If
Set GetColorObject = m_cachedColorObj
Exit Function
Err_Handler:
Err.Raise vbObjectError + 513, “GetColorObject”, _
“AcCmColorオブジェクトの生成に失敗しました。ProgID: ” & GetColorProgID() & vbCrLf & _
“エラー詳細: ” & Err.Description
End Function
”’
”’
Public Sub ApplyTrueColor(ByRef ent As AcadEntity, ByVal red As Byte, ByVal green As Byte, ByVal blue As Byte)
On Error GoTo Err_Handler
If ent Is Nothing Then Exit Sub
Dim colorObj As Object
Set colorObj = GetColorObject()
‘ RGB値を設定
‘ AcColorMethodType.acColorMethodByRGB = 1946157056 (通常は定数が未定義のためリテラルかキャストを使用)
colorObj.SetRGB red, green, blue
‘ エンティティに適用
ent.TrueColor = colorObj
Exit Sub
Err_Handler:
Err.Raise Err.Number, “ApplyTrueColor”, “オブジェクトへのRGB適用に失敗しました: ” & Err.Description
End Sub
”’
”’
”’
”’ カラーブック名およびカラー名がAutoCADシステムに存在しない場合、エラーとなります。
”’
Public Sub ApplyBookColor(ByRef ent As AcadEntity, ByVal bookName As String, ByVal colorName As String)
On Error GoTo Err_Handler
If ent Is Nothing Then Exit Sub
Dim colorObj As Object
Set colorObj = GetColorObject()
‘ カラーブックを設定
‘ 存在しないカラーブック・色名を指定すると、ここでオートメーションエラーが発生する
colorObj.SetColorBookColor bookName, colorName
ent.TrueColor = colorObj
Exit Sub
Err_Handler:
Err.Raise Err.Number, “ApplyBookColor”, _
“カラーブックの適用に失敗しました。” & vbCrLf & _
“Book: ” & bookName & ” / Color: ” & colorName & vbCrLf & _
“エラー詳細: ” & Err.Description
End Sub
”’
”’
Public Sub ClearColorCache()
If Not m_cachedColorObj Is Nothing Then
Set m_cachedColorObj = Nothing
End If
End Sub
—
4. 実用例:外部データベース(設定)を模した一括カラー制御
次に、上記のモジュールを使用して、図面内の特定のオブジェクト(例:ハッチングオブジェクトや円)に対して、RGB値やカラーブック(PANTONE等)を動的に適用するメインロジックの実装例を示します。
実践シナリオ
1. 選択セットで図面内の円(`AcadCircle`)をすべて取得。
2. それぞれの円に対して、RGB指定(鮮やかな朱色:R255, G75, B0)を適用。
3. 特定のキーオブジェクトに対しては、カラーブック「DIC Color Guide」の「DIC 150」を適用。
Public Sub ExecutiveColorControlDemo()
On Error GoTo Err_Handler
Dim sset As AcadSelectionSet
Dim ent As AcadEntity
Dim circle As AcadCircle
Dim count As Long
‘ 1. 選択セットの安全な作成
On Error Resume Next
ThisDrawing.SelectionSets(“ColSel”).Delete
On Error GoTo Err_Handler
Set sset = ThisDrawing.SelectionSets.Add(“ColSel”)
‘ 図面内のすべての円を選択
Dim filterType(0) As Integer
Dim filterData(0) As Variant
filterType(0) = 0: filterData(0) = “CIRCLE”
sset.Select acSelectionSetAll, , , filterType, filterData
If sset.count = 0 Then
MsgBox “図面内に円(CIRCLE)が見つかりません。テスト用に円を配置してください。”, vbExclamation
GoTo CleanUp
End If
‘ トランザクション処理の開始をシミュレート(高速化のため再描画を一時停止)
ThisDrawing.StartUndoMark
Dim oldEcho As Variant
oldEcho = ThisDrawing.GetVariable(“CMDECHO”)
ThisDrawing.SetVariable “CMDECHO”, 0
‘ 2. オブジェクトループ(キャッシュされたカラーオブジェクトが暗黙的に使い回される)
count = 0
For Each ent In sset
Set circle = ent
‘ 偶数・奇数で適用するカラーシステムを切り替えるデモ
If count Mod 2 = 0 Then
‘ RGBによる精密指定(コーポレート・オレンジ:R255, G80, B0)
ApplyTrueColor ent, 255, 80, 0
Else
‘ カラーブック(PANTONE)の適用
‘ ※注意:ご使用のAutoCAD環境に該当カラーブックがインストールされている必要があります。
‘ ここでは標準的な「PANTONE(R) solid coated」を使用
On Error Resume Next
ApplyBookColor ent, “PANTONE(R) solid coated”, “PANTONE Yellow C”
‘ カラーブックが存在しない環境へのフォールバック
If Err.Number <> 0 Then
Err.Clear
‘ フォールバックとしてRGBで金色(R212, G175, B55)を設定
ApplyTrueColor ent, 212, 175, 55
End If
On Error GoTo Err_Handler
End If
count = count + 1
Next ent
‘ 図面の更新
ThisDrawing.Regen acActiveViewport
MsgBox count & ” 個のオブジェクトの色をTrueColor/カラーブックに更新しました。”, vbInformation, “処理完了”
CleanUp:
On Error Resume Next
If Not sset Is Nothing Then sset.Delete
ThisDrawing.SetVariable “CMDECHO”, oldEcho
ThisDrawing.EndUndoMark
‘ メモリリーク防止のためCOMキャッシュをクリア
ClearColorCache
Exit Sub
Err_Handler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
—
5. プログラマが直面する致命的な罠とその回避策
罠1:カラーブック(.acbファイル)の不在
`SetColorBookColor` に指定するカラーブック名(例: `”DIC Color Guide”`)やカラー名(例: `”DIC 150″`)は、AutoCADがインストールされているローカルPC内に実ファイル(.acb)として存在している必要があります。
- 格納場所: 通常、`C:\Users\<ユーザー名>\AppData\Local\Autodesk\AutoCAD <バージョン>\<言語>\Support\Color` に配置されています。
- 対策: 配布用ツールを開発する場合、カラーブック名が存在しない時にシステムをクラッシュさせないよう、上記のサンプルコードで実装しているような `On Error Resume Next` によるRGBへのフォールバック処理を必ず組み込んでください。
罠2:オブジェクト解放忘れ(メモリリークと図面破損)
`GetInterfaceObject` で取得したCOMオブジェクトは、VBAの実行終了時に自動的に解放されるとは限りません。特に、非同期処理や例外によってマクロが途中で強制終了した場合、メモリ上にAutoCADの内部COMオブジェクトへの参照が残り続け、図面保存時のクラッシュやAutoCAD終了時のゾンビプロセス化を引き起こします。
- 対策: `On Error GoTo` によるエラーハンドリングの `CleanUp` セクションにおいて、必ずキャッシュされたカラーオブジェクトを `Nothing` に設定(`ClearColorCache` の呼び出し)してください。
—
6. まとめ
ACI(インデックスカラー)からTrueColorへの脱却は、AutoCADにおける作図自動化を「CADオペレーターの代替」から「エンジニアリングシステムへの統合」へと引き上げるための重要なマイルストーンです。
- 動的なProgID生成により、バージョンアップに怯えない堅牢性を。
- シングルトン(キャッシュ)設計により、大量オブジェクト処理時の圧倒的なパフォーマンス向上を。
- フォールバック設計により、実行環境の差異に左右されない極めて高い堅牢性を。
この3本の矢を組み込んだコード設計を徹底することで、あなたの開発するツールは一過性のマクロから「社内プラットフォーム」としての信頼性を獲得できるでしょう。ぜひ、今日からの実装に取り入れてみてください。
