タブ式テキストエディタ(6) ファイルの読み書き(準備篇)

 ファイルの読み書きを行う関数をつくる前に、読み書きする際に必要な前処理と後処理のための関数をつくります。
 現在のファイルを閉じて、新しいファイルを読み込む際には、次の処理を行うことになります。

 @ 現在のページに変更があるかどうか調べる。
        → "ExpandedText"クラスの"Modified"プロパティ(既存)
 A 変更があれば保存するかどうかユーザーに問う。
        → "AllowUpdate"関数 (今回作成)
 B YESなら保存する。
        → "PageToFile"関数 (次回作成)
 C 開くファイルがあるならページ上に読み込む。
        → "PageFromFile"関数 (次回作成)
 D 読み込んだファイル名をステータスバーパネルに表示。
        → "UpdateInfo"関数 (今回作成)
 E 読み込んだファイル名を"最近使ったファイル"のリストに追加。
        → "UpdateRecentFile"関数 (今回作成)
 F Eの新しいリストに基づき、"最近使ったファイル"メニューを更新。
        → "UpdateRecentMenu"関数 (今回作成)

 BとCは実際にファイルの読み書きを行います。@はAの関数内で使います。A、D、E、FはBとCの関数内に配置しますので、これらを先につくっておくことにします。すべてメインフォーム内のコーディングです。

AllowUpdate : ページに変更があるか

 現在開いているファイルに変更が加えられたかどうかは、"ExpandedTextBox"の"Modified"プロパティで分かります。"PathName"プロパティは、現在開いているファイル名です。空文字の場合は存在しないファイル名、すなわち新規文書を意味します。その場合は、新規文書をあらわす"無題"を仮のファイル名として使用します。これは、"PageFromFile"関数で、新規文書作成時にタブページの"text"プロパティにセットされます。
 変更を認めたら、ユーザーに保存するかどうか問い合わせします。その後の処理を続行していいなら、True、禁止するなら、Falseを返します。
・Yes ・・・保存する(True) →「上書き保存」メニューのクリックイベントを起こす。
・No ・・・保存しない(True) →何もしない。
・Cancel ・・・保存しない(False) →何もしない。

' AllowUpdate : 更新許可の問い合わせ
' ... 引数page : 検査対象ページ
' ... 戻り値 : [True] 更新可, [False] 更新不可
Private Function AllowUpdate(ByVal page As TextPage) As Boolean
    If page.EditBox.Modified Then
        Dim file As String = IO.Path.GetFileName(page.EditBox.PathName)
        If file = "" Then file = page.Text
        Dim res As DialogResult = MessageBox.Show(  _
            "[" & file & "] の内容は変更されています。" _
                    & vbCrLf & "ファイルに保存しますか?", _
             "保存の確認", _
            MessageBoxButtons.YesNoCancel, _
            MessageBoxIcon.Question)

        Select Case res
            Case DialogResult.Yes
                TC1.SelectedTab = page
                mnSave.PerformClick()
                Return True
            Case DialogResult.No     : Return True
            Case DialogResult.Cancel : Return False
        End Select
    Else : Return True
    End If
End Function	

UpdateInfo : ファイル名をステータスバーパネルに表示

 表示箇所は二箇所。ステータスバーパネル(sbPath)にフルパス名を、タイトル部分にフォルダ名を除いたファイル名を表示します。
 "Application.ProductName"はアプリケーション名(=綴り帖)です。これを使うときはアッセンブリ用ファイルに記述する必要があります。また、オーナードローを使ってますので、ステータスバーの再描画には"Refresh"メソッドが必要です。

' UpdateInfo : 情報表示の更新
' ... 引数 page : 対象ページ
Private Sub UpdateInfo(ByVal page As TextPage)
    Dim strPath As String = ""  ' フルパス名
    Dim strFile As String = ""  ' ファイル名のみ

    If Not IsNothing(page) Then
        Dim strEditPath As String = page.EditBox.PathName
        strPath = " " & _
            DirectCast(IIf(strEditPath<>"",strEditPath, ""), String)
        strFile = " - " & _
            DirectCast(IIf(strEditPath<>"",IO.Path.GetFileName(strEditPath), _
            page.Text), String)
    End If

    ' ステータスバーパネルに表示
    sbPath.Text = strPath
    ' フォームのタイトル部分に表示
    Me.Text = Application.ProductName & strFile
    ' ステータスバーを再描画
    SB1.Refresh()
End Sub 

"AssemblyInfo.vb"
 <Assembly: AssemblyTitle("Tsuzuri")>
 <Assembly: AssemblyDescription("タブ式テキストエディタ")>
 <Assembly: AssemblyCompany("")>
 <Assembly: AssemblyProduct("綴り帖")>

UpdateRecentFile : "最近使ったファイル"のリストの更新

 前回つくった"StringCollection"クラスのインスタンスを宣言しておく必要があります。それと、格納する数も定数化しておきます。10個にしていますが、ここを変えれば、20個でも30個でもファイル数を調整できます。このファイル名は、初期化ファイルに保存しますが、それはまた後の回でつくることにします。
 まず、"IndexOf"メソッドで既存のリストの中に同じファイル名があるかを探し、あれば"RemoveAt"メソッドで削除しておきます。そして、リストの先頭に、ファイル名を挿入します。この状態でファイル数を調べ、、最大格納数を上回れば、リストの末尾を削除します。これで上から順に新しいファイルが並ぶことになります。
 最後に、メニューの表示を更新(次の項目を参照)します。

' 変数 : "最近使ったファイル"のリスト
Private m_recent As New StringCollection()
' 定数 : "最近使ったファイル"の最大格納数
Const nRecentSize As Integer = 10

' UpdateRecentFiles : 最近使ったファイルの更新
' ... 引数 path : 追加するファイル名
Private Sub UpdateRecentFiles(ByVal path As String)
    Dim nHit As Integer = m_recent.IndexOf(path)
    If nHit >= 0 Then
        m_recent.RemoveAt(nHit)
    End If
    m_recent.Insert(path, 0)
    If m_recent.Count > nRecentSize Then
        m_recent.RemoveAt(nRecentSize)
    End If
    UpdateRecentMenu()
End Sub 

UpdateRecentMenu : "最近使ったファイル"のメニューの更新

 メニューは、最近使ったファイルの先頭からテキストを設定していきます。メニューがなければ新しいインスタンスをつくってついかしています。このとき、クリックイベントに対応させるために、対応する関数をつくって結び付けなければなりません。

' UpdateRecentMenu : 最近使ったファイルメニューの更新
Private Sub UpdateRecentMenu()
    Dim i As Integer
    For i = 0 To m_recent.Count - 1
        If i >= mnRecent.MenuItems.Count Then
            Dim newmenu As New MenuItem()
            ' メニュー項目の追加
            mnRecent.MenuItems.Add(newmenu)
           ' イベントの追加
            AddHandler newmenu.Click, AddressOf Me.mnFileName_Click
        End If
        Dim header As String = "&" & i.ToString & ". "
        ' メニューの表示テキストの更新
        mnRecent.MenuItems(i).Text = header & IO.Path.GetFileName(m_recent(i))
    Next
End Sub

' mnFileName : 最近使ったファイルを開く
Private Sub mnFileName_Click(ByVal sender As Object, ByVal e As EventArgs)
    (中身は次々回)
End Sub	
| ■HOME | ◆プログラムTop | ▲ページの先頭 | << 前の章 | 次の章 >> |