Drag and Drop Outlook attachment into a Windows Form Control

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I previously performed drag and drop between 2 lists within a Windows form.
Right now I am looking for something a little more complex and I am not able
to find a way to do it.
In just few words, I want to drag a file (in my case a PDF file) which is an
attachment to an email in Outlook 2003 client and drop it over a control (in
my case a command button or anything else) within a window in my application.
When file is dropped over my designated control, I do not need to open it I
just want to save it into a SQL database. Saving files in SQL databases is
not an issue because I am already doing it, my only problem is I don't know
how to capture the dropped file into a variable in order to be afterwards
able to save it into the database.
The same question would apply for other formats too (e.g. BMP, JPG, TIFF,
DOC, XLS, etc.) if each type should be handled in a different way.
I appreciate any hints into this issue.

Thanks,
Adrian
 
Hi Adrian,

Thank you for posting.

This is a quick note to let you know that I am performing research on this
issue and will get back to you as soon as possible. I appreciate your
patience.


Sincerely,
Linda Liu
Microsoft Online Community Support

====================================================
When responding to posts,please "Reply to Group" via
your newsreader so that others may learn and benefit
from your issue.
====================================================
 
Hi Adrian,

Thank you for posting.

If you drag a file which is an attachment to an email in Outlook 2003
client and drop it over your program, you could get two kinds of useful
information about the file with the data formats "FileGroupDescriptor" and
"FileContents". With the first data format "FileGroupDescriptor", you could
get the filename of the file and with the second data format
"FileContents", you could get the content of the file in a memorystream.

The following is a sample. When you drag an attachment of an email in
Outlook 2003 and drop it over this program, the program will get the
attachment's file name and save the attachment with its file name under the
same path of the exe file.

Private Sub Form1_DragEnter(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles MyBase.DragEnter
e.Effect = DragDropEffects.Copy
End Sub

Private Sub Form1_DragDrop(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles MyBase.DragDrop

Dim memoryStream As System.IO.MemoryStream =
e.Data.GetData("FileGroupDescriptor")
'Sets the position within the current stream to the beginning of the
file name.
memoryStream.Seek(76, IO.SeekOrigin.Begin)

Dim fileName As Byte() = New Byte(256) {}
'return the file name in the fileName variable
memoryStream.Read(fileName, 0, 256)

Dim encoding As System.Text.Encoding = System.Text.Encoding.ASCII
'convert to byte arry to string
Dim strFileName As String = encoding.GetString(fileName)
'trim the strFileName to get the correct file name
strFileName = strFileName.TrimEnd("")

memoryStream = e.Data.GetData("FileContents")
'write the file content to a file under the same path of the exe file.
Dim fs As New IO.FileStream(strFileName, IO.FileMode.Create)
memoryStream.WriteTo(fs)
fs.Close()

End Sub

Of course, if you want to save the attachment into a SQL database, it's
enough for you to get the attachment's content in a memorystream
and you needn't save the attachment to the disk.

This approach applies for any kind of attachment(e.g. BMP, DOC, PDF,JPG,
etc.).

Hope this is helpful to you. If you have any other concerns or need
anything else, please don't
hesitate to let me know.



Sincerely,
Linda Liu
Microsoft Online Community Support

====================================================
When responding to posts,please "Reply to Group" via
your newsreader so that others may learn and benefit
from your issue.
====================================================
 
Hi Adrian,

Thanks for your response. I am glad to hear that the problem has been
fixed. If you have any other questions or concerns, please do not hesitate
to contact us. It is always our pleasure to be of assistance.

Have a nice day!


Sincerely,
Linda Liu
Microsoft Online Community Support

====================================================
When responding to posts,please "Reply to Group" via
your newsreader so that others may learn and benefit
from your issue.
====================================================
 
Hi Linda,

The post was very much useful. Thanks for the same.

To add to this complexity I need save the entire email along with
attachments in a .msg file. I have been trying out different ways to do
it but none of them seems to work. Do you have any solutions to this ? I
am currently using VB2003.

Thanks in advance,

Regards,
Shyam
 
What's your problem SKKR? Or, maybe we better start a new subject..
When you saving an email as file, choose the msg type and all
attachments are kept in the email.

Shyam Kishore Kuppu Rao schreef:
 
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::Drop(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
 
Hi Linda,
Good code. I have a case where I want to save the email file or only
attachment file. When user drop email I tackle it thru
e.Data.GetData("FileGroupDescriptor"). How can i handle it for attachment? I
am saving the mails and attachments separately. If attachment is dragged in
then only attachment should be saved. How can we differentiate whether email
is dropped or attachment is dropped?

Thanks for the help,
Amit
 
Back
Top