|
I tested this on a couple email programs and it works fine for outlook, outlook express, and eudora. I downloaded a random email client calypso and of course, they don't follow the standard. Calypso adds their own entry "Calypso E-mail" to the send to menu. It is implemented by a shortcut put into the sendo to directory. I looked in the internet explorer settings dialog under Tools|Internet Options|Programs and Calypso is listed there. Calypso is hooked into the mailto url.
Can this code easily be modified to work with .lnk files...how do you get the IDropTarget interface?
|
|
|
|
|
Ok, this does it all. I am done. You can send to anything that supports IDropTarget. This includes GUID's, .lnk files, .dll files, .exe files, and maybe more, I don't know. I can send files to anything in the send to folder easily. Use this dll (or code) to mimic Send To | Mail Recipient. I still don't have an ftp site to upload the zip file with the compiled dll and source code, so eMail me if you want it.
main code file
<br />
<br />
#include "stdafx.h"<br />
<br />
BOOL APIENTRY DllMain(HANDLE hModule, DWORD fReason, LPVOID lpReserved)<br />
{<br />
return TRUE;<br />
}<br />
<br />
DllExport LONG WINAPI SendToDefaultEmail(char *szPName, char *szFFiles) <br />
{<br />
return SendToDropTarget("{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}",szPName,szFFiles);<br />
}<br />
<br />
DllExport LONG WINAPI SendToDropTarget(char *szFPOrGUIDDropTarget, char *szPName, char *szFFiles) <br />
{<br />
int iFile,<br />
cFiles, <br />
cbFiles,<br />
ich;<br />
DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;<br />
POINTL pt = {0,0};<br />
char *szFName;<br />
HRESULT hr = 0;<br />
wchar_t wzBuf[MAX_PATH];<br />
IDataObject *pDataObject = NULL;<br />
IDropTarget *pDropTarget = NULL;<br />
LPSHELLFOLDER pDeskTopFolder = NULL,<br />
pFolder = NULL;<br />
LPITEMIDLIST pIdlFolder = NULL,<br />
pIdlFile = NULL;<br />
LPCITEMIDLIST *apIdlFiles = NULL;<br />
LPMALLOC pMalloc = NULL;<br />
GUID guidDropTarget;<br />
<br />
SHGetMalloc(&pMalloc);<br />
<br />
if (!szFPOrGUIDDropTarget || !szFPOrGUIDDropTarget[0] || !szPName || !szPName[0] || <br />
!szFFiles || !(cbFiles = strlen(szFFiles))) goto ExitFunc;<br />
for (cFiles=1,ich=0 ; szFFiles[ich] ; ++ich)<br />
if (szFFiles[ich] == '|')<br />
++cFiles;<br />
if (!(apIdlFiles = (LPCITEMIDLIST*)calloc(cFiles,sizeof(LPCITEMIDLIST)))) {<br />
hr = -2;<br />
goto ExitFunc;<br />
}<br />
<br />
if ((hr = SHGetDesktopFolder(&pDeskTopFolder)) != 0) goto ExitFunc; <br />
<br />
<br />
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szFPOrGUIDDropTarget,-1,wzBuf,MAX_PATH);<br />
if (IIDFromString(wzBuf,&guidDropTarget) == S_OK) {<br />
if ((hr = CoCreateInstance(guidDropTarget, NULL, CLSCTX_ALL,IID_IDropTarget, (void **)&pDropTarget)) != 0) goto ExitFunc;<br />
} else {<br />
char szDDropTarget[MAX_PATH],szPDropTarget[MAX_PATH],szFDropTarget[MAX_PATH],szExtDropTarget[MAX_PATH] ;<br />
_splitpath(szFPOrGUIDDropTarget,szDDropTarget,szPDropTarget,szFDropTarget,szExtDropTarget);<br />
strcpy(szPDropTarget,strcat(szDDropTarget,szPDropTarget));<br />
strcat(szFDropTarget,szExtDropTarget);<br />
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szPDropTarget,-1,wzBuf,MAX_PATH);<br />
if ((hr = pDeskTopFolder->ParseDisplayName(NULL, 0, wzBuf, NULL, &pIdlFolder, NULL)) != 0) goto ExitFunc;<br />
if ((hr = pDeskTopFolder->BindToObject(pIdlFolder,NULL,IID_IShellFolder,(void**)&pFolder)) != 0) goto ExitFunc;<br />
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szFDropTarget,-1,wzBuf,MAX_PATH);<br />
if ((hr = pFolder->ParseDisplayName(NULL, 0, wzBuf, NULL, &pIdlFile, NULL)) != 0) goto ExitFunc;<br />
if ((hr = pFolder->GetUIObjectOf(NULL,1,(LPCITEMIDLIST*)&pIdlFile,IID_IDropTarget,NULL,(void**)&pDropTarget)) != 0) goto ExitFunc;<br />
pMalloc->Free(pIdlFile); <br />
pIdlFile = NULL;<br />
pMalloc->Free(pIdlFolder); <br />
pIdlFolder = NULL;<br />
pFolder->Release();<br />
pFolder = NULL;<br />
}<br />
<br />
<br />
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szPName,-1,wzBuf,MAX_PATH);<br />
if ((hr = pDeskTopFolder->ParseDisplayName(NULL, 0, wzBuf, NULL, &pIdlFolder, NULL)) != 0) goto ExitFunc;<br />
if ((hr = pDeskTopFolder->BindToObject(pIdlFolder,NULL,IID_IShellFolder,(void**)&pFolder)) != 0) goto ExitFunc;<br />
for (cFiles=0,szFName = strtok(szFFiles,"|") ; szFName ; szFName = strtok(NULL,"|")) {<br />
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szFName,-1,wzBuf,MAX_PATH);<br />
if ((hr = pFolder->ParseDisplayName(NULL, 0, wzBuf, NULL, &pIdlFile, NULL)) != 0) goto ExitFunc;<br />
apIdlFiles[cFiles++] = pIdlFile;<br />
}<br />
if ((hr = pFolder->GetUIObjectOf(NULL,cFiles,apIdlFiles,IID_IDataObject,NULL,(void**)&pDataObject)) != 0) goto ExitFunc;<br />
<br />
<br />
if ((hr = pDropTarget->DragEnter(pDataObject, MK_LBUTTON, pt, &dwEffect)) != 0) goto ExitFunc;<br />
if (!dwEffect) {<br />
hr = -1;<br />
goto ExitFunc;<br />
}<br />
if ((hr = pDropTarget->Drop(pDataObject, MK_LBUTTON, pt, &dwEffect)) != 0) goto ExitFunc;<br />
<br />
Sleep(100);<br />
<br />
ExitFunc:<br />
<br />
if (pDataObject) pDataObject->Release();<br />
if (apIdlFiles) {<br />
for (iFile = 0 ; iFile < cFiles ; ++iFile) <br />
if ((void*)apIdlFiles[iFile])<br />
pMalloc->Free((void*)apIdlFiles[iFile]);<br />
free(apIdlFiles);<br />
}<br />
if (pFolder) pFolder->Release();<br />
if (pIdlFolder) pMalloc->Free(pIdlFolder);<br />
if (pDropTarget) pDropTarget->Release();<br />
if (pMalloc) pMalloc->Release();<br />
if (pDeskTopFolder) pDeskTopFolder->Release();<br />
return hr;<br />
}<br />
header file:
<br />
<br />
#if !defined(AFX_STDAFX_H__F63181D9_FBE8_4BD0_8835_5EEC2FD181BB__INCLUDED_)<br />
#define AFX_STDAFX_H__F63181D9_FBE8_4BD0_8835_5EEC2FD181BB__INCLUDED_<br />
<br />
#if _MSC_VER > 1000<br />
#pragma once<br />
#endif // _MSC_VER > 1000<br />
<br />
<br />
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers<br />
<br />
#include <windows.h><br />
<br />
<br />
#include <ole2.h>
#include <shlobj.h>
#include <tchar.h>
<br />
#define DllExport __declspec( dllexport )<br />
extern "C" {<br />
DllExport LONG WINAPI SendToDefaultEmail(char *szPFiles, char *szFFiles);<br />
DllExport LONG WINAPI SendToDropTarget(char *szFPOrGUIDDropTarget, char *szPName, char *szFFiles);<br />
}<br />
<br />
#define INLINE_UUID(x) __uuidof(struct __declspec(uuid(x)))<br />
<br />
<br />
#endif // !defined(AFX_STDAFX_H__F63181D9_FBE8_4BD0_8835_5EEC2FD181BB__INCLUDED_)<br />
<br />
def file:
<br />
LIBRARY OSRegExp01<br />
DESCRIPTION "Implements Drop Target Functions"<br />
<br />
EXPORTS<br />
<br />
SendToDefaultEmail @1<br />
SendToDropTarget @2<br />
|
|
|
|
|
Would you mind e-mailing me the dll and c++ source code to support@aristocat.com.
Thank you very much in advance.
Larry Hunt
|
|
|
|
|
Hi there,
I see that this is quite an old post, but is it still possible to get a copy of the VB6 DLL?
Many thanks,
Wayne
|
|
|
|
|
could you email the dll you created to cgreen@dial.pipex.com as I have tried copying and pasting your previous files but I always get compiling errors.
Cheers
|
|
|
|
|
using shlobj.h might fix compile problem Thank you very much for this greate stuff! Really usefull lib.
|
|
|
|
|
please send me the dll at dasiths2hotmail.com
try this too: http://www.vbforums.com/showthread.php?s=&postid=1567035#post1567035
|
|
|
|
|
please send me the dll at dasiths@hotmail.com
try this too: http://www.vbforums.com/showthread.php?s=&postid=1567035#post1567035
|
|
|
|
|
Could you please send me your dll and source code?
Thanks,
Amanda
|
|
|
|
|
Stephane:
Thank you for this code. I have been playing around with the code to see if I can make it work on WinXP. So far, no luck but I haven't as yet spent a lot of time.
If you have made a fix, I would be happy to pay for it.
|
|
|
|
|
One problem is the implementation of QueryInterface().
There should be a check for the queried interface class.
Otherwise the code says, it would return a pointer to e.g. IMarshal, which it realy does'nt.
I think this is better:
HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject)
{
if (iid!=__uuidof(IUnknown) && iid!=__uuidof(IDataObject))
return E_NOINTERFACE;
*ppvObject = (IDataObject*) this;
return S_OK;
}
Hower that doesn't seem to be enough - for now it does not work on XP. (at least for me)
|
|
|
|
|
Finally I could find a working solution for XP:
#define INLINE_UUID(x) __uuidof(struct __declspec(uuid(x)))
void send_mail_attachment(HWND hwnd, String rec_address, String rec_name, String topic, String message_text, FULLFILENAME attachment)
{
try {
IDataObjectPtr pDO;
ShellPath(attachment).GetUIObjectOf(IID_IDataObject, (LPVOID*)&pDO, hwnd);
POINTL pt = {0, 0};
DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
IDropTargetPtr droptarget(INLINE_UUID("9e56be60-c50f-11cf-9a2c-00a0c90a90ce")); // CLSID_SendMail
HRESULT hr = droptarget->DragEnter(pDO, MK_LBUTTON, pt, &dwEffect);
if (SUCCEEDED(hr) && dwEffect)
CheckError(droptarget->Drop(pDO, MK_LBUTTON, pt, &dwEffect));
else {
CheckError(droptarget->DragLeave());
CheckError(hr);
}
} catch(_com_error& e) {
HandleException(e, hwnd);
}
}
This is derived from Seashell Code (http://www.codeproject.com/shell/seashell.asp) and does the trick by using a IDataObject of the Shell "SendTo"-Links.
String, ShellPath, HandleException() are my own little helper classes/function. I just wanted to show the principle.
|
|
|
|
|
Finding something to duplicate sendto|mail recipient has just about driven me crazy! Thank god for this article!
Couple questions.
1) I am new to com programming in C. Could you provide your helper functions? Particularly I am not sure what
ShellPath(attachment).GetUIObjectOf(IID_IDataObject, (LPVOID*)&pDO, hwnd);
is doing. Thanks.
2) Have you tested this on windows 2000, running outlook express? I downloaded the test code, which does the test in main(). It works for outlook, but not outlook express. With express, after Drop() is called, the email appears in express' compose mail window like I want, but I cannot give that email the focus or type into it - its in a locked state, probably waiting for something from my test program. When the test program ends, the compose window disappears. What is going on? It seems like outlook express expects the handoff to be performed slightly differently.
- Thanks
|
|
|
|
|
Hello,
Your comment made me look one more time in the source code.
Now I could found how to fix the SendMail example
There are two problems main with this code:
First the QueryInterface implementation is buggy.
It should contain the following:
HRESULT __stdcall QueryInterface(REFIID iid, void ** ppvObject)
{
if (iid == __uuidof(IUnknown)) {
*ppvObject = (IUnknown*) static_cast<IDataObject*>(this);
return S_OK;
}
if (iid == __uuidof(IDataObject)) {
*ppvObject = static_cast<IDataObject*>(this);
return S_OK;
}
if (iid == __uuidof(IEnumFORMATETC)) {
*ppvObject = static_cast<IEnumFORMATETC*>(this);
return S_OK;
}
return E_NOINTERFACE;
}
Second the code doesn't have a message loop. It seems, outlook express needs a message loop in the calling thread to process its windows messages.
So we should replace the ::Sleep(6*1000); with:
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The remaining problem is now, the process will run forever. It doesn't terminate when you close the mailer window.
Last thing, I would like to insert is a safety check in GetData():
if (!pFormatetc)
return S_FALSE;
I will post my own code without this IDataObject implementation which is discussed here to a new article when I will have made a bit of cleanup. I think, it's a bit cleaner and does not need as much code as with the method discussed here.
By the way:
Could someone point me to how I can insert empty lines in <code> sections of this editor?
--
Martin Fuchs
martin-fuchs@gmx.net
|
|
|
|
|
Thanks for the query interface code.
You dont need to modify GetData(), since it is not being used nor called anymore! You get the IDataObject from GetUIObject() and are using that one!? I think I am right, but I have been programming this com stuff for 2 days now and could be mistaken. Check out my code in the new thread above to see what I mean. I didn't include any of stephan's classes and my code works.
I picked up on the message loop thing too. Since I am calling from vb6, I can tell you the vb6 message loop is sufficient, and no sleep, or doevents is needed in a dll function that sends files to email.
Also, the IDropTarget object needs to stay around for the duration of the email message within the email client. I made the IDropTarget global to the dll in my code and created/deleted it in dllmain().
- John Franco
jfranco@openscantech.com
|
|
|
|
|
how can you insert a default email address in the "to:" field
|
|
|
|
|
Generally speaking, you can do the same than using the "mail recipient" SendTo shortcut from Windows Explorer, not more, not less.
I am afraid you can't specify the to: field with the shortcut, so the answer is no.
An alternative is to use mailto:xxx@xxx.com for instance.
|
|
|
|
|
I started to use the shortcut <mailto:xxx@xxx.com> but it does not take the "attach" command for versions of outlook 2000 or newer.
Well, with the drag'n'drop solution above, how is the code entering text in the "subject" and "body" fields???
|
|
|
|
|
is there a way to enter a default email address in the "to: field"
And, how do you make the newly composed email stay visible without it disapearing?? (besides incrementing the sleep time)
thank you in advance!
agd
|
|
|
|
|
This is a real good tool. I had been searching for ages to find something like this, of cause i actually would have liked to have had it within a activex dll, but thats no prob as was able to get working.
Ive been using this now for a week on a few operating systems and had been working well untill on a winxp machine.
I decided to see why i was getting an error on winxp and used the same code and yes it dies. Im unable to see exactly where, but was after a call to GetData that this seemed to happen.
I would be appreaciated for any assistance in working through this for WinXP as it works great eveywhere else.
Oh by the way the tests were on WinXP Pro (havent tested on home ed)
Email address is gsmith@autointegrity.com.au
Thanks
|
|
|
|
|
I use WinXP, VS7 and MS Outlook 2002. I want to add this code with my MFC project.
After I had added this code into my project, I took bottom message.
What is wrong?
Unhandled exception at 0x771c525e in MD.exe: 0xC0000005: Access violation reading location 0x0000011a
When I try to run attached code. this program causes to run Ms Error Report.
report detail is;
AppName: SendMail.exe AppVer: 0.0.0.0 ModName: ole32.dll
ModVer: 5.1.2600.1106 Offset: 0001525e
Thanks for everything.
|
|
|
|
|
Gennady Khokhorin
Software Developer
|
|
|
|
|
This source code mimics the Send To mail recipient windows shortcut. It works regardless the email client, whether it's Outlook Express, Outlook, or whatever default email client. Of course, the point of this article is not to send an email using Outlook, when your default email client is Outlook Express, for instance. In order to do that, just use CDO (MS SDK).
|
|
|
|
|
I have been searching high and low for this code, do you have a ActivX / DLL that I can call?
Regards
Carl
|
|
|
|
|
I made one using this code. I have not finished testing it yet. Look for a post to a new thread on this page very soon, for source code and a dll.
|
|
|
|
|