タブ式テキストエディタ(7) ファイルの読み書き(実行篇)

 ファイルの読み書きを行う実行関数をつくります。つくる関数は二つ。
 ・"PageFromFile"関数 ・・・ ファイルを開く
 ・"PageToFile"関数  ・・・ ファイルを保存

PageFromFile : ファイルの読み込み

 次の操作のすべてをこの一つの関数でまかないますが、ちょっと長くなってしまいました。まあ一つの関数に記述する限界は100行くらいだそうですから、ぎりぎり許容範囲かなと思います。
@ 新規ページに新規文書を追加する。
A 新規ページに既存のファイルを読み込む。
B アクティブなページに新規文書を設定する。
C アクティブなページに既存のファイルを読み込む。

' 変数 : タブ幅
Private m_tabwidth As Integer = 0

' PageFromFile : 指定したファイルを指定したページに開く
' ... 引数path : パス名。ただし、 [Nothing] で新規作成、[""] でOpenFileDialog を生成
' ... 引数page : 対象ページ。ただし、[Nothing] で新規ページ
Public Sub PageFromFile(ByVal path As String, ByVal page As TextPage)
    Dim d As OpenFileDialog    ' 「ファイルを開く」ダイアログボックス
    Dim strFilter As String = _
    "テキストファイル(*.txt,*.rtf,*.html,*.css)|*.txt;*.rtf;*.html;*.css|すべてのファイル(*.*)|*.*"
    Static nFilter As Integer = 1    ' ダイアログのフィルター番号
    Try
        Dim strFile As String = ""    ' ファイル名
        Dim strCaption As String = ""    ' 見出しの文字列

        ' ページの表示
        If IsNothing(path) Then
            ' 新規作成
            Dim nNumber As Integer = 0    ' 文書番号
            Dim bBreak As Boolean    ' ループ脱出フラグ
            Do
                bBreak = True
                nNumber += 1
                strCaption = "無題" & nNumber.ToString
                Dim p As TextPage
                If TC1.TabPages.Count > 0 Then
                    For Each p In TC1.TabPages
                        If p.Text = strCaption Then
                            bBreak = False : Exit For
                        End If
                    Next
                End If
            Loop Until bBreak
        ElseIf path.Length = 0 Then
            ' ダイアログからファイル名を取得
            d = New OpenFileDialog()
            d.Filter = strFilter
            d.FilterIndex = nFilter
            If d.ShowDialog = DialogResult.OK Then
                strFile = d.FileName
                strCaption = IO.Path.GetFileNameWithoutExtension(strFile)
                nFilter = d.FilterIndex
            End If
        Else
            ' 指定されたファイル名
            strFile = path
            strCaption = IO.Path.GetFileNameWithoutExtension(strFile)
        End If

        If strCaption <> "" Then
            ' ページの取得
            If IsNothing(page) Then
                ' 新規ページ
                page = New TextPage()
                page.Visible = False
                Dim ctrEdit As ExpandedTextControl = page.EditBox
                AddHandler ctrEdit.TextChanged, AddressOf TextPage_TextStateChanged
                AddHandler ctrEdit.SelectionChanged, AddressOf TextPage_TextStateChanged
                AddHandler ctrEdit.OnFileDrop, AddressOf TextPage_OnFileDrop
                TC1.TabPages.Add(page)
            Else
                ' 既存ページ
                page.Visible = False
            End If

            With page
                ' ページの初期設定
                .EditBox.Clear()
                .EditBox.Font = m_font
                .EditBox.SetWordWrap(mnWordwrap.Checked)
                .EditBox.SetTabStops(m_tabwidth)

                ' ファイルの読み込み
                .LoadFile(strFile)
                .Text = strCaption
                .Visible = True
                TC1.SelectedTab = page
                .EditBox.Focus()
            End With

            If strFile <> "" Then UpdateRecentFiles(strFile)
            UpdateInfo(page)
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message, _
            "I/Oエラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Finally
        If Not IsNothing(d) Then d.Dispose()
    End Try
End Sub	

 m_tabwidth(タブ幅)は、ページを設定する時に使用します。0の時は自動的にデフォルト値(第3章)となります。また、関数内の変数"nFilter"は、ダイアログのフィルター番号で、Static宣言をしています。二度目以降にダイアログを開いたときはこの値が適用されます。
 まず、引数"path"の値を調べ、"Nothing"なら新規作成、空文字""ならファイルを開くダイアログボックスを開いてユーザーに選択を求めます。指定されたファイルがあるときはそのまま変数""strFile"と"strCaption"に代入します。
 続いて引数"page"を調べ、"Nothing"の時は、新たにタブページをつくってタブコントロールの追加します。指定のページがある場合は、該当ページ上に新規作成文書をつくるか、ファイルをロードします。
 ページを新たにつくる際に結びつけるイベントは以下の二つです。とりあえず関数だけつくっておくことにします。中身については追々埋めていこうと思います。

' タブページ : テキスト状態の変更イベント 
Private Sub TextPage_TextStateChanged(ByVal sender As Object, ByVal e As EventArgs)
    ' テキストの変更、選択文字列の変更時の処理
End Sub

' タブページ : テキストへのファイルのドラッグドロップ
Private Sub TextPage_OnFileDrop(ByVal e As DragEventArgs)
    ' テキスト部分へファイルがドラッグ&ドロップされた時の処理
End Sub 

PageToFile : ファイルへの書き出し

 次いで、ファイルへの保存です。「上書き保存」、「名前をつけて保存」の両方に対応しています。
 引数"path"が"Noting"、または空文字""の時、「ファイルに保存」ダイアログボックスを開きます。ファイル名に指定があるときは上書き保存。

' PageToFile : 指定ページの内容を指定したファイルに保存
' ... 引数path : パス名。ただし、 [Noting] または[""] でSaveFileDialog を呼び出し
' ... 引数page : 対象ページ。
Public Sub PageToFile(ByVal path As String, ByVal page As TextPage)
    Dim d As SaveFileDialog
    Dim strFilter As String = _
    "テキストファイル(*.txt)|*.txt|リッチテキスト(*.rtf)|*.rtf|HTML(*.html)|*.html|すべてのファイル(*.*)|*.*"
    Try
        If (Not IsNothing(path)) AndAlso IO.File.Exists(path) Then
            ' ファイル名が指定されたとき
            page.SaveFile(path)
            UpdateRecentFiles(path)
        Else
            ' ファイル名の指定がないとき
            d = New SaveFileDialog()
            With d
                .Filter = strFilter
                .OverwritePrompt = False
            End With
            If (d.ShowDialog = DialogResult.OK) AndAlso (d.FileName.Length > 0) Then
                Dim strFile As String = d.FileName    ' ファイル名

                ' 拡張子のチェック
                If IO.Path.GetExtension(strFile) <> "" Then
                    If d.FilterIndex = 1 Then
                        strFile = IO.Path.ChangeExtension(strFile, ".txt")
                    ElseIf d.FilterIndex = 2 Then
                        strFile = IO.Path.ChangeExtension(strFile, ".rtf")
                    ElseIf d.FilterIndex = 3 Then
                        strFile = IO.Path.ChangeExtension(strFile, ".html")
                    End If
                Else
                    strFile += ".txt"
                End If

                ' 既存ファイルのチェック
                Dim bSave As Boolean = True    ' 保存許可
                If IO.File.Exists(strFile) Then
                    Dim msg As String = _
                        "ファイル [" & IO.Path.GetFileName(strFile) & "] は、すでに存在します。" _
                        & vbCrLf & "上書きしますか?"
                    If MessageBox.Show(msg, _
                                "上書きの確認", _
                                MessageBoxButtons.OKCancel, _
                                MessageBoxIcon.Question) _
                            = DialogResult.Cancel Then
                        bSave = False
                    End If
                End If

                If bSave Then
                    page.SaveFile(strFile)
                    page.Text = IO.Path.GetFileNameWithoutExtension(strFile)
                    UpdateInfo(page)
                    UpdateRecentFiles(strFile)
                End If
            End If
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message, "I/Oエラー", _
                MessageBoxButtons.OK, MessageBoxIcon.Error)
    Finally
        If Not IsNothing(d) Then d.Dispose()
    End Try
End Sub

 途中、拡張子をチェックしています。自動付加の対象としているのは".txt"と".rtf"ですが、フィルターの種類共々、そのうち改良して".html"や".css"など、もうちょっと増やしたいと思っています。

| ■HOME | ◆プログラムTop | ▲ページの先頭 | << 前の章 | 次の章 >> |