トップ > 備忘録 > Windowハンドルの取得

Windowハンドルの取得2012.11.19   [更新日]2024.12.14

ウィンドウハンドルとはWindows(OS)が各ウィンドウに割り振る管理番号で、ウィンドウを識別するための識別子です。
Win32APIなどを用い、ウィンドウを指定して何らかの処理を行う場合、必ずウィンドウのハンドルが必要になります。
ウィンドウハンドルを指定することで、コンピュータに該当のウィンドウを認識させることができます。

ここでは、様々な方法で各種のウィンドウハンドルを取得する、サンプルコードとメモを記載します。

メモの内容

プロパティ
 ・Application.Hwndプロパティ

Win32API① Windowハンドルの取得
 ・GetDesktopWindow関数
 ・GetActiveWindow関数
 ・FindWindow関数
 ・FindWindowEx関数
 ・GetParent関数
 ・GetWindow関数
 ・WindowFromPoint関数

Win32API② クラス名・Windowテキストの取得
 ・GetClassName関数
 ・GetWindowText関数


関連コード

ウィンドウのハンドルをまとめて取得するサンプルコード:ウィンドウのハンドル・クラス名一覧を作成する


【お薦め】マクロ・プロシージャを管理する無料のツール!
 Excelマクロ管理ツール


プロパティを用いたウィンドウハンドル取得のサンプルコード

Application.Hwndプロパティ

Excelの最上位のウィンドウ ハンドルをLong型の値で返す。値の取得のみ可能。
Excel2002で追加されたプロパティであるため、Excel2000以前では使用できない。

Sub Excelアプリケーションウィンドウハンドル表示()
    Dim hdlAppWindow As LongPtr
    hdlAppWindow = Excel.Application.Hwnd
    
    MsgBox hdlAppWindow, , "Excel.Application.Hwnd"

End Sub


Win32APIを用いたウィンドウハンドル取得のサンプルコード

次からは、ハンドルを取得するためのWin32API関数である。
VBAでWin32APIを宣言する場合、「宣言セクション」(各モジュールの最上部)に記述しなければならない。
これら関数の返り値は、関数が成功するとハンドル番号、失敗すると「0」を返す。
※ 以後のコードはExcel2010以降に対応

GetDesktopWindow関数

デスクトップのウィンドウハンドルを取得
[参考]Microsoft Learn Challenge GetDesktopWindow関数

'《デスクトップ ウィンドウへのハンドルを取得する》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getdesktopwindow
Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr

Sub デスクトップウィンドウハンドル取得例() Dim hdlDesktop As LongPtr hdlDesktop = GetDesktopWindow() MsgBox hdlDesktop, , "GetDesktopWindow()" End Sub

GetActiveWindow関数

アクティブになっているウィンドウハンドルの取得
[参考]Microsoft Learn Challenge GetActiveWindow関数

'《アクティブなウィンドウのウィンドウハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getactivewindow
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr

Sub アクティブウィンドウハンドル取得例() Dim hdlDesktop As LongPtr hdlDesktop = GetActiveWindow() MsgBox hdlDesktop, , "GetActiveWindow()" End Sub

FindWindow関数

クラス名やウィンドウの名前からウィンドウハンドルを取得
[参考]Microsoft Learn Challenge FindWindow関数

'《クラス名とウィンドウ名が指定した文字列と一致する最上位ウィンドウへのハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindowa
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
                                        ByVal lpClassName As String, _
                                        ByVal lpWindowName As String) As LongPtr

Sub クラス名やウィンドウ名によるウィンドウハンドル取得例() '《代表的なアプリケーションのクラス名》 ' Excel :XLMAIN ' Word :OpusApp ' PowerPoint :PPTFrameClass ' Access :OMain ' Edge :Chrome_WidgetWin_1 ' Visual Basic Editor:wndclass_desked_gsk ' メモ帳 :Notepad ' ペイント :MSPaintApp ' 電卓 :SciCalc '---------------------------------------- ' クラス名からウィンドウハンドル取得 '---------------------------------------- Dim hdlTargetWindow As LongPtr ' Excelのクラス名からハンドル取得 hdlTargetWindow = FindWindow("XLMAIN", vbNullString) MsgBox hdlTargetWindow, , "FindWindow():クラス名" '---------------------------------------- ' ウィンドウ名からウィンドウハンドル取得 '---------------------------------------- ' Excelアプリケーションのウィンドウ名からハンドル取得 hdlTargetWindow = FindWindow(vbNullString, Application.Caption) MsgBox hdlTargetWindow, , "FindWindow():ウィンドウ名" End Sub

FindWindow 関数の引数は以下の2つ
 lpClassName :クラス名
 lpWindowName :ウィンドウ名
引数は省略不可。指定しない場合はvbNullString(空の文字列)で対応する。
2つの引数を共にvbNullStringにした場合は、最前面のWindowのハンドルを取得する。

クラス名取得の参考:ウィンドウのハンドル・クラス名一覧を作成する


FindWindowEx関数

親ウィンドウを基準に、クラスやウィンドウの名前から子ウィンドウのハンドルを取得
[参考]Microsoft Learn Challenge FindWindowEx関数

'《親のウィンドウハンドルを基にクラス名やウィンドウ名に一致する子のウィンドウハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindowexw
Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
                                        ByVal hwndParent As LongPtr, _
                                        ByVal hwndChildAfter As LongPtr, _
                                        ByVal lpClassName As String, _
                                        ByVal lpWindowName As String) As LongPtr

Sub クラス名またはウィンドウ名から子ウィンドウハンドル取得例() '---------------------------------------- ' 親ウィンドウハンドル取得(Excel) '---------------------------------------- Dim hdlParentWindow As LongPtr hdlParentWindow = Application.Hwnd '---------------------------------------- ' Excelのクライアント領域のウィンドウハンドル取得 '---------------------------------------- Dim hdlChildWindow As LongPtr ' FindWindowEx ' ・ 引数1:親ウィンドウハンドル ' ・ 引数2:検索を開始する子のウィンドウハンドル(指定したウィンドウの次のウィンドウから検索開始) ' ・ 引数3:検索する子ウィンドウのクラス名 ' ・ 引数4:検索する子ウィンドウ名 hdlChildWindow = FindWindowEx(hdlParentWindow, 0, "XLDESK", vbNullString) MsgBox hdlChildWindow, , "FindWindowEx():子クラス名" End Sub

FindWindow 関数の引数は以下の4つ
 hwndParent  :親Windowのハンドル
 hwndChildAfter:検索を開始する子Windowのハンドル(指定したウィンドウのZオーダーの次のウィンドウから検索開始)。
         「0」の場合、最初の子Windowから検索
 lpClassName :検索対象の子のクラス名。指定しない場合はvbNullString(空の文字列)で対応する。
 lpWindowName:検索対象の子のウィンドウ名。指定しない場合はvbNullString(空の文字列)で対応する。


GetParent関数

子ウィンドウを基準に、その親ウィンドウのハンドルを取得する
[参考]Microsoft Learn Challenge GetParent関数

'《指定したウィンドウの親または所有者へのハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getparent
Declare PtrSafe Function GetParent Lib "user32" (ByVal hwnd As LongPtr) As Long

'《親のウィンドウハンドルを基にクラス名やウィンドウ名に一致する子のウィンドウハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindowexw
Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
                                        ByVal hwndParent As LongPtr, _
                                        ByVal hwndChildAfter As LongPtr, _
                                        ByVal lpClassName As String, _
                                        ByVal lpWindowName As String) As LongPtr

Sub 子ウィンドウハンドルから親ウィンドウハンドル取得例() '---------------------------------------- ' 子ウィンドウハンドル取得 '---------------------------------------- Dim hdlChildWindow As LongPtr ' Excelのクライアント領域のウィンドウハンドル取得 hdlChildWindow = FindWindowEx(Application.hwnd, 0, "XLDESK", vbNullString) MsgBox "子ウィンドウハンドル:" & hdlChildWindow, , "FindWindowEx():クライアント領域" '---------------------------------------- ' 親ウィンドウハンドル取得 '---------------------------------------- Dim hdlParentWindow As LongPtr hdlParentWindow = GetParent(hdlChildWindow) ' アプリケーションのハンドルと子ウィンドウから取得した親ウィンドウのハンドル比較 MsgBox "Application.hwnd:" & Application.hwnd & vbLf & _ "GetParent():" & hdlParentWindow, , "GetParent()" End Sub

VBAコードをカラーで印刷・Web掲載するためのツールはこちら


書籍紹介本を執筆しました

知りたいがすぐわかる! やりたいがすぐできる!
「Excel VBA 逆引きで学ぶ ユーザーフォーム&コントロール」(Kindle版)
ユーザーフォームを扱えると、VBAでできることが大きく広がります!
本書では、知りたいこと、やりたいことから、逆引きで学びを深められます。
※ 第1章~5章まで公開しています


GetWindow関数

あるウィンドウを基準に、そのウィンドウと関連のある他の任意のウィンドウハンドルを取得する
[参考]Microsoft Learn Challenge GetWindow関数

'《指定したウィンドウと関連するウィンドウのハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getwindow
Declare PtrSafe Function GetWindow Lib "user32" ( _
                                    ByVal hwnd As LongPtr, _
                                    ByVal uCmd As Long) As LongPtr

'《引数2 uCmd に指定するパラメーター》
Const GW_HWNDFIRST As Long = 0  ' 基準となるWindowと同じ種類のうち最前面のWindow
Const GW_HWNDLAST  As Long = 1  ' 基準となるWindowと同じ種類のうち最背面のWindow
Const GW_HWNDNEXT  As Long = 2  ' 基準となるWindowの次のWindow
Const GW_HWNDPREV  As Long = 3  ' 基準となるWindowの前のWindow
Const GW_OWNER     As Long = 4  ' 基準となるWindowのオーナーWindow
Const GW_CHILD     As Long = 5  ' 基準となるWindowの子WindowのうちトップレベルのWindow

Sub 指定したウィンドウと関連のあるウィンドウハンドル取得例() '---------------------------------------- ' Excelの最上位親ウィンドウハンドル取得 '---------------------------------------- Dim hdlParentWindow As LongPtr hdlParentWindow = Application.hwnd '---------------------------------------- ' Excelと関連するトップレベルの子ウィンドウハンドル取得 '---------------------------------------- Dim hdlTargetWindow As LongPtr hdlTargetWindow = GetWindow(hdlParentWindow, GW_CHILD) MsgBox hdlTargetWindow, , "GetWindow()" End Sub

FindWindow 関数の引数は以下の2つ
 hwnd:基準となるウィンドウのハンドル
 uCmd:どのような検索コマンドを実行するかを指定。パラメーターを使用。


WindowFromPoint関数

画面の指定した座標位置のウィンドウのハンドルを取得する
マウスカーソルの座標位置を取得する GetCursorPos関数 とあわせて記載する
※マウスカーソルの座標取得をマクロ実行の3秒後に実行するように、Application.OnTimeメソッドを用いている

[参考]Microsoft Learn Challenge WindowFromPoint関数
    Microsoft Learn Challenge GetCursorPos 関数
    Microsoft Learn Challenge Application.OnTime メソッド

' ***(宣言セクションに記述)***
'-------------------------------------
' Win32API
'-------------------------------------
'《マウス カーソルの位置を画面座標で取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getcursorpos
Declare PtrSafe Function GetCursorPos Lib "user32" ( _
                                        ByRef lpPoint As POINTAPI) As Long

'《指定したポイントを含むウィンドウのハンドルを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-windowfrompoint
Declare PtrSafe Function WindowFromPoint Lib "user32" ( _
                                        ByVal x As Long, _
                                        ByVal y As Long) As LongPtr
'-------------------------------------
' 構造体
'-------------------------------------
' GetCursorPos 関数 の引数として使用
Type POINTAPI
   x As Long
   y As Long
End Type
' ***(ここまで)***

'----------------------------------------------------------------- ' 実行用マクロ '----------------------------------------------------------------- Sub マウスカーソル位置のウィンドウを取得() MsgBox "[OK]ボタンをクリックして 3 秒後のマウスカーソル位置の" & vbLf & _ "Windowのハンドルを取得します", vbInformation ' 3秒後にプロシージャ「マウスカーソルの位置のウィンドウを取得」を実行する Application.OnTime Now() + TimeValue("00:00:03"), "マウスカーソルの位置のウィンドウを取得" End Sub
Private Sub マウスカーソルの位置のウィンドウを取得() '---------------------------------------- ' マウスカーソルの位置を画面座標で取得 '---------------------------------------- Dim typPointapi As POINTAPI Call GetCursorPos(typPointapi) '---------------------------------------- ' マウスカーソル位置のウィンドウのハンドルを取得 '---------------------------------------- Dim hdlFromPoint As LongPtr hdlFromPoint = WindowFromPoint(typPointapi.x, typPointapi.y) MsgBox hdlFromPoint, , "WindowFromPoint()" End Sub

WindowFromPoint 関数の引数は以下の2つである(※)
 x:画面の x 座標
 y:画面の y 座標

(※)WindowFromPoint 関数の引数
Office64bit版で WindowFromPoint関数を使用する場合に POINT 構造体を引数とする方法が推奨されているが、ここではOffice32bit版・64bit版の両方で動作することを優先している。
POINT 構造体を使用する方法は、Microsoft提供ページ「Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support」からダウンロードできるファイル内の「Win32API_PtrSafe.TXT」に記載されている。

「Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support」で「Download」をクリックすると「Office2010Win32API_PtrSafe.exe」がダウンロードされる。
インストールすると、Cドライブの直下に「Office 2010 Developer Resources」フォルダが生成される。
そのフォルダの配下に「Win32API_PtrSafe.TXT」が存在する。


Win32APIを用いたウィンドウのクラス名・テキスト取得のサンプルコード

GetClassName関数

指定したウィンドウが属するクラスの名前を取得
[参考]Microsoft Learn Challenge GetClassName関数

'《指定したウィンドウが属するクラスの名前を取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getclassname
Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
                                        ByVal hwnd As LongPtr, _
                                        ByVal lpClassName As String, _
                                        ByVal nMaxCount As LongPtr) As Long

Sub ウィンドウハンドルからクラス名を取得() '---------------------------------------- ' Excelアプリケーションのハンドル取得 '---------------------------------------- Dim hdlApp As LongPtr hdlApp = Application.hwnd '---------------------------------------- ' クラス名取得 '---------------------------------------- ' クラス名がコピーされるバッファーを固定長文字列として宣言 Dim strClassName As String * 100 ' GetClassName ' ・ 引数1:対象のウィンドウハンドル ' ・ 引数2:クラス名を受け取るバッファー(固定長文字列で指定) ' ・ 引数3:引数2のバッファーの文字数 ' 戻り値 :成功した場合は 引数2 にコピーされた文字数 ' 失敗した場合は 0 Call GetClassName(hdlApp, strClassName, Len(strClassName)) MsgBox strClassName, , "クラス名" End Sub

クラス名取得の参考:ウィンドウのハンドル・クラス名一覧を作成する


GetWindowText関数

指定したウィンドウのタイトル バーにテキストがある場合 そのテキストを取得
[参考]Microsoft Learn Challenge GetWindowText関数

'《指定したウィンドウのテキストを取得》
' https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getwindowtexta
Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
                                        ByVal hwnd As LongPtr, _
                                        ByVal lpString As String, _
                                        ByVal nMaxCount As Long) As Long

Sub ウィンドウハンドルからウィンドウテキストを取得() '---------------------------------------- ' Excelアプリケーションのハンドル取得 '---------------------------------------- Dim hdlApp As LongPtr hdlApp = Application.hwnd '---------------------------------------- ' クラス名取得 '---------------------------------------- ' ウィンドウテキストがコピーされるバッファーを固定長文字列として宣言 Dim strWindowText As String * 100 ' GetWindowText ' ・ 引数1:対象のウィンドウハンドル ' ・ 引数2:テキストを受け取るバッファー(固定長文字列で指定) ' ・ 引数3:引数2のバッファーの文字数 ' 戻り値 :成功した場合は 引数2 にコピーされた文字数 ' 失敗した場合は 0 Call GetWindowText(hdlApp, strWindowText, Len(strWindowText)) MsgBox strWindowText, , "ウィンドウテキスト" End Sub

ページトップへ戻る
Copyright(C) 2009- 坂江 保 All Rights Reserved.