【VBA】ユーザーフォームを最大化・最小化・リサイズ可能にする方法 (Windows API)

目次

はじめに

VBAのユーザーフォームは、デフォルトではウィンドウサイズの変更ができず、タイトルバーには「閉じる」ボタンしかありません。しかし、表示するデータ量に応じてユーザーが自由に大きさを変えられたり、一時的に最小化してシートの作業に戻れたりすると、ツールの利便性が大きく向上します。

このような、Windowsの標準的なウィンドウが持つ「最大化」「最小化」「サイズ変更」といった機能は、Windows APIを駆使して、ユーザーフォームに後から追加することが可能です。

この記事では、ユーザーフォームのウィンドウスタイルを変更し、タイトルバーに最大化・最小化ボタンを追加し、ウィンドウ枠をドラッグしてリサイズ可能にする、高度なテクニックを解説します。


最大化・最小化・リサイズを有効化するVBAサンプルコード

このマクロは、Declareステートメント、Const(定数)、およびフォームの _Activate() イベントプロシージャで構成されます。API関連の定義は、標準モジュールに記述するのが一般的です。

ステップ1: API宣言を標準モジュールに記述

'--- 標準モジュール (例: Module1) に記述 ---

' 64bit/32bit両対応
#If VBA7 Then
    Public Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Public Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
    Public Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    Public Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hwnd As LongPtr) As Long
#Else
    Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Public Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
    ' 32bit環境ではPtr系関数のエイリアスを設定
    Public Const SetWindowLongPtr = SetWindowLong
    Public Const GetWindowLongPtr = GetWindowLong
#End If

' ウィンドウスタイルを取得/設定するための定数
Public Const GWL_STYLE As Long = -16
' リサイズ可能な太い枠線を持つスタイル
Public Const WS_THICKFRAME As Long = &H40000
' 最大化ボタンを持つスタイル
Public Const WS_MAXIMIZEBOX As Long = &H10000
' 最小化ボタンを持つスタイル
Public Const WS_MINIMIZEBOX As Long = &H20000

ステップ2: ユーザーフォームのイベントプロシージャを記述

このコードは、ユーザーフォームのコードモジュールに直接記述します。ウィンドウの存在が確実な Activate イベントを使用します。

【ユーザーフォーム: ResizableForm

' フォームがアクティブになったときに実行されるイベント
Private Sub UserForm_Activate()
    Dim formHandle As LongPtr
    Dim currentStyle As LongPtr
    
    ' 1. このフォームのウィンドウハンドルを取得
    formHandle = FindWindow("ThunderDFrame", Me.Caption)
    If formHandle = 0 Then Exit Sub
    
    ' 2. 現在のウィンドウスタイルを取得
    currentStyle = GetWindowLongPtr(formHandle, GWL_STYLE)
    
    ' 3. 現在のスタイルに、新しいスタイル属性を追加
    '    Or演算子で、必要な属性ビットをオンにする
    SetWindowLongPtr formHandle, GWL_STYLE, currentStyle Or WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX
    
    ' 4. ウィンドウの変更を再描画して適用
    DrawMenuBar formHandle
End Sub

コードの解説

API関数と Activate イベント

FindWindow, GetWindowLongPtr, SetWindowLongPtr, DrawMenuBar の各APIは、ウィンドウの情報を取得・変更するための関数です。これらの詳細な役割は、タイトルバーを消去する記事で解説しています。ウィンドウハンドルを扱う処理は、フォームが完全に表示された後である Activate イベントで行うのが安全です。

currentStyle Or WS_THICKFRAME Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX

ウィンドウスタイルを追加する核心部分です。

  • ウィンドウスタイル定数:
    • WS_THICKFRAME: サイズ変更可能な太い枠線を持つ、という属性です。
    • WS_MAXIMIZEBOX: 最大化ボタンを持つ、という属性です。
    • WS_MINIMIZEBOX: 最小化ボタンを持つ、という属性です。
  • Or 演算子: ビット演算の Or は、複数のスタイル属性を「追加(合成)」するのに使われます。currentStyle(現在のスタイル)に対して、Or を使って WS_THICKFRAME などの属性ビットをオンにしていきます。これにより、元のスタイルを維持したまま、新しい機能だけを追加することができます。

これは、タイトルバーを消去する記事で、And (Not ...) を使ってスタイル属性を「削除」したのとは対照的な操作です。


まとめ

今回は、Windows APIを駆使して、VBAのユーザーフォームに「最大化」「最小化」「サイズ変更」の機能を追加する、高度なカスタマイズ方法を解説しました。

  • ウィンドウのスタイル情報は、GetWindowLongPtrSetWindowLongPtr APIで操作できる。
  • リサイズ、最大化、最小化の機能は、それぞれ WS_THICKFRAME, WS_MAXIMIZEBOX, WS_MINIMIZEBOX というスタイル属性に対応している。
  • ビット演算の Or を使って、既存のスタイルに新しい属性を追加する。

このテクニックを使えば、標準のユーザーフォームの制約を超えて、よりWindowsアプリケーションらしい、柔軟で使い勝手の良いUIを構築することが可能になります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次