詳解・フォームの位置とサイズの記憶

 通常アプリケーションは、終了時のフォームの位置とサイズを記憶しておき、起動時に読み出します。 パソコンに情報を記憶させておく最も簡単な方法は、レジストリを使用することです。  レジストリに情報を記憶するにはSaveSettingステートメント、読み出すにはGetSetting関数を使用します。


<SaveSettingステートメント>

構文:SaveSetting appname, section, key, setting

appname 大元のフォルダと考えてください。
通常はアプリケーションの名前を指定します。(具体的にはApp.Title)
section appnameの下のフォルダと考えてください。
自由に名前を付けることができます。(一部使えない文字有り)
key sectionの下にある文字列変数名(String)と考えてください。
自由に名前を付けることができます。(一部使えない文字有り)
setting keyという文字列変数に格納しておく値(String)と考えてください。

 レジストリはフォルダ(ディレクトリ)のような階層構造になっており、値を入れておくことができると考えてください。

appnameフォルダ
 −sectionフォルダ
  −変数keyに、settingという値が書き込まれる。

・・・と考えれば、解りやすいと思います。

<ChatJamのフォームのプロシージャの具体例>
 SaveSetting App.Title , "MainForm" , "Height" , Me.Height
これで、レジストリの中のChatJam\MainForm\Heightに、フォームの高さが書き込まれる。


<GetSetting関数>

構文:GetSetting(appname, section, key[, default])

appname SaveSettingと同じ
section SaveSettingと同じ
key SaveSettingと同じ
default keyが読み出せなかった場合、つまりまだ何もkeyに入っていない場合に読み出すデフォルト値と考えてください。
ここに何も書かなかった場合、デフォルト値は長さ0の文字列("")となります。

<ChatJamのフォームのプロシージャの具体例>
 Me.Height = GetSetting( App.Title , "MainForm" , "Height" , 3000 )
 これで、レジストリの中のChatJam\MainForm\Heightの値を読み出し、フォームの高さに設定します。また、読み出せなかった場合はフォームの高さはデフォルト値の3000になります。


<フォームの位置とサイズを記憶するアルゴリズム>

さて、具体的にはどういったことをやりたいのでしょう?ちょっと、列挙してみましょう。

<やりたいこと>

 さて、これらのことを実現するには、どういったイベントで行わなければならないのでしょうか。また、注意点は何なのでしょうか。機能を実現するために必要なイベントと、各イベントでやるべきこと、さらには各イベント作成時の注意点を列挙してみましょう。

<Form_Loadイベント>

<Form_Resizeイベント>

<Form_Unloadイベント>


<最大の注意点>

FormのStartUpPositionプロパティは「0 - 手動」にしておきましょう
これを守らないと正常に動作しません。
例えばStartUpPositionが「3 - Windowsの規定値」になっていると以下のように動きます。
Form_Loadイベントが発生
   ↓
Form_Loadイベントプロシージャ内でFormのサイズ変更
   ↓
Form_Resizeイベントが発生(位置がセーブされる)←Form_Load中に割り込んで実行
(このイベントは正しい動き)
   ↓
Form_Loadイベントが完了
   ↓
StartUpPositionに基づくイベントが発生
(位置が強制的にWindowsの規定値になってしまう)
(「0 - 手動」にしておくとこれを防ぐことができる)
   ↓
Form_Resizeイベントが発生(位置がセーブされる)
(このイベントでヘンになる)


<普通の注意点>

FormのBorderStyleプロパティは「2 - 可変」でないと、リサイズできません。
・・・って当たり前か。


<コード公開>

以下に公開するコードは自由に
  • 改変したり、
  • プロジェクトへ組み込んだり、
  • 配布したり、
  • 雑誌等に掲載したり、
    していただいてかまいません。
     著作権は破棄しておりませんが、如何なる障害が発生してもOkayanは責任を負わないものとします。
    ※雑誌やインターネットに掲載する場合は、できればOkayan(okayanstudio@ybb.ne.jp)までご一報ください。

    Option Explicit
    Private Const MinWid    As Long = 3000  'フォームの幅の最小値
    Private Const MinHei    As Long = 3000  'フォームの高さの最小値
    
    Private Sub Form_Load()
        With Me
            'まずは、記憶していた位置とサイズで開き、
            .Move Val(GetSetting(App.Title, "frmMain", "Left", Str((Screen.Width - MinWid) \ 2))), _
                  Val(GetSetting(App.Title, "frmMain", "Top", Str((Screen.Height - MinHei) \ 2))), _
                  Val(GetSetting(App.Title, "frmMain", "Width", Str(MinWid))), _
                  Val(GetSetting(App.Title, "frmMain", "Height", Str(MinHei)))
            '次にウィンドウの状態(最大化/最小化/ノーマル)を設定
            .WindowState = Val(GetSetting(App.Title, "frmMain", "WindowState", vbNormal))
        End With
    End Sub
    
    Private Sub Form_Resize()
        With Me
            If .WindowState = vbMinimized Then Exit Sub     '最小化ならば抜ける
            If .Width < MinWid Then .Width = MinWid         'フォームの幅の最小値チェック
            If .Height < MinHei Then .Height = MinHei       'フォームの高さの最小値チェック
            If .WindowState = vbNormal Then                 'ノーマルの時は位置とサイズを記憶する。
                SaveSetting App.Title, "frmMain", "Left", Str(.Left)
                SaveSetting App.Title, "frmMain", "Top", Str(.Top)
                SaveSetting App.Title, "frmMain", "Width", Str(.Width)
                SaveSetting App.Title, "frmMain", "Height", Str(.Height)
            End If
        End With
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        With Me
            'まずはウィンドウの状態(最大化/最小化/ノーマル)を記憶し、
            SaveSetting App.Title, "frmMain", "WindowState", Str(.WindowState)
            'ノーマルの時は位置のみ記憶する。
            If .WindowState = vbNormal Then
                SaveSetting App.Title, "frmMain", "Left", Str(.Left)
                SaveSetting App.Title, "frmMain", "Top", Str(.Top)
            End If
        End With
    End Sub