【VBA×WindowsAPI】GetActiveWindow関数の使い方
GetActiveWindow関数
GetActiveWindow関数は現在アクティブなウィンドウへのハンドルを取得するための関数です。
ウィンドウハンドルとは、ウィンドウを識別するための特別な識別子です。
ウィンドウを開いたり閉じたり、移動させたり、サイズを変えたり、テキストを変更したりするなど、ウィンドウに対して行いたい様々な操作を指示する際に使用します。このウィンドウに対する操作もWindowAPIに用意されている何種類もの関数で行うことが可能です。
ウィンドウハンドルはC++では「HWND型」という型で扱いますが、中身としては長整数型の値であるためVBAではLongPtr型(32bitではLong型)を使用します。VBAでウィンドウハンドルを格納する変数はC++の型に合わせてhWndなどと記載することが多いです。
ウィンドウハンドルは、ウィンドウが作成されるときに自動的に割り当てられます。
そして、そのウィンドウが存在している間は一貫して有効ですが、ウィンドウが閉じられると無効になります。つまりハンドルを取得すると毎回値が違うウィンドウも存在するということです。
VBAにおいてはUserFormもウィンドウであるため、たとえばUserFormを最前面に移動させたり、サイズを変更できるようにしたり、半透明にしたりと様々な操作を行うことが可能になります。このとき、その操作の対象となるUserFormへのハンドルを取得するための関数がGetActiveWindow関数という訳です。この他にもFindWindow関数やGetNextWindow関数、GetParent関数といったウィンドウハンドルを取得するための関数は何種類も存在します。
GetActivewindow関数は処理が行われた”瞬間”にアクティブなウィンドウのハンドルを取得するのです。そのためマクロをVBE上で実行するとVBEのウィンドウハンドルが、Excelブック上から実行するとExcelのウィンドウハンドルが取得されます。(つまりVBAにおいてはあまり汎用性はない)
UserFormのウィンドウハンドルを取得したい場合、UserFormの「Initializeイベント」にGetActivewindow関数を記載してもUserFormが表示される前(アクティブになる前)に処理が流れてしまうためハンドルは取得できません。UserFormのウィンドウハンドルを取得するには「Initializeイベント」が流れてUserFormが画面に表示された後にGetActivewindow関数を実行する必要があります。
使用方法
GetActivewindow関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function GetActiveWindow Lib “user32” () As LongPtr
Declare Function GetActiveWindow Lib “user32” () As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr #Else Declare Function GetActiveWindow Lib "user32" () As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
GetActivewindow関数の構文は下記のように書きます。
hwnd = GetActivewindow()
戻り値
hwnd (64bit:LongPtr型 / 32bit:Long型)
戻り値は現在アクティブなウィンドウのハンドルです。
プログラム上でマルチスレッド(並行処理)をする場合は、関数が呼び出された側に関連付けられているアクティブウィンドウのハンドルを返しますが、VBAマクロにおいてはマルチスレッドの考えは基本的には不要です。アクティブウィンドウが存在しない場合はNULL値(0)が返されます。
ウィンドウハンドルは開発(実行)環境によって戻り値の型が変化するので注意が必要です。
サンプルコード
以下はGetActiveWindow関数とGetWindowText関数を使って、アクティブウィンドウのキャプション名を取得するサンプルコードです。VBEから実行した場合はVBEのウィンドウのキャプションが、Excelブック上から実行した場合はそのExcelブックのキャプションがイミディエイトウィンドウに出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long Sub main() Dim hwnd As LongPtr Dim lRet As LongPtr Dim sBuf As String * 100 Dim sCap As String 'アクティブウィンドウのハンドルを取得 hwnd = GetActiveWindow '取得したハンドルのクラス名を取得(固定長文字列) lRet = GetWindowText(hwnd, sBuf, Len(sBuf)) '不要なバッファ分は削除 sCap = Left(sBuf, InStr(sBuf, vbNullChar) - 1) '取得したクラス名をイミディエイトウィンドウに出力 Debug.Print sCap End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:GetActiveWindow function (winuser.h) – Win32 apps