RichTextBox for WPF
ヒットテスト
RichTextBox for WPF の使い方 > ヒットテスト

C1RichTextBox は、ユーザーの対話式操作を実装するための標準メカニズムとしてハイパーリンクをサポートします。さらに、カスタムのマウス対話機能を追加して提供することもできます。たとえば、ユーザーが要素をクリックしたときに、カスタム書式を適用したり、コンテキストメニューを表示することができます。

このようなシナリオを可能にするために、C1RichTextBox には、ElementMouse* イベントと GetPositionFromPoint メソッドが公開されています。

マウスイベントをトリガした要素を確認するだけでよい場合は、イベントハンドラの source パラメータから取得できます。より詳細な情報(要素内でクリックされた単語など)が必要な場合は、GetPositionFromPoint メソッドが必要です。GetPositionFromPoint はクライアント座標でポイントを受け取り、その位置をドキュメント座標で表す C1TextPosition オブジェクトを返します。

C1TextPosition オブジェクトには、ElementOffset という2つの主要なプロパティがあります。Element プロパティはドキュメント内の要素を表し、Offset プロパティは文字インデックス(要素が C1Run の場合)または指定されたポイントにある子要素のインデックスです。

たとえば、次のコードは、C1RichTextBox を作成し、ハンドラを ElementMouseLeftButtonDown イベントに関連付けます。

コードのコピー
Public Sub New()
  ' デフォルトの初期化
   InitializeComponent()
  ' C1RichTextBox を作成してページに追加します
   _rtb = New C1RichTextBox()
   LayoutRoot.Children.Add(_rtb)
  ' イベントハンドラを関連付けます
   Add Handler _rtb.ElementMouseLeftButtonDown AddressOf rtb_ElementMouseLeftButtonDown
End Sub
コードのコピー
public MainPage()
{
  // デフォルトの初期化
  InitializeComponent();
  // C1RichTextBox を作成してページに追加します
  _rtb = new C1RichTextBox();
  LayoutRoot.Children.Add(_rtb);
  // イベントハンドラを関連付けます
  _rtb.ElementMouseLeftButtonDown += rtb_ElementMouseLeftButtonDown;
}

次のイベントハンドラは、クリックされた要素全体に対して FontWeight プロパティを切り替えます。この要素は、単語、文、または段落全体の場合もあります。

コードのコピー
Private Sub _rtb_ElementMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
   If Keyboard.Modifiers <> 0 Then
       Dim run = TryCast(sender, C1Run)
       If run IsNot Nothing Then
           run.FontWeight = If(run.FontWeight = FontWeights.Bold, FontWeights.Normal, FontWeights.Bold)
       End If
   End If
End Sub
コードのコピー
void _rtb_ElementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.Modifiers != 0)
  {
   var run = sender as C1Run;
   if (run != null)
   {
     run.FontWeight = run.FontWeight == FontWeights.Bold
       ? FontWeights.Normal
       : FontWeights.Bold;
   }
  }
}

このコードは、sender パラメータを C1Run オブジェクトにキャストして、クリックされた要素を取得します。

単語の FontWeight valueを切り替える場合は、クリックされた文字を特定してから選択範囲を単語全体に拡張する必要があります。ここで GetPositionFromPoint メソッドが必要になります。次に、これを行うイベントハンドラの改訂バージョンを示します。

コードのコピー
Private Sub _rtb_ElementMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
   If Keyboard.Modifiers <> 0 Then
      ' コントロール座標で位置を取得します
       Dim pt = e.GetPosition(_rtb)
      ' その位置のテキストポインタを取得します
       Dim pointer = _rtb.GetPositionFromPoint(pt)
     ' ポインタが C1Run をポイントしていることを確認します
       Dim run = TryCast(pointer.Element, C1Run)
       If run IsNot Nothing Then
          ' C1Run 内の単語を取得します
           Dim text = run.Text
           Dim start = pointer.Offset
           Dim [end] = pointer.Offset
           While start > 0 AndAlso Char.IsLetterOrDigit(text, start - 1)
               start -= 1
           End While
           While [end] < text.Length - 1 AndAlso Char.IsLetterOrDigit(text, [end] + 1)
               [end] += 1
           End While
          ' クリックされたランの太字プロパティを切り替えます
           Dim word = New C1TextRange(pointer.Element, start, [end] - start + 1)
           word.FontWeight = If(word.FontWeight.HasValue AndAlso word.FontWeight.Value = FontWeights.Bold, FontWeights.Normal, FontWeights.Bold)
       End If
   End If
End Sub
コードのコピー
void _rtb_ElementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.Modifiers != 0)
{
  // コントロール座標で位置を取得します
   var pt = e.GetPosition(_rtb);
  // その位置のテキストポインタを取得します
   var pointer = _rtb.GetPositionFromPoint(pt);
  // ポインタが C1Run をポイントしていることを確認します
   var run = pointer.Element as C1Run;
   if (run != null)
   {
     // C1Run 内の単語を取得します
     var text = run.Text;
    var start = pointer.Offset;
     var end = pointer.Offset;
     while (start > 0 && char.IsLetterOrDigit(text, start - 1))
       start--;
     while (end < text.Length - 1 && char.IsLetterOrDigit(text, end + 1))
       end++;
     // クリックされたランの太字プロパティを切り替えます
     var word = new C1TextRange(pointer.Element, start, end - start + 1);
     word.FontWeight =
       word.FontWeight.HasValue && word.FontWeight.Value == FontWeights.Bold
         ? FontWeights.Normal
       : FontWeights.Bold;
   }
}
}

FontWeight プロパティは、null 可能な値を返します。この範囲内で、この属性に複数の値が混ざって含まれる場合、このプロパティは null を返します。FontWeight プロパティを切り替えるために使用するコードは、以前に書式設定ツールバーを実装したときに使用したコードと同じです。

GetPositionFromPoint を使用すると、画面上のポイントから C1TextPosition オブジェクトを取得できます。GetRectFromPosition メソッドは逆の操作を実行します。すなわち、C1TextPosition オブジェクトの画面上の位置を表す Rect を返します。これは、ドキュメントの特定部分の近くに UI 要素を表示するような場合に役立ちます。