【テクニカル・上級編】【上級】AcadApplication.Preferences.Display.CursorSizeを0%から100%へ動的変更:精密な位置合わせを支援するVBA十字カーソル制御 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:`CursorSize`動的制御による精密位置合わせエンジニアリング

図面上の膨大な座標空間において、1ピクセルのズレが数メートルの致命的な設計ミスに繋がる土木・プラント設計の現場。そこでは、マウスカーソルの位置合わせ精度が生産性を左右する。

AutoCADの標準機能である「十字カーソルサイズ(`CursorSize`プロパティ)」は、通常オプション画面から手動で変更する。だが、これを考えてみてほしい。全体配置図を確認しているときは標準のままで構わないが、「特定の詳細位置合わせコマンドを実行する瞬間だけ、カーソルを画面いっぱいの100%に拡張し、処理が終われば元のサイズに復元する」としたらどうだろうか?

本稿では、`AcadApplication.Preferences.Display.CursorSize`をVBAから動的に操り、さらにWindows APIやイベントハンドリングを駆使して「実用に耐えうる極限のUI自動化」を実装するアーキテクチャを解説する。

—

1. `CursorSize` オブジェクトモデルの深層と落とし穴

AutoCADのプロパティ構造において、十字カーソルのサイズはアプリケーション全体の環境設定(Preferences)に属している。

ThisDrawing.Application.Preferences.Display.CursorSize = 100

一見すると極めてシンプルに思えるこのコードだが、シニアエンジニアであればここで一つの疑問に行き着くはずだ。
「このプロパティ変更は、レジストリや`.cfg`ファイルへの書き込みを伴うため、高頻度で実行するとI/Oボトルネックを引き起こすのではないか?」

その通り。`Preferences`オブジェクトを介した設定変更は、内部的にAutoCADのプロファイルへ即時永続化(Persist)される動作を誘発することがある。マクロのループ内でこれを無闇に呼び出すと、確実にパフォーマンスが低下する。したがって、動的制御を行う場合は「必要な時だけ変更し、確実に復元する」という厳密なライフサイクル管理が絶対条件となる。

—

2. 実装:コマンド実行時限定のカーソル100%動的制御モジュール

以下のコードは、特定の図面要素の位置合わせ作業を想定した実用モジュールである。エラーハンドリングと状態の確実な復元(レイヤー構造のクリーンアップに似た思想)を担保している。

Option Explicit

‘ —————————————————————————
‘ モジュール名: mCursorController
‘ 概要: カーソルサイズを動的に制御し、精密位置合わせを支援するプロシージャ
‘ —————————————————————————

Public Sub ExecutePrecisionAlignment()
Dim acadApp As AcadApplication
Dim originalCursorSize As Integer
Dim isErrorOccurred As Boolean

‘ 1. アプリケーションインスタンスの安全な取得
On Error GoTo ErrorHandler
Set acadApp = ThisDrawing.Application

‘ 2. 現在のカーソルサイズを退避(保守性の確保)
originalCursorSize = acadApp.Preferences.Display.CursorSize

‘ 3. カーソルを全画面(100%)へ拡張
‘ ※ 範囲は 1 から 100 まで。0を指定するとボックスカーソルになる。
acadApp.Preferences.Display.CursorSize = 100

‘ — 【実務フェーズ】精密位置合わせ処理のシミュレーション —
‘ ここに実際のユーザーインタラクション(Utility.GetPoint等)を記述する
Call RunUserInteraction(acadApp)

GoTo Finally

ErrorHandler:
isErrorOccurred = True
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “Cursor Controller”

Finally:
‘ 4. 状態の確実な復元(例外発生時も必ず実行する)
If Not acadApp Is Nothing Then
acadApp.Preferences.Display.CursorSize = originalCursorSize
End If

‘ 5. 明示的なオブジェクト解放(メモリリークの根絶)
Set acadApp = Nothing

If isErrorOccurred Then Exit Sub
End Sub

Private Sub RunUserInteraction(ByVal app As AcadApplication)
Dim pt1 As Variant

‘ 例として、ユーザーからの点入力待ちの間にカーソル100%の恩恵を受ける
app.ActiveDocument.Utility.Prompt vbCrLf & “【精密モード】位置合わせの基準点を指定してください: ”

On Error Resume Next
pt1 = app.ActiveDocument.Utility.GetPoint(, “点を選択: “)
On Error GoTo 0

If Not IsEmpty(pt1) Then
app.ActiveDocument.Utility.Prompt vbCrLf & “指定座標: X=” & pt1(0) & “, Y=” & pt1(1)
End If
End Sub

—

3. 高度な応用:Windows API連携による描画リフレッシュの強制

AutoCADの内部グラフィックスエンジンは、VBAからのプロパティ変更を即座にビューポートへ描画反映しない場合がある(特にハードウェアアクセラレーション有効時)。カーソルサイズを変更した直後に確実画面を再描画させたい場合、AutoCAD標準の `Regen` メソッドでは重すぎる。

そこで、軽快な画面更新のためにAutoCADのウィンドウハンドル(HWND)を特定し、Windows API (`RedrawWindow`) を直接叩くアプローチが有効となる。

‘ 32ビット/64ビット環境両対応のAPI宣言
If Win64 Then
Private Declare PtrSafe Function FindWindowEx Lib “user32” Alias “FindWindowExA” (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr
Private Declare PtrSafe Function RedrawWindow Lib “user32” (ByVal hwnd As LongPtr, lprcUpdate As Any, ByVal hrgnUpdate As LongPtr, ByVal fuRedraw As Long) As Long
Else
Private Declare Function FindWindowEx Lib “user32” Alias “FindWindowExA” (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
Private Declare Function RedrawWindow Lib “user32” (ByVal hwnd As Long, lprcUpdate As Any, ByVal hrgnUpdate As Long, ByVal fuRedraw As Long) As Long
End If

Private Const RDW_INVALIDATE As Long = &H1
Private Const RDW_UPDATENOW As Long = &H100

‘ ビューポートの強制再描画関数
Public Sub ForceViewportRefresh(ByVal acadApp As AcadApplication)
#If Win64 Then
Dim hCadWnd As LongPtr
#Else
Dim hCadWnd As Long
#End If

‘ AutoCADのメインフレームからドキュメントウィンドウ(AfxFrameOrView)を特定
hCadWnd = FindWindowEx(acadApp.hWnd, 0, “AfxFrameOrView”, vbNullString)

If hCadWnd <> 0 Then
Call RedrawWindow(hCadWnd, ByVal 0&, 0, RDW_INVALIDATE Or RDW_UPDATENOW)
End If
End Sub

このAPIを組み合わせることで、ユーザーがコマンドを起動した瞬間、ラグなく、かつ確実に「画面一杯の十字カーソル」が出現するプロフェッショナルなUI体験が完成する。

—

4. チーフアーキテクトからの提言:レガシーとモダンを繋ぐ保守の哲学

AutoCAD VBAは、現代の.NET API(ObjectARX / AutoCAD .NET API)全盛の時代にあっても、その「手軽さと即時性」において圧倒的な優位性を持っている。しかし、古い仕組みゆえにメモリ管理や環境依存の不具合を踏み抜くリスクも高い。

1. 例外処理における状態のデッドロック回避
今回紹介したように、設定値を変更する処理では、エラー発生時に元の値に戻らなくなる「状態の汚染」が最も恐ろしい。`On Error GoTo` を用いたクリーンアップブロック(`Finally` パターン)の徹底は、業務システムにおける鉄則である。
2. オブジェクトのスコープと解放
`ThisDrawing.Application` や `AcadApplication` をローカル変数に格納して使用する場合、プロシージャ終了時には必ず `Set xxx = Nothing` を明示し、COMコンポーネントの参照カウントを適切にデクリメントすること。

技術の本質は、単に動くコードを書くことではない。「どのような異常系であってもシステムを安全に元の状態へ復元できる堅牢性」を担保することにある。この十字カーソル制御の知見が、あなたの管理するCAD環境の生産性を極限まで引き上げる一助となることを確信している。

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