【VBA×WindowsAPI】UserFormに最大化・最小化・サイズ可変の情報を設定する

VBAのUserFormは通常のウィンドウとは違い、拡大/縮小や最大化/最小化といったウィンドウサイズの変更をすることはできません。このときWindowsAPIを使うことで通常のウィンドウと同じように最大化/最小化ボタンを付与したり、サイズをドラッグで変更できるようにしたりすることができます。

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

UserFormに最大化・最小化・サイズ可変の情報を設定

UserFormはデフォルトではウィンドウの境界をドラッグしてサイズを拡張したり、タイトルバーに最小化、最大化ボタンは付与されていませんが、WindowsAPIを使うことで上画像のようにウィンドウサイズの可変や最小化/最大化のボタンを設定することが可能になります。

Windowsのウィンドウはウィンドウスタイルという、そのウィンドウの見た目や振る舞いが定義された内部的な情報を持っています。VBAのUserFormのデフォルト時のウィンドウスタイルは下画像の通りで、たとえば「WS_CAPTION」はタイトルバーが有ることを表し、「WS_VISIBLE」は画面上に表示されていることを表します。(その他のスタイルについてはウィンドウスタイルを参照下さい)

このとき、ウィンドウサイズが可変であるかや最小化/最大化ボタンを含むかもこのウィンドウスタイルに含まれます。つまり、現在のウィンドウスタイルを取得した後、ウィンドウサイズの可変、最小化/最大化ボタンのスタイルを追加することでUserFormにそれら機能を実装させることが出来ます。

VBAでUserFormに最大化・最小化・サイズ可変のウィンドウスタイルを設定するには下記のWindows APIを利用します。それぞれ関数のより詳細な使い方の解説は各関数のリンクページを参照下さい。

icon-check-square FindWindow関数              :指定のウィンドウのハンドルを取得する
icon-check-square GetWindowLongPtr関数
 :指定されたウィンドウに関する情報を取得する
icon-check-square SetWindowLongPtr関数   :指定されたウィンドウの属性を変更する

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

UserForm可変化サンプルコード

下記はUserFormに最小化/最大化ボタンを付与してウィンドウサイズの可変を可能にするためのサンプルコードです。UserForm上にはほとんどの場合、コントロールが存在するためサンプルコードでは上画像のようにウィンドウのサイズにコントロールが追従する内容も実装されています。下記コード記載のUserFormに対して「UserForm.Show vbModeless」を実行することで設定を施した状態にして起動することができます。(※予めUserForm上にCommandButtonを作成しておく必要があります)

Option Explicit
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
Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long

Private Const GWL_STYLE = -16
Private Const WS_MAXIMIZEBOX = &H10000  '最大化ボタン
Private Const WS_MINIMIZEBOX = &H20000  '最小化ボタン
Private Const WS_THICKFRAME = &H40000   'サイズ可変

Private Sub UserForm_Initialize()

    Dim hWnd As LongPtr
    Dim hStyle As LongPtr
    
    'ウィンドウハンドル取得
    hWnd = FindWindow("ThunderDFrame", Me.Caption)
    
    'ウィンドウスタイル取得
    hStyle = GetWindowLongPtr(hWnd, GWL_STYLE)
    
    'ウィンドウスタイルにサイズ可変,最大化ボタン,最小化ボタン情報を付与
    hStyle = hStyle Or WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX
    
    'ウィンドウスタイルを適用
    Call SetWindowLongPtr(hWnd, GWL_STYLE, hStyle)
    
End Sub

Private Sub UserForm_Resize()

    'CommandButtonサイズの追従(If文はサイズが0以下になる発生するエラー対策)
    If Me.width > 100 Then Me.CommandButton1.width = Me.width - 40
    If Me.height > 100 Then Me.CommandButton1.height = Me.height - 55
    
End Sub

 

コード解説

icon-edit UserFormのウィンドウハンドルを取得

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

UserFormもウィンドウの1つであるため一意のウィンドウハンドルを持ちます。ウィンドウハンドルを取得するための関数はいくつも存在しますがここでは常套手段のFindWindow関数を使ってウィンドウハンドルを取得しています。FindWindow関数は下記のように記載することで指定のクラス名もしくはウィンドウ名から該当のウィンドウへのハンドルを取得することができます。

icon-code FindWindow関数 

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

UserFormはクラス名が”ThunderDFrame”で、ウィンドウ名はMe.Captionとなります。いずれか片方を入力してもう一方の引数をvbNullStringとしても取得可能ですが、サンプルコードではどちらの引数も入力して確実にUserFormが取得できるようにしています。
 

icon-edit ウィンドウスタイルの取得

UserFormのウィンドウハンドルが取得できたらそのハンドルからウィンドウスタイルを取得します。ウィンドウスタイルはGetWindowLongPtr関数を使い下記のように記載します。

icon-code ウィンドウスタイル取得 

hStyle = GetWindowLongPtr(hWnd, GWL_STYLE)

第1引数の「hWnd」にはUserFormのウィンドウハンドル、第2引数には取得する情報がウィンドウスタイルであることを表す定数値「GWL_STYLE」をそれぞれ入力することで、戻り値として入力したウィンドウが持つウィンドウスタイルを取得することができます。
   

icon-edit 取得したウィンドウスタイルに追加設定

ウィンドウスタイルが取得できたらウィンドウサイズ可変、最大化/最小化ボタンを表すウィンドウスタイル情報を追加します。ウィンドウスタイルの追加はOr演算子を使い、下記のように記載します。

icon-code ウィンドウスタイルに追加設定 

hStyle = hStyle Or WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX

このとき、この3種の設定はすべて同時に行う必要はありません。たとえばサイズ可変の設定のみしたければ「hStyle = hStyle Or WS_THICKFRAME」と記載することで最大化/最小化ボタンを設定せずにサイズ可変のみの設定をすることができます。
 

icon-edit UserFormにウィンドウスタイルを再設定

ウィンドウスタイルの追加設定ができたらその情報をUserFormに再設定します。ウィンドウスタイルの設定はSetWindowLongPtr関数を使って下記のように記載します。

icon-code ウィンドウスタイルの再設定 

Call SetWindowLongPtr(hWnd, GWL_STYLE, hStyle)

第1引数の「hWnd」にはUserFormのウィンドウハンドル、第2引数には設定する情報がウィンドウスタイルであることを表す定数値「GWL_STYLE」、第3引数の「hStyle」には設定するウィンドウスタイル(前項で追加設定したもの)をそれぞれ入力します。

これによりUserFormに最大化/最小化ボタンが付与されサイズ変更も可能になります。
 

関連情報

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

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

icon-share-square 参考

2024年3月26日Excel,VBA,Windows API