Implementing “Sent To Mail Recipient”; in your Application

I wanted to be able to easily email a file from a utility I wrote, and thought “wouldn’t it be so much easier if I could incorporate the ‘Sent To Mail Receipient’ functionality available within Windows” so I didn’t have to worry about which email application is actually installed.  I know this will typically limit this to either Microsoft Outlook Express or Microsoft Outlook, but at least I don’t have to worry about the mechanism required to create an email with an attachment which is yet to be sent.

So the following is the C++ code which implements createEmailWithAttachment().

The GetUIObjectOfFile() routine is taken from Raymand Chen’s blog where he posted How to host an IContextMenu, part 1.

The droptarget code was taken from a discussion thread which was incomplete.

Unicode and non-unicode variants are supported.

HRESULT GetUIObjectOfFile(HWND hwnd, LPCWSTR pszPath, REFIID riid, 
                          void **ppv) 
{ 
  *ppv = NULL; 
  HRESULT hr; 
  LPITEMIDLIST pidl; 
  SFGAOF sfgao; 
  hr = SHParseDisplayName(pszPath, NULL, &pidl, 0, &sfgao); 
  if (SUCCEEDED(hr)) 
  { 
    IShellFolder *psf; 
    LPCITEMIDLIST pidlChild; 
    hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, 
                        &pidlChild); 
    if (SUCCEEDED(hr)) 
    { 
      hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv); 
      psf->Release(); 
    } 
    CoTaskMemFree(pidl); 
  } 
  return hr; 
} 

#ifdef DEFINE_GUID 
#undef DEFINE_GUID 
#endif 

#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) 
        EXTERN_C const GUID name 
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } } 

DEFINE_GUID(CLSID_SendMail, 0x9E56BE60, 0xC50F, 0x11CF, 0x9A, 0x2C, 0x00, 
            0xA0, 0xC9, 0x0A, 0x90, 0xCE); 

static HRESULT createEmailWithAttachment(LPCTSTR pszFileName) 
{ 
  IDataObject *pDataObject = NULL; 
  IDropTarget *pDropTarget = NULL; 
  LPCWSTR pwszFileName = NULL; 
  bool bCreated = false; 
  HRESULT hr; 

#ifdef UNICODE 
  pwszFileName = pszFileName; 
#else 
  WCHAR *pwszBuffer = NULL; 

  int nLength = MultiByteToWideChar(CP_ACP, 0, pszFileName, 
                                    strlen(pszFileName), NULL, 0); 
  if (nLength DragEnter(pDataObject, MK_LBUTTON, pt, &dwEffect); 
      if (SUCCEEDED(hr)) 
      { 
        hr = pDropTarget->Drop(pDataObject, MK_LBUTTON, pt, &dwEffect); 
        if (SUCCEEDED(hr)) 
          bCreated = true; 
      } 
      pDropTarget->Release(); 
    } 

#ifndef UNICODE 
    free(pwszBuffer); 
#endif // UNICODE 

    pDataObject->Release(); 
  } 

  return hr; 
}

Leave a Reply