現在開いているファイルに変更が加えられたかどうかは、"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
表示箇所は二箇所。ステータスバーパネル(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("綴り帖")>
前回つくった"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 : 最近使ったファイルメニューの更新
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