自作ContextMenuStrip

自作ContextMenuStripを自作する機会があり、

上のメニューから
元に戻す、切り取り、コピー、貼り付け、削除、すべて選択
を実装したContextMenuStripを作成した。

参考:TextBox(またはRichTextBox)でコピー、切り取り、貼り付け、元に戻すを行う: .NET Tips: C#, VB.NET
から「元に戻す、切り取り、コピー、貼り付け」をそのまま使用。

削除、すべて選択は以下。

'削除
Private Sub deleteMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles deleteMenu.Click
   TextBox1.Text = TextBox1.Text.Remove(TextBox1.SelectionStart,TextBox1.SelectionLength)
End Sub


’すべて選択
Private Sub selectMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles selectMenu.Click
  TextBox1.SelectAll()
End Sub

これをテキストボックス上で使うとき、
まず、マウスダウンイベントで、標準のContextMenuを使えなくし、
今回作ったContextMenuStrip(cmsDisp)を使用する。

Private Sub TextBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
   Dim mp As Point
    If e.Button = Windows.Forms.MouseButtons.Right Then
     '右クリックコントロール外、無効処理
     TextBox1.Capture = False
     
     TextBox1.ContextMenuStrip = cmsDisp
     mp = Windows.Forms.Control.MousePosition
     'ContextMenuStripをマウスカーソルの位置に表示
     Me.cmsDisp.Show(mp)
     
     If TextBox1.Text.Length = 0 Then
      MenuEnabled(EnableMode.StrNo)
     ElseIf TextBox1.SelectionLength = 0 Then
      Call MenuEnabled(EnableMode.SelectNo)
     ElseIf TextBox1.SelectionLength = TextBox1.Text.Length Then
      Call MenuEnabled(EnableMode.SelectAll)
     ElseIf TextBox1.SelectionLength > 0 Then
      Call MenuEnabled(EnableMode.Normal)
     End If
   End If

End Sub

「TextBox1.Capture = False」は
テキストフィールド上で右クリックして、テキストフィールド外で
右クリックを離したときに標準のContextMenuが表示されるのを防いだもの。
最初、このミスに気付かなかったので、危なかった。

MenuEnabledでContextMenuStripのメニューの選択可否を切り替える
以下の変数はあらかじめ宣言済みとする。
 Enum EnableMode
   StrNo = 0 '文字列無し
   SelectNo = 1 '選択文字列無し
   SelectAll = 2 '文字列戦選択
   Normal = 3 '文字列選択あり
 End Enum

  Private Sub MenuEnabled(ByVal strEnable As EnableMode)
  Dim data As IDataObject
 
  'テキストボックスの文字列の状態から
  'ContextMenuのメニュー表示切替を行う
  Select Case strEnable
 Case EnableMode.StrNo
    '文字列なし
    cutMenu.Enabled = False
    copyMenu.Enabled = False
    deleteMenu.Enabled = False
    selectMenu.Enabled = False
  Case EnableMode.SelectNo
    '文字列あり、選択なし
    cutMenu.Enabled = False
    copyMenu.Enabled = False
    deleteMenu.Enabled = False
    selectMenu.Enabled = True
  Case EnableMode.SelectAll
    '文字列全選択
    cutMenu.Enabled = True
      copyMenu.Enabled = True
      deleteMenu.Enabled = True
      selectMenu.Enabled = False
  Case EnableMode.Normal
  '文字列あり、選択有り(全て選択していない)
      cutMenu.Enabled = True
      copyMenu.Enabled = True
      deleteMenu.Enabled = True
      selectMenu.Enabled = True
 End Select
 
 If TextBox1.CanUndo = True Then
    '元に戻すことができるか調べる
    undoMenu.Enabled = True
 Else
    undoMenu.Enabled = False
 End If
 
 data = Clipboard.GetDataObject()
 If (IsNothing(data) = False) AndAlso (data.GetDataPresent(DataFormats.Text) = True) Then
     'クリップボードにテキストデータがあるときは貼り付けメニュー有効
     pasteMenu.Enabled = True
 Else
    pasteMenu.Enabled = False
 End If
 
  End Sub

(上の処理にReadOnly時の時の処理も必要・今回は省略)

作成結果が以下。