TreeView拖放帮助-_无效的FORMATETC结构_异常

时间:2020-03-05 18:49:33  来源:igfitidea点击:

我正在尝试将拖放功能实现为TreeView控件。当我在节点上启动拖动时,我得到:

无效的FORMATETC结构(HRESULT的异常:0x80040064(DV_E_FORMATETC))

ItemDrag处理程序(发生异常的地方)如下所示:

private void treeView_ItemDrag(object sender,
        System.Windows.Forms.ItemDragEventArgs e)
{

        this.DoDragDrop(e.Item, DragDropEffects.Move);
}

有谁知道这个问题的根本原因以及如何解决? (.NET 2.0,Windows XP SP2)

解决方案

回答

" FORMATETC"是一种应用程序剪贴板,因为缺少更好的用语。为了产生一些在树节点上拖动的视觉技巧,必须将其及其源代码描述复制到此剪贴板中。源代码控件将其信息加载到" FORMATETC"剪贴板中,并将其发送到目标对象。看起来错误发生在放置而不是拖动上。 DV_E_FORMATETC中的DV通常指示放置步骤中发生的错误。
目的地看起来不像我们要投放的目标。剪贴板可能已损坏,或者放置目标的位置可能无法理解它。

我建议我们尝试以下两种方法之一。

  • 删除原始的树结构和目标。转储dll。关闭所有内容。打开并将树视图和目标放回窗体。它的格式可能不正确,没有完全填充" FORMATETC"结构。
  • 尝试放置另一个树视图并放到该树视图上。如果我们要下降到另一棵树并且它可以工作,则说明橙子对橙子都可以工作,而这不是树视图。如果它是网格或者列表视图,则可能是目的地。我们可能需要更改那些结构才能接收下降。

并非有帮助,但是结构是这样的:

typedef struct tagFORMATETC
{
  CLIPFORMAT      cfFormat;
  DVTARGETDEVICE  *ptd;
  DWORD           dwAspect;
  LONG            lindex;
  DWORD           tymed;
} FORMATETC, *LPFORMATETC;

回答

使用列表和树视图控件进行拖放时,必须确保正确删除和插入列表项。例如,使用涉及三个ListView控件的拖放操作:

private void triggerInstanceList_DragOver(object sender, DragEventArgs e)
    {
        SetDropEffect(e);
    }

    private void triggerInstanceList_DragEnter(object sender, DragEventArgs e)
    {
        SetDropEffect(e);
    }

    private void SetDropEffect(DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(ListViewItem)))
        {
            ListViewItem itemToDrop = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
            if (itemToDrop.Tag is TriggerTypeIdentifier)
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.Move;
        }
        else
            e.Effect = DragDropEffects.None;
    }

    private void triggerInstanceList_DragDrop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(typeof(ListViewItem)))
        {
            try
            {
                ListViewItem itemToDrop = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
                if (itemToDrop.Tag is TriggerTypeIdentifier)
                {
                    ListViewItem newItem = new ListViewItem("<new " + itemToDrop.Text + ">", itemToDrop.ImageIndex);
                    _triggerInstanceList.Items.Add(newItem);
                }
                else
                {
                    _expiredTriggers.Items.Remove(itemToDrop);
                    _triggerInstanceList.Items.Add(itemToDrop);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }
    }

我们会注意到,在DragDrop事件结束时,我将移动ListViewItem或者创建其中一个的副本。