【実務・中級編】【上級】AcadApplication.GetInterfaceObjectによる「AcCmColor」操作:ACI(インデックスカラー)を超えたTrueColorの完全制御 – AutoCAD VBA解析バイブル

スポンサーリンク

【上級】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インスタンス

”’

”’ 実行中のAutoCADバージョンに適したAcCmColorのProgIDを動的に生成する
”’

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

”’

”’ AcCmColor オブジェクトを安全かつ高速に取得する(シングルトンパターン)
”’

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

”’

”’ 指定されたエンティティに対して、RGBカラーを適用する
”’

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

”’

”’ 指定されたエンティティに対して、カラーブック(DICやPANTONE)の色を適用する
”’

”’
”’ カラーブック名およびカラー名が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

”’

”’ キャッシュしているCOMオブジェクトを明示的に解放する(プロセスのクリーンアップ用)
”’

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本の矢を組み込んだコード設計を徹底することで、あなたの開発するツールは一過性のマクロから「社内プラットフォーム」としての信頼性を獲得できるでしょう。ぜひ、今日からの実装に取り入れてみてください。

タイトルとURLをコピーしました