2009-05-27 16 views
1

私は、ツリーフォームと複数行のテキストボックスをWindowsフォームの同じフォームにまとめています。 TreeViewからノードをテキストボックスにドラッグしてテキストボックスにテキストを挿入できるようにドラッグアンドドロップ設定があります(これは動作しています)。ドロップを受け入れるときにテキストボックスにキャレットを挿入する方法

これは、マウスをテキストボックスの上にドラッグすると、何らかのインジケータがテキストを通って移動し、テキストが挿入される場所を示し、ドロップされたときにその位置に挿入されるようにしたいと考えています。現在、私はSelectionStartにテキストを置いていますが、ドラッグ操作でSelectionStartは更新されないため、最後にカーソルがあった場所に移動します。私はあなたがtextBox1_DragOverイベントを処理を見てみたいと思います

private void treeView1_ItemDrag(object sender, ItemDragEventArgs e) 
    { 
     if (e.Button != MouseButtons.Left) 
      return; 

     object item = e.Item; 
     treeView1.DoDragDrop(((TreeNode)item).Tag.ToString(), DragDropEffects.Copy | DragDropEffects.Scroll); 
    } 

    private void textBox1_DragEnter(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent(DataFormats.StringFormat)) 
     { 
      e.Effect = DragDropEffects.Copy | DragDropEffects.Scroll; 
     } 
     else 
     { 
      e.Effect = DragDropEffects.None; 
     } 
    } 

    private void textBox1_DragDrop(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent(DataFormats.StringFormat)) 
     { 
      textBox1.SelectionLength = 0; 
      textBox1.SelectedText = (string)e.Data.GetData(DataFormats.StringFormat); 
     } 
    } 
+0

これは私が探していたものです。ありがとう! –

答えて

3

は、ここに私の現在のコードです。 DragOverイベント引数に含まれるマウスの位置を 'textBox1.GetCharIndexFromPosition()'に渡します。

キャレットの位置を設定するには、チャーの位置を使用できる必要があります。ここで

は(最後に余分な1)文字があるよりも、1つの余分キャレット位置があるとしてGetCharIndexFromPositionは(当然)が、1つのキャレット位置が欠落しているように、これは実際には本当に刺激する GetCharIndexFromPosition

2

のドキュメントです。これを使用して、DragOverでSelectionStartを設定し、DragDropでInsertを設定します。

private int GetCaretIndexFromPoint(TextBox tb, int x, int y) 
    { 
     Point p = tb.PointToClient(new Point(x, y)); 
     int i = tb.GetCharIndexFromPosition(p); 
     if (i == tb.Text.Length - 1) 
     { 
      Point c = tb.GetPositionFromCharIndex(i); 
      if (p.X > c.X) 
       i++; 
     } 
     return i; 
    } 

完璧ではありませんが、それは仕事をします。誰かがネイティブバージョンを見つけた場合は、私に教えてください:)

+0

本当に非常に刺激的です。私はこれを試してみなければならないかもしれない。私の回避策は、開始ドラッグ時に余分なスペースを追加するだけで、テキストの最後にドロップしてからドロップするとスペースを削除できるようにしました。 –

8

ドラッグドロップに関するこれらのアドバイスには、テキストキャレットが表示されています。結局のところ、私はあなたが単にコントロールに焦点を設定する必要があることがわかった!したがって、textBox1.DragOverイベントハンドラの最終コードは次のようになります。私は、このソリューションのWPFの実装を探していたとものを見つけることができませんでした

/// <summary> 
/// Gives visual feedback where the dragged text will be dropped. 
/// </summary> 
private void textBox1_DragOver(Object sender, System.Windows.Forms.DragEventArgs e) 
{ 
    // fake moving the text caret 
    textBox1.SelectionStart = GetCaretIndexFromPoint(textBox1, e.X, e.Y); 
    textBox1.SelectionLength = 0; 
    // don't forget to set focus to the text box to make the caret visible! 
    textBox1.Focus(); 
} 

/// <remarks> 
/// GetCharIndexFromPosition is missing one caret position, as there is one extra caret 
/// position than there are characters (an extra one at the end). 
/// </remarks> 
private int GetCaretIndexFromPoint(System.Windows.Forms.TextBox box, int x, int y) 
{ 
    Point realPoint = box.PointToClient(newPoint(x, y)); 
    int index = box.GetCharIndexFromPosition(realPoint); 
    if (index == box.Text.Length - 1) 
    { 
     Point caretPoint = box.GetPositionFromCharIndex(index); 
     if (realPoint.X > caretPoint.X) 
     { 
      index += 1; 
     } 
    } 
    return index; 
} 
1

:私は前の回答からGetCaretIndexFromPoint機能が含まれています。したがって、次のように実装されます(元のソリューション作成者のクレジット)。 WPF版を探している人に役立つことを願っています。

/// <summary> 
    /// Handles the Preview DragOver event to set the textbox selection at the precise place where the user dropped the dragged text 
    /// </summary> 
    private static void element_PreviewDragOver(object sender, DragEventArgs dragEventArgs) 
    { 
     TextBox textBox = sender as TextBox; 
     if (textBox != null && dragEventArgs != null) 
     { 
      // Set the caret at the position where user ended the drag-drop operation 
      Point dropPosition = dragEventArgs.GetPosition(textBox); 

      textBox.SelectionStart = GetCaretIndexFromPoint(textBox, dropPosition); 
      textBox.SelectionLength = 0; 

      // don't forget to set focus to the text box to make the caret visible! 
      textBox.Focus(); 
      dragEventArgs.Handled = true; 
     } 
    } 

    /// <summary> 
    /// Gets the caret index of a given point in the given textbox 
    /// </summary> 
    /// <param name="textBox"></param> 
    /// <param name="point"></param> 
    /// <returns></returns> 
    private static int GetCaretIndexFromPoint(TextBox textBox, Point point) 
    { 
     int index = textBox.GetCharacterIndexFromPoint(point, true); 

     // GetCharacterIndexFromPoint is missing one caret position, as there is one extra caret position than there are characters (an extra one at the end). 
     // We have to add that caret index if the given point is at the end of the textbox 
     if (index == textBox.Text.Length - 1) 
     { 
      // Get the position of the character index using the bounding rectangle 
      Rect caretRect = textBox.GetRectFromCharacterIndex(index); 
      Point caretPoint = new Point(caretRect.X, caretRect.Y); 

      if (point.X > caretPoint.X) 
      { 
       index += 1; 
      } 
     } 
     return index; 
    } 

    /// <summary> 
    /// Handler for preview drag event in a textbox 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="dragEventArgs"></param> 
    private static void element_PreviewDrop(object sender, DragEventArgs dragEventArgs) 
    { 
     TextBox textBox = sender as TextBox; 
     if (textBox != null && dragEventArgs != null && dragEventArgs.Data != null && dragEventArgs.Data.GetDataPresent(DataFormats.StringFormat)) 
     { 
      string newText = dragEventArgs.Data.GetData(DataFormats.StringFormat) as string; 
      if (!string.IsNullOrEmpty(newText)) 
      { 
       // do your custom logic here 
       textBox.Focus(); 
      } 
      dragEventArgs.Handled = true; 
     } 
    } 
1

(メモ帳)などの一般的なツールの動作をエミュレートする、GetCaretIndexFromPoint()関数は、両方のX及びY座標をチェックしなければなりません。

/// <summary> 
/// Gives visual feedback where the dragged text will be dropped. 
/// </summary> 
private void textBox1_DragOver(Object sender, System.Windows.Forms.DragEventArgs e) 
{ 
    // fake moving the text caret 
    textBox1.SelectionStart = GetCaretIndexFromPoint(textBox1, e.X, e.Y); 
    textBox1.SelectionLength = 0; 
    // don't forget to set focus to the text box to make the caret visible! 
    textBox1.Focus(); 
} 

/// <remarks> 
/// GetCharIndexFromPosition is missing one caret position, as there is one extra caret 
/// position than there are characters (an extra one at the end). 
/// </remarks> 
private int GetCaretIndexFromPoint(System.Windows.Forms.TextBox box, int x, int y) 
{ 
    Point realPoint = box.PointToClient(new Point(x, y)); 
    int index = box.GetCharIndexFromPosition(realPoint); 
    if (index == box.Text.Length - 1) 
    { 
     Point caretPoint = box.GetPositionFromCharIndex(index); 
     if ((realPoint.X > caretPoint.X) || (realPoint.Y > caretPoint.y)) 
     { 
      index += 1; 
     } 
    } 
    return index; 
} 

テキストボックス内の最後の文字がテキストの行の後に新しい行で、あなたは以下の対とcaretPointの右側にcaretPointの左下とにテキストをドロップする場合は、違いを見ることができます。

彼の優れた答えは、user468106にありがとうございます!

関連する問題