【VBA×WindowsAPI】ウィンドウ(UserForm)のオーナーウィンドウを変更する

通常VBAのUserFormは、Excelなどのアプリケーションウィンドウを親として作成されます。そのため、親であるアプリケーションウィンドウを最小化すると、UserFormも同時に最小化されます。このUserFormの親であるウィンドウはWindows APIを使用することで変更することができます。

これにより、たとえばExcel VBAでPowerPointを操作する際、本来であればUserFormの親はExcelウィンドウになりますが、親ウィンドウをPowerPointウィンドウに変更することで、Excel VBAのUserFormでありながらPowerPointのウィンドウとして扱うことができるようになります。

オーナーウィンドウの変更

オーナーウィンドウとは、ウィンドウの親子関係における「親」にあたるウィンドウのことを指します。一般的に、モーダルダイアログやサブウィンドウがオーナーウィンドウを持つことが多く、オーナーウィンドウが閉じられると、関連する子ウィンドウも一緒に閉じられます。また、オーナーウィンドウの背面には子ウィンドウが配置されないよう制御され、子ウィンドウが常に前面に表示されます。そのためアプリケーションウィンドウをオーナーとするUserFormやMsgBox関数で表示されるメッセージボックスは、Excelウィンドウの背面に表示されることはありません。

このオーナーウィンドウはWindowsAPIを使うことで変更ができます。上画像はUserFormのオーナーをメモ帳ウィンドウに変更したものです。これによりメモ帳ウィンドウより背面にUserFormが表示されることはなくなり、メモ帳を最小化するとUserFormもあわせて最小化されるようになります。

VBAで指定のウィンドウのオーナーを変更するには下記のWindows APIを利用します。
それぞれ関数のより詳細な使い方の解説は各関数のリンクページを参照下さい。

icon-check-square FindWindow関数          :ウィンドウのハンドルを取得する
icon-check-square SetWindowLongPtr関数 :ウィンドウのオーナーを設定する

「そもそもWindows APIって何?」という方はコチラ(メインページ)も併せて参照下さい。

サンプルコード

UserFormのオーナーウィンドウをメモ帳ウィンドウに変更するためのサンプルコードは下記の通りです。UserFormコードとして下記コードを設定後、メモ帳ウィンドウを起動した状態でUserFormを表示させることで、オーナーウィンドウをメモ帳ウィンドウに変更することができます。

ここではUserFormのオーナーウィンドウを変更していますが、ウィンドウハンドルさえ取得できればVBAとは関係のない指定のウィンドウのオーナーを変更することも可能です。

コード解説

icon-edit ウィンドウハンドルを取得する

ウィンドウにはそれぞれウィンドウハンドルと呼ばれる、ウィンドウを識別するためのID情報のようなものが付与されています。このウィンドウハンドルを取得することで、”どの”ウィンドウに対して処理を行うのかを簡単に指示することができます。(Windows APIでは頻出ワードです)

今回は指定のウィンドウを透明にしたいので、透明にする対象となるウィンドウのハンドルを習得します。ウィンドウハンドルを取得する方法はいくつも存在しますがここでは常套手段のFindWindow関数を使ってウィンドウハンドルを取得しています。FindWindow関数は下記のように記載することで指定のクラス名もしくはウィンドウ名から該当のウィンドウへのハンドルを取得することができます。

icon-code  FindWindow関数 

hWnd = FindWindow(クラス名”, “ウィンドウ名”)

UserFormの場合はCaptionがウィンドウ名となるので引数を「(vbNullString, Me.Caption)」、メモ帳の場合はクラス名がNotepadとなるので引数を「(“Notepad”, vbNullString)」としています。
  

icon-edit オーナーウィンドウの設定

オーナーウィンドウの変更にはSetWindowLongPtr関数を使い、下記のように記載します。

icon-code  SetWindowLongPtr関数 

Call SetWindowLongPtr(hWnd1, GWL_HWNDPARENT, hWnd2)

hWnd1にはオーナーを変更する対象のウィンドウのハンドル、hWnd2には設定するオーナーウィンドウのハンドルをそれぞれ入力します。第2引数は定数値「GWL_HWNDPARENT(=-8)」を入力します。SetWindowLongPtr関数は指定のウィンドウの様々な情報を設定するための関数であり、この定数は設定するウィンドウの情報がオーナーウィンドウであるということを指示するための値です。
 

関連情報

icon-share-square VBA×WindowsAPIまとめページ

その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。

icon-share-square 参考

Microsoft公式:SetWindowLongPtrA 関数 (winuser.h) – Win32 apps

Excel, VBA, Windows API

Posted by Lic