【入門編】フォームの「OnResize」イベントでコントロールの配置を動的に最適化するレスポンシブUIの基礎 – Access VBA解析バイブル

スポンサーリンク

こんにちは! Accessのフォームを開いたとき、「あともうちょっと右側の余白を広くしたいな」「ウィンドウを大きくしたのに、中のリストボックスがスカスカのままで格好悪いな」と思ったことはありませんか?

マクロの記録から一歩抜け出して、本格的な業務アプリケーションを作ろうとすると、避けて通れないのが「画面の動的なサイズ変更(レスポンシブUI)」です。

今回は、Accessフォームの`OnResize`(サイズ変更時)イベントを完全に手なづけ、ウィンドウの拡大・縮小に合わせて中のコントロール(テキストボックスやリストボックスなど)を自在に伸縮させる極意を伝授します。

ここをクリアすれば、あなたの作るAccessアプリは一気に「プロのシステム」の顔つきに変わりますよ。さあ、一緒に扉を開けていきましょう!

1. なぜAccessで「レスポンシブUI」が必要なのか?

ExcelやWebの画面と違って、Accessのフォームはデフォルトのままだと「作ったときのサイズ」に固定されてしまいます。ユーザーがウィンドウを最大化しても、フォームはポツンと左上に小さく取り残され、まわりの背景(MDIクライアント領域)がグレーのままで広がっていきますよね。

これでは、

  • 大量のデータを表示したいのに、リストボックスが小さすぎてスクロールが必要。
  • 入力欄の幅が狭くて長い住所が見切れてしまう。

といった「使い勝手の悪いシステム」の温床になってしまいます。

これを解決するのが、フォームの`OnResize` イベントです。ウィンドウの枠をマウスでグッと引っ張って広げた「その瞬間」にVBAが発動し、ミリ秒単位で中のコントロールのサイズや位置を計算し直して配置する――今回は、この魔法のような仕組みを作ります。

2. 実装の全体像と「3つのステップ」

やるべきことはとてもシンプルです。

1. 基準となるサイズを把握する:フォームの設計時のサイズ(初期幅・初期高さ)を覚えておく。
2. イベントを捉える:フォームがリサイズされた瞬間(`Form_Resize`)をVBAでフックする。
3. コントロールを再配置・変形する:新旧のサイズ比率、あるいは差分を計算して、コントロールの `Width`(幅)や `Height`(高さ)を書き換える。

言葉で聞くと難しそうですが、コードは驚くほどスッキリ書けます。次のセクションで実際のコードを見てみましょう。

3. 実践!コピペで動くレスポンシブ・フォームのVBAコード

ここでは、ウィンドウを横に広げたら「リストボックスの幅」が広がり、縦に広げたら「リストボックスの高さ」が伸びる、そんな王道のレイアウトを実装します。

対象フォームの準備

1. 適当なフォーム(例: `F_Main`)をデザインビューで開きます。
2. フォームの中に、適当なリストボックス(例: `lstData`)と、テキストボックス(例: `txtSearch`)を配置します。
3. フォームのプロパティシートを開き、「イベント」タブにある 「サイズ変更時 (On Resize)」 の右側の `…` ボタンをクリックし、「プロシージャ ビルダー」を選びます。

VBE(Visual Basic Editor)が開いたら、以下のコードをそのまま貼り付けてください。

Option Compare Database
Option Explicit

‘ =================================================================00
‘ フォームのレスポンシブ制御モジュール
‘ =================================================================00

‘ フォームが開いたときの「基準サイズ」を記憶するための変数
Private m_InitialFormWidth As Long
Private m_InitialFormHeight As Long

Private Sub Form_Open(Cancel As Integer)
‘ 【重要】フォームが読み込まれた瞬間の幅と高さを保持する
‘ Accessの内部単位は「トウィップ (Twip)」です(1インチ = 1440トウィップ)
m_InitialFormWidth = Me.Width
m_InitialFormHeight = Me.InsideHeight
End Sub

Private Sub Form_Resize()
‘ エラーハンドリングの基本:フォームが最小化されたときなどのゼロ除算を防ぐ
On Error GoTo ErrorHandler

‘ 1. フォームが開く前(Openイベント前)や、初期化が済んでいない場合は何もしない
If m_InitialFormWidth = 0 Or m_InitialFormHeight = 0 Then Exit Sub

‘ 2. 現在のフォームの内側サイズを取得
Dim currentWidth As Long
Dim currentHeight As Long
currentWidth = Me.InsideHeight ‘ ※修正:InsideWidthを取得します
currentWidth = Me.InsideWidth ‘ (念のため正確なプロパティを記述)

‘ 3. 拡大・縮小の「倍率」を計算する
‘ 現在のサイズ ÷ 初期サイズ で、どれくらい拡大されたかがわかります
Dim widthRatio As Double
Dim heightRatio As Double

widthRatio = CCur(currentWidth) / CCur(m_InitialFormWidth)
heightRatio = CCur(currentHeight) / CCur(m_InitialFormHeight)

‘ =================================================================
‘ 4. 各コントロールの配置を動的に変更する
‘ =================================================================

‘ 例A:検索テキストボックス(横幅だけをウィンドウに合わせて広げる)
‘ 設計時の幅が 3000トウィップ だとしたら、倍率を掛け算します
‘ Me.txtSearch.Width = 3000 widthRatio

‘ 例B:リストボックス(右側と下側の余白を常に一定に保つように拡大する)
‘ ここでは「フォームの端からのマージン(余白)」を維持するロジックが実用的です

‘ 右側のマージンを「設計時から変えたくない場合」の計算例:
‘ リストボックスの左位置 (Left) は固定し、幅 = 現在のフォーム幅 – 左の余白 – 右の余白
Const LIST_LEFT As Long = 360 ‘ 左端からの距離 (トウィップ)
Const LIST_TOP As Long = 1200 ‘ 上端からの距離
Const RIGHT_MARGIN As Long = 360 ‘ 右側の余白を常に360トウィップに保つ
Const BOTTOM_MARGIN As Long = 360 ‘ 下側の余白を常に360トウィップに保つ

‘ コントロールのサイズを一括変更(画面のちらつきを防ぐため、WidthとHeightを最後に設定)
With Me.lstData
.Move LIST_LEFT, LIST_TOP, _
currentWidth – LIST_LEFT – RIGHT_MARGIN, _
currentHeight – LIST_TOP – BOTTOM_MARGIN
End With

Exit_Handler:
Exit Sub

ErrorHandler:
‘ フォームが閉じかける際などの予期せぬエラーはイミディエイトに出して無視
Debug.Print “Form_Resize Error: ” & Err.Description
Resume Exit_Handler
End Sub

4. コードの深掘り:ここがエンジニアのこだわりポイント

初学者のうちは「なんとなく動いたからラッキー」で終わりがちですが、実務で耐えうるコードを書くためには、以下の3つのポイントを押さえておく必要があります。

① Access独特の単位「トウィップ (Twip)」とは?

コードに出てくる数値(`360` など)は、ピクセルではありません。Accessではトウィップという独自の単位が使われています。

  • 1 インチ = 1440 トウィップ
  • 1 センチ = 約 567 トウィップ

画面の位置やサイズをコードで微調整するときは、この「トウィップ」単位で計算していることを忘れないようにしましょう。

② `.Move` メソッドの圧倒的な優位性

コントロールの大きさを変えるとき、つい以下のように書きがちです。

Me.lstData.Width = 5000
Me.lstData.Height = 4000

しかし、これだと「幅を変えた瞬間」と「高さを変えた瞬間」に、画面の再描画(レンダリング)が2回走ってしまいます。 画面がカクついたり、チラついたりする原因です。

プロのエンジニアは、位置とサイズを一度に指定できる `Me.ControlName.Move Left, Top, Width, Height` メソッドを使います。これなら描画は1回で済み、動作が非常にスムーズになります。

③ 「倍率計算」か「余白固定」か

レスポンシブデザインには大きく分けて2つのアプローチがあります。
1. 倍率方式:すべての部品を比率に合わせて拡大縮小する(画像やグラフに向いています)。
2. 余白固定(マージン)方式:テキストボックスやリストボックスは幅を広げ、ボタン類は右端に張り付かせておく(入力フォームに最適です)。

実務の業務システムでは、文字サイズまで拡大されてしまう「倍率方式」よりも、「外側の余白を一定に保ちながら、中身のリストをビヨーンと伸ばす」余白固定方式の方が圧倒的に実用的で美しく仕上がります。上記のサンプルコードは、まさにこの実践的な方式を採用しています。

5. 陥りやすい罠とエラー回避の知恵

`OnResize` イベントを扱う上で、誰もが一度はハマる「罠」があります。

  • 罠1:フォームを最小化(アイコン化)したときにエラーが出る
  • 原因:フォームが最小化されると、`InsideHeight` や `InsideWidth` が「0」またはマイナスに近い異常値になり、それをベースに計算しようとしてオーバーフローやゼロ除算エラーが発生します。
  • 対策:上記のコードのように、エラーハンドラ(`On Error GoTo`)を必ず仕込んでおくこと。また、`currentWidth <= 0` のときは処理を抜けるガード節を入れると完璧です。
  • 罠2:コントロールが小さくなりすぎて消えてしまう
  • 原因:ユーザーがウィンドウを極端に小さく縮めたとき、コントロールの幅や高さにマイナスの値が代入されてしまうことがあります。
  • 対策:必要であれば `If currentWidth – LIST_LEFT – RIGHT_MARGIN < 1000 Then Exit Sub` のように、コントロールの「最小サイズ(最小保証幅)」をコードで守ってあげましょう。

まとめ:ここをクリアすればAccess VBAの基本はバッチリです!

今回は、フォームの `OnResize` イベントを使ったレスポンシブUIの基礎について解説しました。

  • フォームの初期サイズを `Open` イベントで記憶する。
  • ウィンドウが動かされたら `Resize` イベントが走る。
  • `.Move` メソッドを使って、コントロールの幅や高さをスマートに再計算する。

この一連の流れを自分のものにできたなら、あなたはもう「Accessに言われるがまま画面を作っていた初学者」ではありません。ユーザーの使い勝手を第一に考えた、ワンランク上のアプリケーション・アーキテクトの扉を叩いています。

ぜひ、お手元のAccessファイルで試してみてください。「ウィンドウに合わせてスルスル動くフォーム」の心地よさに、きっと感動するはずですよ!

タイトルとURLをコピーしました