I know this is a rather old topic, but I still have a problem with drag&drop
in .NET 2.0: Any stream contents provided in the dropped data seem to be
empty (the stream has the correct size, but all bytes are zero).
To evaluate this I wrote a small sample app in C# which generically browses
the contents of the DragEventArgs and converts all streams in Strings,
replacing null bytes by dots.
Then I did the same in C++ and voilà : The stream contents could be read. It
appears that the problem exists only for REAL streams (content of type
TYMED_ISTREAM). In C# also content data of type TYMED_HGLOBAL is represented
as a MemoryStream (with the correct content).
I tested both applications by dragging/dropping Outlook mail items.
So far I couldn't find anything on this topic in the net, so maybe someone
can help me with it?
Here ist the C# code:
private void OnDragDrop( object sender, DragEventArgs e )
{
string[] types = e.Data.GetFormats( true );
listBox1.Items.Clear();
for (int i = 0; i < types.Length; i++) {
object ob = e.Data.GetData( types[ i ] );
if( ob != null && ob is System.IO.Stream )
{
System.IO.Stream stream = ( System.IO.Stream ) ob;
byte[] buffer = new byte[ stream.Length ];
stream.Seek( 0, System.IO.SeekOrigin.Begin );
int read = stream.Read( buffer, 0, buffer.Length );
StringBuilder b = new StringBuilder( types[ i ] );
b.Append( ':' );
for( int j = 0; j < buffer.Length; j++ )
{
b.Append( buffer[ j ] == 0 ? '.' : Convert.ToChar(
buffer[ j ] ) );
}
listBox1.Items.Add( b.ToString() );
}
else
{
StringBuilder b = new StringBuilder( types[ i ] );
if( ob == null )
{
b.Append( ": null" );
}
else
{
b.Append( ":" + ob.GetType() );
}
listBox1.Items.Add( b.ToString() );
}
}
}
And here the lenghty C++ code:
HRESULT __stdcall clsDropTarget:
rop(IDataObject* pDataObject,
DWORD grfKeyState,
POINTL pt,
DWORD* pdwEffect)
{
CString out;
IEnumFORMATETC* pFetc;
pDataObject->EnumFormatEtc(DATADIR_GET, &pFetc);
ULONG fetched = 0;
FORMATETC fetc;
pFetc->Next(1, &fetc, &fetched);
while (fetched == 1) {
char fBuffer[100];
GetClipboardFormatName(fetc.cfFormat, fBuffer, 100);
if (fetc.tymed & TYMED_ISTREAM) {
fetc.tymed = TYMED_ISTREAM;
STGMEDIUM stgMed;
pDataObject->GetData(&fetc, &stgMed);
if (stgMed.tymed == TYMED_ISTREAM && stgMed.pstm != NULL) {
STATSTG statStg; memset(&statStg, 0, sizeof(statStg));
stgMed.pstm->AddRef();
stgMed.pstm->Stat(&statStg, STATFLAG_DEFAULT);
if(statStg.cbSize.LowPart)
{
LARGE_INTEGER uliMove; uliMove.LowPart = 0;
uliMove.HighPart = 0;
ULARGE_INTEGER uliNewPos;
stgMed.pstm->Seek(uliMove, STREAM_SEEK_SET, &uliNewPos);
char* aBuffer = new char[statStg.cbSize.LowPart];
ULONG ulBytesRead = 0;
if(SUCCEEDED(stgMed.pstm->Read(aBuffer,
statStg.cbSize.LowPart, &ulBytesRead)))
{
for (ULONG i = 0; i < ulBytesRead; i++) {
if (aBuffer
== 0) {
aBuffer = '.';
}
}
aBuffer[ulBytesRead < sizeof(aBuffer) ? ulBytesRead
: ulBytesRead - 1] = 0;
out.AppendFormat("%s: %s\r\n", fBuffer, aBuffer);
}
delete[] aBuffer;
}
stgMed.pstm->Release();
} else {
out.AppendFormat("%s: no stream\r\n", fBuffer);
}
} else {
if (fetc.tymed == TYMED_HGLOBAL) {
STGMEDIUM stgMed;
pDataObject->GetData(&fetc, &stgMed);
if (stgMed.tymed == TYMED_HGLOBAL && stgMed.hGlobal != NULL) {
size_t l = GlobalSize(stgMed.hGlobal);
char* buf = new char[l];
char* p = (char*) GlobalLock(stgMed.hGlobal);
if (p != NULL) {
for (UINT i = 0; i < l; i++) {
buf = p == 0 ? '.' : p;
}
out.AppendFormat("%s: HGLOBAL %s\r\n", fBuffer, buf);
} else {
out.AppendFormat("%s: Tymed %d\r\n", fBuffer,
fetc.tymed);
}
GlobalUnlock(stgMed.hGlobal);
delete[] buf;
}
} else {
out.AppendFormat("%s: Tymed %d\r\n", fBuffer, fetc.tymed);
}
}
pFetc->Next(1, &fetc, &fetched);
}
pFetc->Release();
SetWindowText(m_hWndStatic, out)
*pdwEffect = DROPEFFECT_NONE;
m_fCanDrop = FALSE;
return S_OK;
}
Thanks,
Roland