tags:

views:

772

answers:

2

Hi,

I'm trying to implement Drag & Drop functionality with source being a TreeView control. When I initiate a drag on a node, I'm getting:

Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))

The ItemDrag handler (where the exception takes place), looks like:

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

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

Does anyone know the root cause of this and how to remedy it? (.NET 2.0, Windows XP SP2)

A: 

FORMATETC is a type of application clipboard, for lack of a better term. In order to pull off some of the visual tricks of draging around the tree node, it has to be copied into this clipboard with its source description. The source control loads its info into the FORMATETC clipboard and sends it to the target object. It looks like the error occurs on the drop and not on the drag. The DV in DV_E_FORMATETC typically indicates the error occurrs on the drop step.
The destination doesn't look like it likes what you are droping on it. The clipboard may be corrupt or the drop destination may not be configured to understand it.

I recommend you try one of two things.

  1. Remove the original tree structure and destination. Dump your dlls. Close everything. Open up and put the treeview and destination back on the form. It may have just been poorly formed and not fully populating the FORMATETC structure.
  2. Try putting another treeview and droping to that. If you are droping to another tree and it works you know your oranges to oranges work and it isn't the treeview. It may be the destination if it is a grid or listview. You may need to change those structures to be able to receive the drop.

Not that it helps but the structure is something like this:

typedef struct tagFORMATETC
{
  CLIPFORMAT      cfFormat;
  DVTARGETDEVICE  *ptd;
  DWORD           dwAspect;
  LONG            lindex;
  DWORD           tymed;
} FORMATETC, *LPFORMATETC;
Stradas
You're giving a c/c++ answer to a c# question.
dviljoen
You misunderstood the answer. This is how the FORMATETC is constructed in windows. The code of the answer is not an answer it is how the object having the error is built. The clipboard is not written in C#, it is written in C++ and is a part of windows. The error is local to windows and there is no C# code in that object. This is the code that of the object having the error. I answer is the text above the code. The solution is in replacing the .DLLs with the newer library.
Stradas
+1  A: 

When doing drag and drop with list and treeview controls you have to make sure that you removing and inserting the list items correctly. For example, using drag and drop involving three ListView controls:

    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);
            }
        }
    }

you will note that at the end of the DragDrop event I am either moving the ListViewItem or creating a copy of one.

Joe Caffeine