【VBA×WindowsAPI】GetParent関数の使い方
GetParent関数
GetParent関数は指定したウィンドウの親ウィンドウのハンドルを取得するための関数です。
Windowsのウィンドウにはそれぞれを識別するためにウィンドウハンドルというものが設定されており、WindowsAPIではこのウィンドウハンドルを使うことで任意のウィンドウに対して何らかの操作を行うことを可能にしています。ウィンドウハンドルはSpy++等の専用のツールを使うことで調べることができ、下画像のように親子の関係を持ったツリー構造になっています。
上記のようなツリー構造において指定のウィンドウの子どもにあたるウィンドウのハンドルを取得したい場合はFindWindowEx関数を使いますが、これとは逆に指定のウィンドウの親にあたるウィンドウのハンドルを取得したい場合にGetParent関数を使います。
GetParent関数は指定のウィンドウの親を取得する関数ですが、指定のウィンドウがポップアップウィンドウの場合、親ではなくそのウィンドウの所有者となるウィンドウのハンドルが取得できます。ポップアップウィンドウの定義としてはウィンドウスタイルにWS_POPUPが含まれているウィンドウです。ウィンドウスタイルはハンドルと同じくSpy++等の専用ツールで確認することができます。
定義だとわかりづらいですが、ポップアップウィンドウとは簡単にいえばアプリケーション内でアプリケーションウィンドウとは別に新たに表示されるウィンドウのことです。たとえばExcelでいうと「検索と置換」ウィンドウや「セルの書式設定」ウィンドウ、UserFormなどがこれにあたります。
使用方法
GetParent関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function GetParent Lib “user32” (ByVal hwnd As LongPtr) As LongPtr
Declare Function GetParent Lib “user32” (ByVal hwnd As Long) As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function GetParent Lib "user32" (ByVal hwnd As LongPtr) As LongPtr #Else Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
GetParent関数の構文は下記のように書きます。
hWndParent = GetParent(hWnd)
引数
hWnd (64bit:LongPtr型 / 32bit:Long型)
親ウィンドウのハンドルを取得するウィンドウのハンドルを入力します。
ウィンドウハンドルを取得するための関数としてFindWindow関数やFindWindowEx関数、GetActiveWindow関数など様々なものがあります。環境によって引数の型が変わるので注意が必要です。
戻り値
hWndParent (64bit:LongPtr型 / 32bit:Long型)
戻り値は引数に入力されたウィンドウの親のウィンドウハンドルです。
入力されたウィンドウハンドルがポップアップウィンドウ(ウィンドウスタイルにWS_POPUPを持つウィンドウ)の場合、親ではなくそのウィンドウの所有者となるウィンドウのハンドルが返されます。
サンプルコード
以下はGetParent関数とFindWindow関数、GetWindowText関数を使って、UserFormのウィンドウハンドルからアプリケーションのウィンドウハンドルを取得して、アプリケーションウィンドウのキャプション(ウィンドウ名)を取得するサンプルコードです。下記コードをUserFormのコードにコピーペーストしてからUserFormを表示すれば、Initializeイベントが走りアプリケーションのキャプションを取得してイミディエイトウィンドウに出力するされます。
UserFormはウィンドウスタイルにWS_POPUPを持つポップアップウィンドウのため、所有者つまりはアプリケーション(Excel等)のウィンドウハンドルが取得されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function GetParent Lib "user32" (ByVal hWnd As LongPtr) As LongPtr Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long Private Sub UserForm_Initialize() Dim hWnd As LongPtr Dim hWndParent As LongPtr Dim lRet As LongPtr Dim sBuf As String * 100 Dim sCap As String 'UserFormのウィンドウハンドルを取得 hWnd = FindWindow(vbNullString, Me.Caption) 'UserFormの所有者ウィンドウのハンドルを取得 hWndParent = GetParent(FindWindow(vbNullString, Me.Caption)) '取得したハンドルのウィンドウ名を取得(固定長文字列) lRet = GetWindowText(hWndParent, sBuf, Len(sBuf)) '不要なバッファ分は削除 sCap = Left(sBuf, InStr(sBuf, vbNullChar) - 1) '取得したウィンドウ名をイミディエイトウィンドウに出力 Debug.Print sCap End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:GetParent 関数 (winuser.h) – Win32 apps