【スライドショー制御】”SlideShowWindow”オブジェクトをハック:実行中のスライドショー強制終了と特定スライドへの動的ジャンプ
PowerPoint VBAの領域において、静的なマクロの記録や、単なるプレゼンテーションの自動生成に終始しているうちは、まだ初級の域を出ない。真にシステムアーキテクトとしての手腕が問われるのは、「実行中のプレゼンテーション(Runtime)」に対するリアルタイムな介入と制御だ。
今回は、プレゼンテーションの最前線で動的にスライドショーをハックし、ユーザーの入力や外部システムからのシグナルに応じて、画面を意図したスライドへ強制ジャンプ、あるいは即時終了させるための極限の知見を公開する。
—
1. `SlideShowWindow` オブジェクトのライフサイクルと罠
多くの開発者が陥る最初の罠は、`Presentation` オブジェクトと `SlideShowWindow` オブジェクトの混同だ。
PowerPointのオブジェクトモデルにおいて、ファイル(実体)を表すのは `Presentation` であり、現在画面上でレンダリングされている「窓」を表すのは `SlideShowWindow` である。スライドショーが実行されていない状態では、`Presentation.SlideShowSettings` は存在しても、有効な `SlideShowWindow` はメモリ上に存在しない。
[Application]
└─ [Presentations(index)] (ファイルの実体)
└─ [SlideShowSettings] (設定)
└─ [SlideShowWindow] (描画ウィンドウ ※実行中のみ存在)
└─ [View] (現在のビューポート、スライド位置)
ここで重要となるのが、「スライドショー実行中のビューポートへの安全なアクセス」である。生半可なコードを書くと、ユーザーがESCキーを押した瞬間や、ウィンドウが非アクティブな状態のときに実行時エラー(エラー429や91)が多発する。
—
2. 実装:安全なスライドショー監視と動的ジャンプエンジン
以下のコードは、現在実行中のスライドショーウィンドウを捕捉し、エラーハンドリングを徹底した上で、任意のインデックスへダイレクトにジャンプ、あるいはセーフティに強制終了させるプロフェッショナル向けの実装例だ。
Option Explicit
‘ Windows API: 実行中のスライドショーウィンドウへ強制的にフォーカスを戻すための外部関数
If VBA7 Then
Declare PtrSafe Function SetForegroundWindow Lib “user32” (ByVal hwnd As LongPtr) As Long
Else
Declare Function SetForegroundWindow Lib “user32″ (ByVal hwnd As Long) As Long
End If
”’
”’
Public Sub HackSlideShow(ByVal targetSlideIndex As Long, Optional ByVal forceTerminate As Boolean = False)
Dim targetSSW As SlideShowWindow
Dim targetPres As Presentation
On Error GoTo ErrorHandler
‘ 1. 現在アクティブなスライドショーウィンドウが存在するか検証
Set targetSSW = GetActiveSlideShowWindow()
If targetSSW Is Nothing Then
MsgBox “現在実行中のスライドショーウィンドウが見つかりません。”, vbExclamation, “System Alert”
Exit Sub
End If
‘ 2. 親プレゼンテーションの取得とメモリ安全性の確保
Set targetPres = targetSSW.Presentation
‘ 3. 強制終了フラグが立っている場合の処理
If forceTerminate Then
‘ イベントを一時抑制してクローズ(パフォーマンス最適化)
Application.EnableEvents = False
targetSSW.View.Exit
GoTo CleanUp
End If
‘ 4. インデックスの境界値チェック(例外防止)
If targetSlideIndex < 1 Or targetSlideIndex > targetPres.Slides.Count Then
Err.Raise vbObjectError + 1000, “HackSlideShow”, “指定されたスライドインデックスは範囲外です: ” & targetSlideIndex
End If
‘ 5. 動的ジャンプの実行
‘ View.GotoSlide メソッドを使用することで、アニメーションのレンダリング状態を保持したまま遷移
targetSSW.View.GotoSlide Index:=targetSlideIndex, ResetSlide:=msoTrue
‘ 6. ウィンドウを最前面に強制アタッチ(API連携)
#If VBA7 Then
Dim hwnd As LongPtr
hwnd = targetSSW.hwnd
#Else
Dim hwnd As Long
hwnd = targetSSW.hwnd
#End If
If hwnd <> 0 Then
SetForegroundWindow hwnd
End If
CleanUp:
‘ オブジェクトの明示的解放(メモリリーク防止の鉄則)
Set targetSSW = Nothing
Set targetPres = Nothing
Application.EnableEvents = True
Exit Sub
ErrorHandler:
‘ 致命的なエラーのキャッチとクリーンアップ
Application.EnableEvents = True
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “Critical Error”
Resume CleanUp
End Sub
”’
”’
Private Function GetActiveSlideShowWindow() As SlideShowWindow
Dim ssw As SlideShowWindow
On Error Resume Next
‘ 実行中のショーが複数ある場合を考慮し、現在アクティブなものを特定
If Application.SlideShowWindows.Count > 0 Then
Set ssw = Application.SlideShowWindows(1)
‘ ウィンドウが有効かさらに検証
If ssw.View.State = ppSlideShowRunning Then
Set GetActiveSlideShowWindow = ssw
End If
End If
On Error GoTo 0
End Function
—
3. チーフアーキテクトが解説するコードの急所
A. `View.GotoSlide` と `ResetSlide` の挙動
`targetSSW.View.GotoSlide(Index, ResetSlide)` を呼び出す際、第2引数に `msoTrue` を指定することが極めて重要だ。
これを `msoFalse` にすると、ジャンプ先のスライドが過去に通過した際のアニメーション状態(途中で止まった状態など)を保持したまま描画されてしまい、プレゼンターが混乱する。システム制御による動的ジャンプでは、常に `msoTrue`(スライドを初期状態にリセットして描画)を選択するのが鉄則である。
B. `Application.EnableEvents` の制御
マクロからスライドショーの終了(`targetSSW.View.Exit`)を実行する際、余計なイベントトリガーが走るのを防ぐために一時的に `False` に設定している。これを怠ると、`PresentationClose` などのイベントが多重発火し、意図しないプロセス競合を引き起こす原因となる。
C. ウィンドウハンドル (`hwnd`) と Win32 API の活用
PowerPointの標準オブジェクトモデルだけでは、OSレベルでのウィンドウフォーカスの奪取に失敗する場合がある(特にマルチモニター環境や外部アプリケーション連携時)。
`SlideShowWindow.hwnd` からウィンドウハンドルを取得し、User32.dllの `SetForegroundWindow` を叩くことで、VBA側から強制的にユーザーの視線をターゲットスライドへ釘付けにすることが可能となる。
—
4. レガシー環境とシステム間連携への応用
この `SlideShowWindow` ハックの真価は、単体での動作にあるのではない。外部のCOMコンポーネント、C#製アドイン、あるいはTCP/IPソケット通信を介した外部システムからのリモート制御の基盤として機能する点にある。
例えば、工場内のセンサー異常検知システム(C#製)からCOM経由でこのVBAモジュールを叩き、`HackSlideShow(15, False)` のように特定の警告スライドへミリ秒単位でジャンプさせる――といったエンタープライズレベルのキオスク端末ソリューションを、PowerPoint単体で構築できる。
オブジェクトのライフサイクルを完全に理解し、メモリ管理とエラーハンドリングを極めた者だけが、VBAを「おもちゃのスクリプト」から「堅牢なミドルウェア」へと昇華させることができるのだ。コードの細部に宿る神を忘れるな。
