タブ式テキストエディタ(10) 編集メニューの実装

 編集メニューをコーディングしていきます。ただし、検索と置換は、いっぺんにやると大変なので次回まとめてつくることにします。

テキストの整形

 テキストの整形関係のメニューは、ExpandedTextControlクラスをつくった時とほぼ同じ内容になります。変換メニューだけがこちらだけの機能となっています。横着して一つの関数で処理しています。

' 編集メニュー : 元に戻す
Private Sub mnUndo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnUndo.Click
    If Not IsNothing(TC1.SelectedTab) Then
        With DirectCast(TC1.SelectedTab, TextPage).EditBox
            .Undo()
            .ClearUndo()
        End With
    End If
End Sub

' 編集メニュー : 切り取り
Private Sub mnCut_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnCut.Click
    If Not IsNothing(TC1.SelectedTab) Then
        DirectCast(TC1.SelectedTab, TextPage).EditBox.Cut()
    End If
End Sub

' 編集メニュー : コピー
Private Sub mnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnCopy.Click
    If Not IsNothing(TC1.SelectedTab) Then
        DirectCast(TC1.SelectedTab, TextPage).EditBox.Copy()
    End If
End Sub

' 編集メニュー : 貼り付け
Private Sub mnPaste_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnPaste.Click
    If Not IsNothing(TC1.SelectedTab) Then
        DirectCast(TC1.SelectedTab, TextPage).EditBox.Paste()
    End If
End Sub

' 編集メニュー : 削除
Private Sub mnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnDelete.Click
    If Not IsNothing(TC1.SelectedTab) Then
        DirectCast(TC1.SelectedTab, TextPage).EditBox.SelectedText = ""
    End If
End Sub

' 編集メニュー : すべて選択
Private Sub mnSelectAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnSelectAll.Click
    If Not IsNothing(TC1.SelectedTab) Then
        DirectCast(TC1.SelectedTab, TextPage).EditBox.SelectAll()
    End If
End Sub 

' 編集メニュー : 変換
Private Sub mnCUpper_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnCUpper.Click, mnCLower.Click, mnCProper.Click, _
                mnCWide.Click, mnCNarrow.Click, mnCHira.Click, mnCKata.Click
    Dim nIndex As Integer = DirectCast(sender, MenuItem).Index  ' メニュー番号
    Dim ctrEdit As ExpandedTextControl = DirectCast(TC1.SelectedTab, TextPage).EditBox
    Dim nStrConv As VbStrConv = VbStrConv.None  ' 変換方法
    Select Case nIndex
        Case 0 : nStrConv = VbStrConv.UpperCase    ' 大文字変換
        Case 1 : nStrConv = VbStrConv.LowerCase    ' 小文字変換
        Case 2 : nStrConv = VbStrConv.ProperCase    ' プロパー変換
        Case 3 : nStrConv = VbStrConv.Wide    ' 全角変換
        Case 4 : nStrConv = VbStrConv.Narrow    ' 半角変換
        Case 5 : nStrConv = VbStrConv.Hiragana    ' ひらがな変換
        Case 6 : nStrConv = VbStrConv.Katakana    ' カタカナ変換
    End Select
    ' 選択部分のテキストを入れ替え
    ctrEdit.SelectedText = StrConv(ctrEdit.SelectedText, nStrConv)
End Sub

指定した行へ移動

 指定した行への移動はダイアログボックスを使います。ダイアログボックスを開いて、取得した値に基づいて行を移動させています。諸関数はリッチテキストの章で設定したオリジナルのものも含まれます。ダイアログボックスについては次の項を参照してください。

   ' 編集メニュー : 指定行へ移動
Private Sub miJump_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles mnJump.Click
    Dim ctrEdit As ExpandedTextControl = DirectCast(TC1.SelectedTab, TextPage).EditBox
    Dim nMax As Integer = ctrEdit.GetLineCount    ' 行数
    Dim d As New NumericDialog("指定行へ移動", "行目へ移動(全" & nMax.ToString & "行)")
    Try
        Dim nLine, nChar As Integer
        nChar = ctrEdit.SelectionStart    ' 現在の文字の位置
        nLine = ctrEdit.GetLineIndex(nChar)  ' nCharがある行の位置
        d.SetValues(ctrEdit.GetLineCount, 1, nLine + 1)  'ダイアログにデータをセット 
        If d.ShowDialog(Me) = DialogResult.OK Then
            ctrEdit.ScrollToLine(d.Value - 1)    ' キャレットを移動
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message, "行指定エラー", _
                MessageBoxButtons.OK, MessageBoxIcon.Error)
    Finally
        d.Dispose()
    End Try
End Sub

数値指定ダイアログをつくる

 数値指定ダイアログは、手抜きをして他のメニューでも使い回しができるようにつくります。コンストラクタでタイトルと説明文字列を設定して、"SetValues"関数で上限値や下限値を指定するようにします。例によってデザイナを使っていませんので、記述が長めになっています。

Public Class NumericDialog
    Inherits System.Windows.Forms.Form

    ' 変数
    WithEvents lb1 As System.Windows.Forms.Label      ' 説明表示用ラベル
    WithEvents en1 As System.Windows.Forms.TextBox    ' 入力用テキストボックス
    WithEvents bnOK As System.Windows.Forms.Button    ' OKボタン
    WithEvents bnCancel As System.Windows.Forms.Button  ' キャンセルボタン
    Private m_notes As String = ""        ' 単位の説明の文字列
    Private m_value As Integer = 0        ' 設定した値
    Private m_max As Integer = Integer.MaxValue    ' 入力の上限値
    Private m_min As Integer = Integer.MinValue    ' 入力の下限値

    ' プロパティ
    Public Property Notes() As String
        Get
            Return m_notes
        End Get
        Set(ByVal Value As String)
            m_notes = Value
        End Set
    End Property

    Public Property Value() As Integer
        Get
            Return m_value
        End Get
        Set(ByVal Value As Integer)
            m_value = Value
        End Set
    End Property

    Public Property MaxValue() As Integer
        Get
            Return m_max
        End Get
        Set(ByVal Value As Integer)
            m_max = Value
        End Set
    End Property

    Public Property MinValue() As Integer
        Get
            Return m_min
        End Get
        Set(ByVal Value As Integer)
            m_min = Value
        End Set
    End Property

    ' New コンストラクタ
    ' ... 引数caption : ダイアログのタイトル
    ' ... 引数notes  :  説明表示用文字列
    Public Sub New(ByVal caption As String, ByVal notes As String)
        MyBase.New()
        InitializeControls()
        Me.Text = caption
        m_notes = notes
    End Sub

    ' InitializeControls : コントロールの初期化
    Private Sub InitializeControls()
        Me.lb1 = New System.Windows.Forms.Label()
        Me.en1 = New System.Windows.Forms.TextBox()
        Me.bnOK = New System.Windows.Forms.Button()
        Me.bnCancel = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        With lb1
            .Name = "lb1"
            .Location = New System.Drawing.Point(62, 8)
            .Size = New System.Drawing.Size(148, 20)
            .TabIndex = 0
            .TextAlign = System.Drawing.ContentAlignment.MiddleLeft
        End With
        With en1
            .Name = "en1"
            .Location = New System.Drawing.Point(8, 8)
            .Size = New System.Drawing.Size(52, 19)
            .TabIndex = 1
            .Text = ""
            .TextAlign = HorizontalAlignment.Center
        End With
        With bnOK
            .Name = "bnOK"
            .FlatStyle = FlatStyle.System
            .Location = New System.Drawing.Point(196, 8)
            .Size = New System.Drawing.Size(72, 22)
            .TabIndex = 2
            .Text = "OK"
        End With
        With bnCancel
            .Name = "bnCancel"
            .FlatStyle = FlatStyle.System
            .Location = New System.Drawing.Point(196, 36)
            .Size = New System.Drawing.Size(72, 22)
            .TabIndex = 3
            .Text = "キャンセル"
        End With
        Me.AutoScaleBaseSize = New Size(5, 12)
        Me.ClientSize = New Size(278, 64)
        Me.Controls.AddRange(New Control() {Me.bnCancel, Me.bnOK, Me.en1, Me.lb1})
        Me.FormBorderStyle = FormBorderStyle.FixedToolWindow
        Me.Name = "NumericDialog"
        Me.StartPosition = FormStartPosition.CenterParent
        Me.AcceptButton = bnOK
        Me.CancelButton = bnCancel
        Me.Text = "数値の指定"
        Me.ResumeLayout(False)
    End Sub

    ' ロード
    Private Sub Dialog_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
            Handles MyBase.Load
        lb1.Text = m_notes
        With en1
            .Text = m_value.ToString
            .MaxLength = 11
            .ImeMode = ImeMode.NoControl
            .Focus()
        End With
        bnOK.CausesValidation = True
    End Sub

    ' 値を設定
    ' ... 引数max : 入力の上限値
    ' ... 引数min : 入力の下限値
    ' ... 引数current : 現在の値
    Public Sub SetValues(ByVal max As Integer, ByVal min As Integer, ByVal current As Integer)
        m_max = max
        m_min = min
        m_value = current
    End Sub

    ' OKボタン
    Private Sub bnOK_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
            Handles bnOK.Click
        Dim msg As String = ""
        If IsNumeric(en1.Text) Then
            Dim nValue As Integer = CInt(en1.Text)
            If nValue < m_min Or nValue > m_max Then
                msg = "範囲外の値です。(範囲 :" & m_min & "〜" & m_max & ")"
                MessageBox.Show(msg, "入力エラー", _
                        MessageBoxButtons.OK, MessageBoxIcon.Error)
                en1.Focus()
                en1.SelectAll()
            Else
                m_value = nValue
                Me.DialogResult = DialogResult.OK
            End If
        Else
            msg = "整数の値を入力してください。"
            MessageBox.Show(msg, "入力エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
            en1.Focus()
            en1.SelectAll()
        End If
    End Sub

    ' キャンセルボタン
    Private Sub bnCancel_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
            Handles bnCancel.Click
        Me.DialogResult = DialogResult.Cancel
    End Sub
End Class

編集メニューの保守

 編集メニューの使用可・不可の切り替えをコーディングします。「検索・置換」メニューと「すべて選択」メニューは、テキストを取得する必要がありますが、textプロパティやlinesプロパティで取得するとアンドゥデータが消えてしまうので、Win32APIの力を借りて実現しています。第3章でつくった関数で対応しています。

' 編集メニュー
Private Sub mnEdit_Select(ByVal sender As System.Object, ByVal e As System.EventArgs) _
            Handles mnEdit.Select
    Dim p As TextPage = DirectCast(TC1.SelectedTab, TextPage)

    If Not IsNothing(p) Then
        Dim nLineCount As Integer = p.EditBox.GetLineCount
        Dim nLineLength As Integer = p.EditBox.GetLineLength(0)

        mnUndo.Enabled = p.EditBox.CanUndo
        mnCut.Enabled = Not p.EditBox.SelectedText.Equals("")
        mnCopy.Enabled = Not p.EditBox.SelectedText.Equals("")
        mnPaste.Enabled = Clipboard.GetDataObject.GetDataPresent(DataFormats.Text) _
                                OrElse Clipboard.GetDataObject.GetDataPresent(DataFormats.Rtf)
        mnDelete.Enabled = Not p.EditBox.SelectedText.Equals("")
        mnFind.Enabled _
                = (Not (nLineCount + nLineLength).Equals(1)) AndAlso (Not FindDialog.Exists)
        mnJump.Enabled = Not (nLineCount <= 1)
        mnConvert.Enabled = Not p.EditBox.SelectedText.Equals("")
        mnSelectAll.Enabled = Not (nLineCount + nLineLength).Equals(1)
    End If
End Sub 
| ■HOME | ◆プログラムTop | ▲ページの先頭 | << 前の章 | 次の章 >> |