【テクニカル・上級編】【上級プロ向け】Windows APIを活用したCorelDRAWのウィンドウ完全非表示化(Invisible Mode)とバックグラウンド超高速一括フォーマット変換エンジン – CorelDRAW VBA解析バイブル

スポンサーリンク

【上級プロ向け】Windows APIを活用したCorelDRAWのウィンドウ完全非表示化(Invisible Mode)とバックグラウンド超高速一括フォーマット変換エンジン

CorelDRAW VBAにおける最大のボトルネックは、CADやDTPエンジンそのものではない。GUIの描画(画面更新)、イベントハンドラ、そしてリソースの無駄な浪費である。

数千点におよぶベクターアセットをバッチ処理でPDFやSVG、あるいはレガシーフォーマットへ変換する際、画面上にCorelDRAWのウィンドウを表示し、画面がチラつきながら1つずつ処理していくようなアプローチは、プロフェッショナルの現場においてはシステム障害と同義の悪手だ。

今回は、Windows API(User32.dll)をVBAから直接叩き、CorelDRAWのアプリケーションウィンドウそのものを完全に不可視(Invisible Mode)に沈めた状態で、描画オーバーヘッドを理論上の限界までゼロに削ぎ落とした「超高速一括フォーマット変換エンジン」の全貌を公開する。

1. 描画オーバーヘッドの正体とウィンドウ完全非表示化の理論

CorelDRAWは、COMオートメーションを通じて背後で操作している最中であっても、デフォルトでは内部のUIスレッドとウィンドウハンドル(`HWND`)がアクティブに描画サイクルを回している。

`Application.Visible = False` というプロパティも存在するが、これはCorelDRAWのドキュメントウィンドウを隠すに留まり、アプリケーション全体のウィンドウプロシージャやGDIの描画処理、イベントキューの処理完全には停止しない。そのため、大量ファイルを連続処理すると、OSのウィンドウマネージャーが描画の同期を取ろうとしてCPUサイクルを無駄に消費し、メモリリークの温床ともなる。

これを解決するのが、Windows API `ShowWindow` によるウィンドウハンドルの完全制御である。

CorelDRAW自身のプロセスから得られるメインウィンドウの `HWND` を特定し、OSレベルで `SW_HIDE`(非表示)を強制する。これにより、OSの描画エンジン(Desktop Window Manager)はCorelDRAWの存在を視覚的に完全に無視し、CPUリソースの100%を「純粋なベクター演算とファイルI/O」に集中させることが可能になる。

2. 実装アーキテクチャ:バックグラウンド超高速変換エンジン

以下のコードは、標準モジュールに配置するだけで即座に稼働する、プロダクションクオリティのバッチ変換エンジンである。
Windows APIの宣言、メモリの適正管理、そしてCorelDRAW特有のオブジェクトライフサイクルを考慮した堅牢な設計となっている。

Option Explicit

‘ ==============================================================================
‘ Windows API Declarations for Window Control
‘ ==============================================================================
If VBA7 Then
Private Declare PtrSafe Function FindWindowEx Lib “user32” Alias “FindWindowExA” (ByVal hWndParent As LongPtr, ByVal hWndChildAfter As LongPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr
Private Declare PtrSafe Function ShowWindow Lib “user32” (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Private Declare PtrSafe Function GetActiveWindow Lib “user32” () As LongPtr
Else
Private Declare Function FindWindowEx Lib “user32” Alias “FindWindowExA” (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
Private Declare Function ShowWindow Lib “user32” (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function GetActiveWindow Lib “user32” () As Long
End If

Private Const SW_HIDE As Long = 0
Private Const SW_SHOW As Long = 5

‘ ==============================================================================
‘ メイン処理:バックグラウンド一括フォーマット変換エントリーポイント
‘ ==============================================================================
Public Sub ExecuteInvisibleBatchConversion()
Dim sourceDir As String
Dim targetDir As String
Dim fso As Object
Dim folder As Object
Dim file As Object
Dim startTime As Double
Dim processedCount As Long

‘ 処理対象ディレクトリの設定(環境に合わせて変更してください)
sourceDir = “C:\VectorSource\”
targetDir = “C:\VectorOutput\PDF\”

Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(sourceDir) Then
MsgBox “ソースディレクトリが存在しません: ” & sourceDir, vbCritical
Exit Sub
End If
If Not fso.FolderExists(targetDir) Then fso.CreateFolder targetDir

startTime = Timer
processedCount = 0

‘ CorelDRAWの環境最適化(警告や画面更新の完全遮断)
With Application
.Optimization = True
.EventsEnabled = False
.StartupScriptDisabled = True
End With

‘ 【核心】CorelDRAWウィンドウの完全非表示化
Call SetCorelDrawVisibility(False)

‘ エラーハンドリングを有効化し、異常終了時も必ずウィンドウと環境を復元する
On Error GoTo ErrorHandler

Set folder = fso.GetFolder(sourceDir)
For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “cdr” Then
If ProcessSingleFile(file.Path, targetDir, fso) Then
processedCount = processedCount + 1
End If
End If
Next file

ErrorHandler:
‘ ==============================================================================
‘ クリーンアップ & 復元処理(メモリリーク・ゾンビプロセスの防止)
‘ ==============================================================================
On Error Resume Next

‘ ウィンドウを可視状態に戻す
Call SetCorelDrawVisibility(True)

With Application
.EventsEnabled = True
.Optimization = False
.Refresh
End With

Set file = Nothing
Set folder = Nothing
Set fso = Nothing

If Err.Number <> 0 Then
MsgBox “バッチ処理中にエラーが発生しました: ” & Err.Description, vbCritical
Else
MsgBox “一括変換が完了しました。” & vbCrLf & _
“処理ファイル数: ” & processedCount & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation
End If
End Sub

‘ ==============================================================================
‘ CorelDRAWウィンドウの可視性をAPIで制御するプロシージャ
‘ ==============================================================================
Private Sub SetCorelDrawVisibility(ByVal makeVisible As Boolean)
Dim hwndApp As LongPtr
Dim cmdShow As Long

If makeVisible Then
cmdShow = SW_SHOW
Else
cmdShow = SW_HIDE
End If

‘ CorelDRAWのメインフレームウィンドウハンドルを取得
‘ ※CorelDRAWのクラス名はバージョンにより異なる場合があります(CDRXX Main Frame等)
hwndApp = Application.Handle

If hwndApp <> 0 Then
ShowWindow hwndApp, cmdShow
End If
End Sub

‘ ==============================================================================
‘ 単一ファイルの極限最適化コンバージョン処理
‘ ==============================================================================
Private Function ProcessSingleFile(ByVal inputPath As String, ByVal outputPathRoot As String, ByRef fso As Object) As Boolean
Dim doc As Document
Dim exportPath As String
Dim baseName As String
Dim expFilter As ExportFilter

ProcessSingleFile = False

On Error GoTo CleanUp

‘ ドキュメントのサイレントオープン(UIイベントを発生させない)
Set doc = Application.OpenDocument(inputPath)

baseName = fso.GetBaseName(inputPath)
exportPath = outputPathRoot & baseName & “.pdf”

‘ PDFエクスポートフィルターの設定と実行(メモリ効率を意識した最小限の設定)
Set expFilter = doc.ExportMS(exportPath, cdrPDF, cdrCurrentPage)
With expFilter
.Finish
End With

ProcessSingleFile = True

CleanUp:
‘ オブジェクトの明示的解放とガベージコレクション的アプローチ
If Not doc Is Nothing Then
doc.Close
Set doc = Nothing
End If
Set expFilter = Nothing

Exit Function
End Function

3. シニアエンジニアが押さえるべき設計上のキモ

1. `Application.Handle` と APIの協調

CorelDRAW VBAでは、オブジェクトモデルから `.Handle` プロパティ(または親ウィンドウのポインタ)にアクセスできる。これを `ShowWindow` に渡すことで、外部のEXEを操作するような煩雑な `FindWindow` のプロセス名探索をバイパスし、確実かつ高速に自身のウィンドウハンドルを隠蔽できる。

2. 例外発生時の「ゾンビプロセス」および「隠し画面」の回避

バックグラウンド処理において最も恐ろしいのは、ループの途中で予期せぬエラー(破損したCDRファイル、メモリ不足など)が発生し、処理が中断したままExcelやCorelDRAWが裏でゾンビとして生き続けること、あるいはウィンドウが非表示のままハングアップしてユーザーが操作不能になることだ。
上記コードでは `On Error GoTo ErrorHandler` を厳格に実装し、いかなる例外が起なかろうとも必ず `ShowWindow(…, SW_SHOW)` と `.Optimization = False` が実行されるフェイルセーフ構造にしている。

3. メモリの明示的解放とドキュメントのライフサイクル

数千ファイルを扱うループ処理において、`Set doc = Application.OpenDocument(…)` の開放漏れは致命的なメモリリークを引き起こす。
CorelDRAWの内部エンジンはCOMオブジェクトの参照カウント管理が厳密であるため、ループの1イテレーションが終わるごとに `doc.Close` を呼び出し、ローカル変数 `doc` および `expFilter` に `Nothing` を代入してメモリプレッシャーを即座に解放することが、長時間稼働するバッチシステムの必須条件となる。

4. 総括:レガシーの皮を被ったハイパフォーマンス・エンジニアリング

CorelDRAW VBAは、しばしば「古い技術」「限定的なマクロ言語」と過小評価される。しかし、Windowsのアーキテクチャ、APIのメモリモデル、そしてCOMのライフサイクルを完全に理解したエンジニアが手を入れたVBAは、C++やC#でゼロからWin32アプリケーションを書く工数と比較しても、圧倒的な開発スピードと遜色ない実行パフォーマンスを叩き出す。

画面を描画しない。イベントを処理しない。リソースを溜め込まない。
この「Invisible Mode」を取り入れたバッチエンジンは、あなたのデスクトップ環境を、夜間に何千ものアセットを静かに、そして暴力的なまでの速度で処理し尽くす、無音の超高効率プラントへと変貌させるだろう。

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