将文本拖放到特定的鼠标位置 - 显示插入符号或位置指示器

EGS*_*GSL 6 c# treeview textbox drag-and-drop winforms

我正在将一个项目从 a 粘贴TreeView到 a TextBox,但我想将该项目粘贴到鼠标的当前位置,并显示一个插入符号,如下图所示。带插入符号的图像: 例子

这是我的代码:

private void tvOperador_ItemDrag(object sender, ItemDragEventArgs e)
{
    var node = (TreeNode)e.Item;
    if (node.Level > 0)
    {
        DoDragDrop(node.Text, DragDropEffects.Copy);
    }
}
private void txtExpresion_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(string))) e.Effect = DragDropEffects.Copy;
}
private void txtExpresion_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(System.String)))
    {
        string Item = (System.String)e.Data.GetData(typeof(System.String));
        string[] split = Item.Split(':');

        txtExpresion.Text += split[1];
    }
}
Run Code Online (Sandbox Code Playgroud)

TaW*_*TaW 5

这很棘手,因为该操作会捕获Drag&Drop鼠标,因此您无法使用鼠标事件。

一种方法是设置一个Timer来完成这项工作......:

    Timer cursTimer = new Timer();

    void cursTimer_Tick(object sender, EventArgs e)
    {
        int cp = txtExpresion.GetCharIndexFromPosition(
                 txtExpresion.PointToClient(Control.MousePosition));
        txtExpresion.SelectionStart = cp;
        txtExpresion.SelectionLength = 0; 
        txtExpresion.Refresh();
    }
Run Code Online (Sandbox Code Playgroud)

Timer使用该函数Control.MousePosition每 25 毫秒左右确定光标位置,设置插入符并更新TextBox.

在您的事件中,您初始化它并确保它TextBox具有焦点;最后在当前选择处添加字符串:

    private void txtExpresion_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(string)))
        {
            e.Effect = DragDropEffects.Copy;
            txtExpresion.Focus();
            cursTimer = new Timer();
            cursTimer.Interval = 25;
            cursTimer.Tick += cursTimer_Tick;
            cursTimer.Start();
        }
    }

    private void txtExpresion_DragDrop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(System.String)))
        {
            cursTimer.Stop();

            string Item = (System.String)e.Data.GetData(typeof(System.String));
            string[] split = Item.Split(':');

            txtExpresion.SelectedText = split[1]
        }
    }
Run Code Online (Sandbox Code Playgroud)

解决这个问题的另一种方法是不使用普通的拖放,只对鼠标事件进行编码,但这个方法在我的第一次测试中工作正常。

更新

虽然上述解决方案确实有效,但使用 aTimer似乎不太优雅DragOver正如礼萨的回答所示,使用该事件要好得多。但与其绘制光标,为什么不做真正的事情,即控制实际的工字梁..?

DragOver事件在移动过程中一直被调用,因此它的工作方式非常类似于MousMove:所以这里是两个解决方案的合并,我认为这是最好的方法:

private void txtExpresion_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(System.String)))
    {
        string Item = (System.String)e.Data.GetData(typeof(System.String));
        string[] split = Item.Split(':');
        txtExpresion.SelectionLength = 0;
        txtExpresion.SelectedText = split[1];
    }
}

private void txtExpresion_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(string)))
    {
        e.Effect = DragDropEffects.Copy;
        txtExpresion.Focus();
    }
}

private void txtExpresion_DragOver(object sender, DragEventArgs e)
{
    int cp = txtExpresion.GetCharIndexFromPosition(
                          txtExpresion.PointToClient(Control.MousePosition));
    txtExpresion.SelectionStart = cp;
    txtExpresion.Refresh();

}
Run Code Online (Sandbox Code Playgroud)