|
ここではサンプルとして右のようなフォームを用意してみました。このフォーム上に配置されたすべてのコントロールに対して、「横一列に直線配置」・「縦一列に直線配置」・「縦方向の間隔を削除して詰める」操作を行ってみます。直線配置についてはAccessの「左揃え」や「上揃え」でも一列に並べることはできますが、このサンプルフォームのようにコントロールの間隔が不揃いである場合、その間隔の調整までは行ってくれません。続けてメニューなどから「上下の間隔」の操作を実行する必要があります。そこでここでは「左揃え」や「上揃え」はもちろんのこと、コントロールの間隔が一定(等間隔)になるような操作も行うようにします。 |
|
|
最初に今回のサンプルコードの共通的な変数などを宣言します。ここでは対象とするフォーム名を「frmTest」としましたが、アドインとしてこのような機能を組み込む場合には、
Application.CurrentObjectName
の値から現在アクティブになっているオブジェクト名を取得しそれを代入する、という方法をとるのがよいでしょう。
ここで、sngTmpTop と sngTmpLeft は各コントロールの再配置後の[上位置]プロパティと[左位置]プロパティの値を保持する作業用変数です。また、sngCntrlGap はコントロールの間隔を表す変数です。T'sKitの各ツールではこの値を画面上のテキストボックスで指定するようになっていますが、ここでは一定の値を代入することとします。 |
なお、[上位置]や[左位置]プロパティをVBAから設定する場合にはすべて『Twip値』で指定しなければなりません。Accessのプロパティシートのように『cm』で管理したい場合には "1cm=567Twip" として換算します。ここではそれをあらかじめ定数"TWIP_CM"として宣言しています。
Dim frm As Form
Dim ctl As Control
Dim sngTmpTop As Single
Dim sngTmpLeft As Single
Dim sngCntrlGap As Single
Dim iintLoop
Const TWIP_CM = 567 '1cm当たりのTwip値
'対象フォームをフォームオブジェクト変数にセット
Set frm = Forms!frmTest |
|
それでは最初にコントロールを横一列に直線配置してみます。一番左のテキストボックスの上位置と左位置をともに0.5cmに、またコントロールの間隔を0.2cmにします。
sngTmpTop = 0.5 * TWIP_CM
sngTmpLeft = 0.5 * TWIP_CM
sngCntrlGap = 0.2 * TWIP_CM
frm.Painting = False
For iintLoop = 0 To frm.Controls.Count - 1
Set ctl = frm.Controls(iintLoop)
With ctl
.Top = sngTmpTop
.Left = sngTmpLeft
sngTmpLeft = sngTmpLeft + .Width + sngCntrlGap
End With
Next iintLoop
frm.Painting = True
このコードでは、テキストボックスのプロパティを変更する前にフォームの[Painting]プロパティを"False"に設定し、変更後に"True"に戻しています。これはテキストボックスのプロパティ値を1つ変えるたびにその値に基づいてテキストボックスが再描画される、つまりテキストボックスが左・上と順番に移動していく動作が見えてしまうのを防ぐためのものです。 |
いったん[Painting]プロパティを"False"に設定することによって、個々のプロパティを変更してもその時点では見た目にはテキストボックスの位置は変わらないようになります。そして最後に"True"にした時点で、すべてのテキストボックスが一斉に新しい位置に移動したように見せることができます。
For〜Nextのループはフォーム上のすべてのコントロールを列挙するループです。このループ内ではカウンタ用の変数iintLoopを使って frm.Controls(iintLoop) のような書式でiintLoop番目のコントロールを参照することができます。
個々のコントロールに対しては、現在の変数値を[Top/上位置]プロパティと[Left/左位置]プロパティそれぞれにセットして新しい位置を設定します。そして左位置を表す変数値(sngTmpLeft)にそのコントロールの幅(.Width)とコントロール間隔の指定値を加算することによって、次のコントロールの左位置を算出します。
|
|
続いてコントロールを縦一列に直線配置してみます。横一列の場合と異なるのは、1つのテキストボックスの位置を変更した後、左位置ではなく上位置を表す変数値(sngTmpTop)にそのコントロールの高さ(.Height)とコントロール間隔の指定値を加算する点だけです。
sngTmpTop = 0.5 * TWIP_CM
sngTmpLeft = 0.5 * TWIP_CM
sngCntrlGap = 0.2 * TWIP_CM
frm.Painting = False
For iintLoop = 0 To frm.Controls.Count - 1
Set ctl = frm.Controls(iintLoop)
With ctl
.Top = sngTmpTop
.Left = sngTmpLeft
sngTmpTop = sngTmpTop + .Height + sngCntrlGap
End With
Next iintLoop
frm.Painting = True |
|
|
最後に、縦方向の間隔を削除してテキストボックスを詰めて再配置してみます。プロパティ変更を行う部分のコードは縦一列に直線配置する場合とまったく同じです。コントロールの間隔を削除するということは間隔をゼロにするということですので、コントロールの間隔を表す変数sngCntrlGap = 0 とするだけです。
sngTmpTop = 0.5 * TWIP_CM
sngTmpLeft = 0.5 * TWIP_CM
sngCntrlGap = 0
frm.Painting = False
For iintLoop = 0 To frm.Controls.Count - 1
Set ctl = frm.Controls(iintLoop)
With ctl
.Top = sngTmpTop
.Left = sngTmpLeft
sngTmpTop = sngTmpTop + .Height + sngCntrlGap
End With
Next iintLoop
frm.Painting = True |
|
|
すべてのコントロールを列挙するループ、For iintLoop = 0 To frm.Controls.Count - 1
の部分では、実際には画面上の配置順ではなく作成された順番でコントロールが取り出されます。したがって、一般的には上からあるいは左から順番にコントロールが作成されるとは限りませんので、T'sKitではコントロール情報をいったんテーブルに書き出してから再配置操作を行っています。まずこのループを使ってとにかく対象となるすべてのコントロールの[上位置]、[左位置]、[幅]、[高さ]などの関連するプロパティ値を取得してテーブルに書き出します。 |
そして、それをクエリーによって上位置の昇順あるいは左位置の昇順で取り出すようにします。後はそれらのレコードを順番にループで読み込んで、上あるいは左から順番に一定の間隔を空けて再配置していきます。
また、「#12 フォーム上の特定の種類のコントロールを選択する」で説明した[InSelection]プロパティを利用することで、T'sKitの各ツールで行っているような、フォームのデザインで現在選択されているコントロールだけを対象に配置の変更を行うこともできます。 |