VBAのユーザーフォーム(UserForm)サイズを可変化させる方法

VBAでは「UserForm」というマクロ用の入力ウィンドウを作成することができます。
しかしながらUserFormは通常のウィンドウとは違い、拡大/縮小や最大化/最小化といったウィンドウサイズの変更をすることはできません。

場合によってはユーザーが自身の手でUserFormのサイズを変更したいということもあるでしょう。
という訳で今回はWindows APIを利用してUserFormサイズを可変化する方法を解説していきます。
今回学ぶことのできる内容は以下のとおりです。

 Windows APIについて
 GetActiveWindow関数の使い方
 GetWindowLong関数の使い方
 SetWindowLong関数の使い方
DrawMenuBar関数の使い方
 上記の関数を使ってUserFormのサイズを可変化させる方法

内容は少し難しく感じるかもしれませんがUserFormサイズの可変化はサンプルコードのコピペだけで実現可能なので、コードの内容はどうでもいいという場合でもすぐに実装できるようになっています。

 

UserFormサイズを可変化するためのAPI関数

UserFormサイズを可変化するには下記の4つのWindows APIの関数を使います。

・GetActiveWindow関数 :現在アクティブなウィンドウのウィンドウハンドルを取得する
・GetWindowLong関数 :
指定されたウィンドウに関する情報を取得する
・SetWindowLong関数   :指定されたウィンドウの属性を変更する
・DrawMenuBar関数  :ウィンドウのメニューバーを再描画する

各関数は下記のような順番で使用します。

① GetActiveWindow関数でUserFormウィンドウを取得
② GetWindowLong関数で取得したUseFormのウィンドウ情報を取得
③ SetWindowLong関数で取得したウィンドウ情報に「可変化」に関する情報を追加  
④ ウィンドウのメニューバーを再描画 (=③の内容を反映させる)

 
上記の処理を行うことで最終的に下のgif画像のようにUserFormのサイズを変更することができるようになります。(ウィンドウ右上の[最大化][最小化]のボタンはUserFormを表示とともに追加されます)


 

Windows APIとは 

これら関数はWindows APIで用意されているものでVBAとは別のものです。Windows APIとは簡単にいえばWindowsに用意されている機能がまとまっているセットのようなものです。

Windows APIにはウィンドウサイズを変更する関数以外にも様々な関数があり、VBA上でそれらを呼び出すことで、Windowsに用意されている様々な機能を使用することができます。(たとえばWindowsのシステム効果音を鳴らしたり、指定した秒数だけ処理を止めることができます)

ちなみに名前からわかると思いますが、Windows APIではWindowsの機能を呼び出しているだけので基本的にはWindows以外のOSでは使用することはできません

 

UserFormサイズを可変化する各関数の使い方

マウス操作の関数を使うにははじめに「Windous APIの関数を使うよ」と宣言する必要があります。
※宣言をしないと各関数は使えずエラーになるので書き忘れに注意しましょう。

使用しているWindowsが32bitか64bitかによって宣言時に書く内容が変わってきます。
以下のどちらかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。

 icon-code 64bit 

‘【GetActiveWindow関数】
   Declare PtrSafe Function GetActiveWindow Lib “user32” () As LongPtr
‘【GetWindowLong関数】
   Declare PtrSafe Function GetWindowLong Lib “user32” Alias “GetWindowLongA” _
   (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
‘【SetWindowLong関数】
   Declare PtrSafe Function SetWindowLong Lib “user32” Alias “SetWindowLongA” _
   (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
‘【DrawMenuBar関数】
   Declare PtrSafe Function DrawMenuBar Lib “user32” (ByVal hwnd As LongPtr) As Long

 icon-code 32bit 

‘【GetActiveWindow関数】
   Declare Function GetActiveWindow Lib “user32” () As Long
‘【GetWindowLong関数】
   Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA” _
   (ByVal hwnd As Long, ByVal nIndex As Long) As Long
‘【SetWindowLong関数】
   Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA” _
   (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
‘【DrawMenuBar関数】
   Declare Function DrawMenuBar Lib “user32” (ByVal hwnd As Long) As Long

※操作環境のbitと構文があっていないとエラーになるので注意しましょう。
 

上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。

この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。

各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。

Private Declare PtrSafe Function~ :モジュール内で呼び出し有効
Public Declare PtrSafe Function~ :モジュール外で呼び出し有効

また、各関数ではあらかじめ決められた値である”定数”を使用します。
これらも関数の宣言と同じ場所にまとめて記載しておく必要があるので注意しましょう。

 

UserForm可変化サンプルコード

これまでの内容をまとめたサンプルコードを紹介します。
サンプルコードはユーザーフォーム(UserFom1)上にコマンドボタン(CommandButton1)があることを想定しています。下のgif画像のようにユーザーフォームのサイズが変わるにつれてコマンドボタンのサイズも追従するようなコードとなっています。

つまりは、サンプルコードと同じ考えでコントロールを設定することで、ユーザーフォーム上のオブジェクトのサイズもフレキシブルに変化させることが可能になります。

サンプルコードは下記の2つです。
モジュールとUserFormの両者にコードを書く必要があるので注意してください。
また上記の通りUserFormだけでなくCommandButtonも作成しておいてください。
 

標準モジュールコード

各API関数の書き方は上記の通り(Sub ResizeForm)でほぼ定型文です。
各関数でどのような処理をしているかは上記コードのコメント文を参照してください。
34bit/64bitによる書き方の違いはありませんが変数の型だけは違うので注意しておきましょう。
  

UserFormコード

 
UserFormとCommandButtonを作成ののち、上記コードをコピペしてSub Main()を実行すれば先程のgif画像のように可変化できるUserFormを表示することができます。あとは作成するマクロに合わせて普段通りにコントロールや処理を追加していくだけです。

 

まとめ

今回はWindows APIを使ってUserFormのサイズを可変化する方法についてでした。

ユーザー視点に立つとウィンドウのサイズ変更機能はあると案外助かるものです。
サンプルコードのようにコントロールのサイズも追従させるとなると、多少コードは長くなってしまいますがかなりユーザーファーストなマクロにすることができます。

マクロによってはサイズ変更自体不要なものもあるので、作成する機能に合わせて実装してみるのも悪くことと思います。

 

icon-book VBAでその他のWindows APIを呼び出そう

2023年2月4日Excel, VBA, Windows API

Posted by Lic