【Excel VBA】EnumWindows()によるウィンドウの列挙(コールバック関数とフォーム作成を試す)
Excel VBAからWindows APIの EnumWindows() を利用して、現在起動しているすべてのトップレベルウィンドウのハンドルとタイトルを列挙する方法を解説します。
古いVB5用のサンプルコードやリンク切れとなった配布ファイルに頼らず、現在の64bit版を含むExcel環境でも安全に動作するコードと手順を再構成しました。
1. この記事で何ができるか
VBAの標準機能だけでは取得できない、Windows上の他アプリケーションのウィンドウ一覧(タイトルとウィンドウハンドル)を取得し、イミディエイトウィンドウに出力することができます。
2. 想定環境・前提条件
- 動作確認環境: Microsoft Excel (32bit / 64bit 環境両対応)
- OS: Windows 10 / 11
- 前提知識: VBAの標準モジュール、ユーザーフォーム、および
AddressOf演算子の基本的な知識
3. 完全なコード
ウィンドウ列挙を行うためには、標準モジュールにAPIの宣言とコールバック関数を記述し、フォームや別の標準モジュールから呼び出します。
標準モジュール (例: Module1)
Option Explicit
' 64bitおよび32bit環境に対応したAPI宣言
#If VBA7 Then
Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
Declare PtrSafe Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthW" (ByVal hwnd As LongPtr) As Long
Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextW" (ByVal hwnd As LongPtr, ByVal lpString As LongPtr, ByVal nMaxCount As Long) As Long
Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As LongPtr) As Long
#Else
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
#End If
' コールバック関数(EnumWindowsから呼び出される)
#If VBA7 Then
Public Function EnumWindowsProc(ByVal hwnd As LongPtr, ByVal lParam As LongPtr) As Long
#Else
Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
#End If
Dim lLength As Long
Dim sTitle As String
' 表示されているウィンドウのみ対象とする場合
If IsWindowVisible(hwnd) Then
lLength = GetWindowTextLength(hwnd)
If lLength > 0 Then
sTitle = Space$(lLength + 1)
#If VBA7 Then
GetWindowText hwnd, StrPtr(sTitle), lLength + 1
#Else
GetWindowText hwnd, sTitle, lLength + 1
#End If
sTitle = Left$(sTitle, lLength)
' タイトルが存在する場合はイミディエイトウィンドウに出力
If Trim$(sTitle) <> "" Then
Debug.Print "HWnd: " & hwnd & " | Title: " & sTitle
End If
End If
End If
' 列挙を継続するためには 1 (True) を返す
EnumWindowsProc = 1
End Function
' 実行用プロシージャ
Public Sub StartEnumWindows()
Debug.Print "--- ウィンドウ列挙開始 ---"
' AddressOf を用いてコールバック関数のアドレスを渡す
EnumWindows AddressOf EnumWindowsProc, 0
Debug.Print "--- ウィンドウ列挙終了 ---"
End Sub
4. 実行手順
- Excelを開き、
Alt + F11キーを押してVBE(Visual Basic Editor)を起動します。 - メニューの [挿入] > [標準モジュール] をクリックして新規モジュールを追加します。
- 上記のコードをすべて貼り付けます。
- VBE上で
StartEnumWindowsプロシージャ内にカーソルを置き、F5キー(または上部の再生ボタン)を押して実行します。 Ctrl + Gキーを押してイミディエイトウィンドウを開き、出力されたウィンドウ一覧を確認します。
5. 期待される結果
イミディエイトウィンドウに以下のような形式で、現在起動しているウィンドウのハンドルとタイトルが表示されます。
--- ウィンドウ列挙開始 ---
HWnd: 131252 | Title: 予約語・関数名 - Microsoft Visual Basic for Applications
HWnd: 66324 | Title: 検索 - Google Chrome
--- ウィンドウ列挙終了 ---
6. トラブルシューティング・注意点
- ポインタサイズの差異 (VBA7 / 64bit対応): 64bit版Excelを使用する場合、ウィンドウハンドル (HWND) は
LongPtr型として扱う必要があります。古い32bit専用コードをそのまま動かすとVBEが強制終了(クラッシュ)する原因になりますので、上記のように条件付きコンパイル(#If VBA7 Then)を使用してください。 - 無限ループやクラッシュを防ぐ注意: コールバック関数内でエラーが発生するとExcel全体がフリーズ・強制終了するリスクがあります。デバッグ中はこまめにファイルを保存してください。
この記事の更新履歴
この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。
2026年9月26日
- 削除リンク切れとなっている古い外部ZIPファイルのダウンロードリンクを削除しました。
- 追加EnumWindows関数とコールバック処理を用いたウィンドウ列挙の完全なVBAサンプルコードと実行手順を追加しました。
