home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / docmapi.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  7KB  |  259 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #pragma warning(disable: 4228)
  13. #include <mapi.h>
  14. #pragma warning(default: 4228)
  15.  
  16. #ifdef AFX_MAPI_SEG
  17. #pragma code_seg(AFX_MAPI_SEG)
  18. #endif
  19.  
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // MAPI implementation helpers and globals
  27.  
  28. AFX_STATIC_DATA BOOL _afxIsMailAvail = (BOOL)-1;    // start out not determined
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // _AFX_MAIL_STATE
  32.  
  33. class _AFX_MAIL_STATE : public CNoTrackObject
  34. {
  35. public:
  36.     HINSTANCE m_hInstMail;      // handle to MAPI32.DLL
  37.     virtual ~_AFX_MAIL_STATE();
  38. };
  39.  
  40. _AFX_MAIL_STATE::~_AFX_MAIL_STATE()
  41. {
  42.     if (m_hInstMail != NULL)
  43.         ::FreeLibrary(m_hInstMail);
  44. }
  45.  
  46. EXTERN_PROCESS_LOCAL(_AFX_MAIL_STATE, _afxMailState)
  47.  
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CDocument MAPI support
  50.  
  51. void CDocument::OnFileSendMail()
  52. {
  53.     ASSERT_VALID(this);
  54.     ASSERT(_afxIsMailAvail);   // update handler always gets called first
  55.  
  56.     CWaitCursor wait;
  57.  
  58.     _AFX_MAIL_STATE* pMailState = _afxMailState;
  59.     if (pMailState->m_hInstMail == NULL)
  60.         pMailState->m_hInstMail = ::LoadLibraryA("MAPI32.DLL");
  61.  
  62.     if (pMailState->m_hInstMail == NULL)
  63.     {
  64.         AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD);
  65.         return;
  66.     }
  67.     ASSERT(pMailState->m_hInstMail != NULL);
  68.  
  69.     ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);
  70.     (FARPROC&)lpfnSendMail = GetProcAddress(pMailState->m_hInstMail, "MAPISendMail");
  71.     if (lpfnSendMail == NULL)
  72.     {
  73.         AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL);
  74.         return;
  75.     }
  76.     ASSERT(lpfnSendMail != NULL);
  77.  
  78.     TCHAR szTempName[_MAX_PATH];
  79.     TCHAR szPath[_MAX_PATH];
  80.     BOOL bRemoveTemp = FALSE;
  81.     if (m_strPathName.IsEmpty() || IsModified())
  82.     {
  83.         // save to temporary path
  84.         VERIFY(GetTempPath(_countof(szPath), szPath) != 0);
  85.         VERIFY(GetTempFileName(szPath, _T("afx"), 0, szTempName) != 0);
  86.  
  87.         // save it, but remember original modified flag
  88.         BOOL bModified = IsModified();
  89.         BOOL bResult = DoSave(szTempName, FALSE);
  90.         SetModifiedFlag(bModified);
  91.         if (!bResult)
  92.         {
  93.             TRACE0("Warning: file save failed during File.Send Mail.\n");
  94.             return;
  95.         }
  96.         bRemoveTemp = TRUE;
  97.     }
  98.     else
  99.     {
  100.         // use actual file since it isn't modified
  101.         lstrcpyn(szTempName, m_strPathName, _countof(szTempName));
  102.     }
  103. #ifdef _UNICODE
  104.     char szTempNameA[_MAX_PATH];
  105.     _wcstombsz(szTempNameA, szTempName, _countof(szTempNameA));
  106. #endif
  107.  
  108.     // build an appropriate title for the attachment
  109.     TCHAR szTitle[_MAX_PATH];
  110.     if (!m_strPathName.IsEmpty())
  111.         AfxGetFileName(m_strPathName, szTitle, _countof(szTitle));
  112.     else
  113.     {
  114.         lstrcpyn(szTitle, m_strTitle, _countof(szTitle));
  115.         if (m_strTitle.Find('.') == -1) // no extension
  116.         {
  117.             // append the default suffix if there is one
  118.             CString strExt;
  119.             CDocTemplate* pTemplate = GetDocTemplate();
  120.             if (pTemplate != NULL &&
  121.                 pTemplate->GetDocString(strExt, CDocTemplate::filterExt))
  122.             {
  123.                 lstrcat(szTitle, strExt);
  124.             }
  125.         }
  126.     }
  127.  
  128. #ifdef _UNICODE
  129.     char szTitleA[_MAX_PATH];
  130.     _wcstombsz(szTitleA, szTitle, _countof(szTitleA));
  131. #endif
  132.  
  133.     // prepare the file description (for the attachment)
  134.     MapiFileDesc fileDesc;
  135.     memset(&fileDesc, 0, sizeof(fileDesc));
  136.     fileDesc.nPosition = (ULONG)-1;
  137. #ifdef _UNICODE
  138.     fileDesc.lpszPathName = szTempNameA;
  139.     fileDesc.lpszFileName = szTitleA;
  140. #else
  141.     fileDesc.lpszPathName = szTempName;
  142.     fileDesc.lpszFileName = szTitle;
  143. #endif
  144.  
  145.     // prepare the message (empty with 1 attachment)
  146.     MapiMessage message;
  147.     memset(&message, 0, sizeof(message));
  148.     message.nFileCount = 1;
  149.     message.lpFiles = &fileDesc;
  150.  
  151.     // prepare for modal dialog box
  152.     AfxGetApp()->EnableModeless(FALSE);
  153.     HWND hWndTop;
  154.     CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, &hWndTop);
  155.  
  156.     // some extra precautions are required to use MAPISendMail as it
  157.     // tends to enable the parent window in between dialogs (after
  158.     // the login dialog, but before the send note dialog).
  159.     pParentWnd->SetCapture();
  160.     ::SetFocus(NULL);
  161.     pParentWnd->m_nFlags |= WF_STAYDISABLED;
  162.  
  163.     int nError = lpfnSendMail(0, (ULONG)pParentWnd->GetSafeHwnd(),
  164.         &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
  165.  
  166.     // after returning from the MAPISendMail call, the window must
  167.     // be re-enabled and focus returned to the frame to undo the workaround
  168.     // done before the MAPI call.
  169.     ::ReleaseCapture();
  170.     pParentWnd->m_nFlags &= ~WF_STAYDISABLED;
  171.  
  172.     pParentWnd->EnableWindow(TRUE);
  173.     ::SetActiveWindow(NULL);
  174.     pParentWnd->SetActiveWindow();
  175.     pParentWnd->SetFocus();
  176.     if (hWndTop != NULL)
  177.         ::EnableWindow(hWndTop, TRUE);
  178.     AfxGetApp()->EnableModeless(TRUE);
  179.  
  180.     if (nError != SUCCESS_SUCCESS &&
  181.         nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)
  182.     {
  183.         AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);
  184.     }
  185.  
  186.     // remove temporary file, if temporary file was used
  187.     if (bRemoveTemp)
  188.         CFile::Remove(szTempName);
  189. }
  190.  
  191. void CDocument::OnUpdateFileSendMail(CCmdUI* pCmdUI)
  192. {
  193.     ASSERT_VALID(this);
  194.  
  195.     if (_afxIsMailAvail == (BOOL)-1)
  196.     {
  197.         _afxIsMailAvail = ::GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0 &&
  198.             SearchPath(NULL, _T("MAPI32.DLL"), NULL, 0, NULL, NULL) != 0;
  199.     }
  200.  
  201.     // enable the Send... menu item if available
  202.     pCmdUI->Enable(_afxIsMailAvail);
  203.     CMenu* pMenu = pCmdUI->m_pMenu;
  204.     if (!_afxIsMailAvail && pMenu != NULL)
  205.     {
  206.         // remove the Send... menu and surrounding separators
  207.         UINT nStateAbove = pMenu->GetMenuState(pCmdUI->m_nIndex-1, MF_BYPOSITION);
  208.         UINT nStateBelow = pMenu->GetMenuState(pCmdUI->m_nIndex+1, MF_BYPOSITION);
  209.         pMenu->RemoveMenu(pCmdUI->m_nIndex, MF_BYPOSITION);
  210.         if (nStateAbove & nStateBelow & MF_SEPARATOR)
  211.         {
  212.             // a separator must be removed since the Send... is gone
  213.             if (nStateAbove != (UINT)-1)
  214.                 pMenu->RemoveMenu(pCmdUI->m_nIndex-1, MF_BYPOSITION);
  215.             else if (nStateBelow != (UINT)-1)
  216.                 pMenu->RemoveMenu(pCmdUI->m_nIndex, MF_BYPOSITION);
  217.         }
  218.     }
  219. }
  220.  
  221. /////////////////////////////////////////////////////////////////////////////
  222. // COleDocument MAPI support
  223.  
  224. void COleDocument::OnFileSendMail()
  225. {
  226.     ASSERT_VALID(this);
  227.     ASSERT(m_bRemember);
  228.  
  229.     LPSTORAGE lpOrigStg = m_lpRootStg;
  230.     m_lpRootStg = NULL;
  231.  
  232.     TRY
  233.     {
  234.         m_bRemember = FALSE;
  235.         CDocument::OnFileSendMail();
  236.     }
  237.     CATCH_ALL(e)
  238.     {
  239.         m_lpRootStg = lpOrigStg;
  240.         m_bRemember = TRUE;
  241.         THROW_LAST();
  242.     }
  243.     END_CATCH_ALL
  244.  
  245.     m_lpRootStg = lpOrigStg;
  246.     m_bRemember = TRUE;
  247. }
  248.  
  249. #ifdef AFX_INIT_SEG
  250. #pragma code_seg(AFX_INIT_SEG)
  251. #endif
  252.  
  253. #pragma warning(disable: 4074)
  254. #pragma init_seg(lib)
  255.  
  256. PROCESS_LOCAL(_AFX_MAIL_STATE, _afxMailState)
  257.  
  258. /////////////////////////////////////////////////////////////////////////////
  259.