【VBA×WindowsAPI】GetWindowLongPtr関数の使い方
GetWindowLongPtr関数
GetWindowLongPtr関数は指定したウィンドウに関する情報を取得するための関数です。
WinAPIにはGetWindowLong関数という同じ機能を持つ関数が存在しますが、GetWindowLongPtr関数はこのGetWindowLong関数を64bit/32bitの両環境で使えるようにしたものです。
ウィンドウに関する情報として、指定のウィンドウのウィンドウスタイルや拡張ウィンドウスタイル、関連付いたウィンドウのハンドルなどを取得することができます。
ウィンドウスタイルとはウィンドウの見た目や動作の基本的なスタイルのことで、例えばウィンドウの枠線やタイトルバー、最大化/最小化ボタンの有無などがこれにあたります。拡張ウィンドウスタイルとはさらに応用的なウィンドウスタイルのことで、ドラッグ&ドロップ操作の機能やウィンドウの右側スクロールバー(ブラウザのような)の有無などがこれにあたります。
ウィンドウは起動時に各アプリケーションで指定されたウィンドウスタイルを持って起動されます。VBAのUserFormのデフォルト時のウィンドウスタイルと拡張ウィンドウスタイルは下画像の通りです。たとえば「WS_CAPTION」はタイトルバーが有ることを表し、「WS_EX_LEFT」は左揃えのプロパティを持っていることを表します。(詳しくは上記ウィンドウスタイルのリンクを参照)
GetWindowLongPtr関数とは対の存在となるSetWindowLongPtr関数を使うことで、このウィンドウスタイル/拡張ウィンドウスタイルを追加したり除去したりすることができます。このとき、現状のウィンドウスタイルはそのままで新たに追加したいという場合に、現状のウィンドウスタイルを取得する必要があります。このときに利用されるのがGetWindowLongPtr関数です。
ウィンドウスタイル以外にもいくつか取得できる情報がありますが、VBAで利用する際はUserFormのウィンドウスタイル/拡張ウィンドウスタイルを操作して本来のUserFormではできないことを可能にすることに利用したりします。(UserFormの透明化、ウィンドウ最大化/最小化ボタンの追加など)
使用方法
GetWindowLongPtr関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。
使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。
Declare PtrSafe Function GetWindowLongPtr Lib “user32” Alias “GetWindowLongPtrA” _
(ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Declare Function GetWindowLongPtr Lib “user32” Alias “GetWindowLongPtrA” _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。
1 2 3 4 5 |
#If VBA7 Then Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr #Else Declare Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long #End If |
各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。
・Public Declare PtrSafe Function~ :モジュール外で呼び出し有効
構文
GetWindowLongPtr関数の構文は下記のように書きます。
lRet = GetWindowLongPtr(hWnd, nIndex)
引数
hWnd (64bit:LongPtr型 / 32bit:Long型)
情報を取得する対象のウィンドウへのハンドルを入力します。
ウィンドウハンドルを取得するための関数としてFindWindow関数やFindWindowEx関数、GetActiveWindow関数など様々なものがあります。環境によって引数の型が変わるので注意が必要です。
nIndex (Long型)
取得したい情報のインデックスの定数値を入力します。
定数値はいくつか存在しますが、代表的なものを抜粋すると下表のような値があります。
値 | 意味 |
GWL_STYLE = -16 | ウィンドウスタイルを取得する |
GWL_EXSTYLE = -20 | 拡張ウィンドウスタイルを取得する |
GWLP_HWNDPARENT = -8 | 親ウィンドウのハンドルがある場合はそのハンドルを取得する |
上記以外の定数値はGetWindowLongPtr関数(パラメータ)ページを参照下さい
戻り値
lRet (64bit:LongPtr型 / 32bit:Long型)
戻り値は引数で指定したインデックスの情報です。
関数が失敗した場合は「0」が返されます。
ウィンドウハンドルと同様に環境によって戻り値の型が変わるので注意が必要です。
サンプルコード
以下はGetWindowLongPtr関数とFindWindow関数、SetWindowLongPtr関数を使って、UserFormに最大化ボタンと最小化ボタンを付与するサンプルコードです。UserFormを1つ作成し下記コードをコピーペーストしてUserFormを表示させることで、フォームのInitializeイベントが走り表示されるUserFormに最大化ボタンと最小化ボタンを付与することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr Const GWL_STYLE As Long = -16 'ウィンドウスタイル Const WS_MAXIMIZEBOX As Long = &H10000 '最大化ボタン Const WS_MINIMIZEBOX As Long = &H20000 '最小化ボタン Private Sub UserForm_Initialize() Dim hWnd As LongPtr Dim hStyle As LongPtr '自身(userForm)のウィンドウハンドルを取得 hWnd = FindWindow(vbNullString, Me.Caption) '現状のウィンドウスタイルを取得 hStyle = GetWindowLongPtr(hWnd, GWL_STYLE) '現状のウィンドウスタイルに最大化/最小化ボタンを追加 Call SetWindowLongPtr(hWnd, GWL_STYLE, hStyle Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX) End Sub |
VBA×WindowsAPIまとめページ
その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。
参考
Microsoft公式:GetWindowLongW 関数 (winuser.h) – Win32 apps