Launching a MAPI Form
| Nik Okuntseff |
MS Exchange Server Programming |
Launching a MAPI Form
It would be useful to know how to launch a new form. I assume that the
form is already installed on the system. How someone would programmatically
launch a new form?
If we follow the route of raw MAPI standards the problem appears to
be not trivial. Form servers are separate COM executables, and they expect
significant volume of work to be performed by their clients. For example,
you need to implement IMAPIMessageSite interface among other things. Form
server may call methods of this interface. This interaction is complex.
An alternative (and easier) way is to use IMAPISession::PrepareForm
and IMAPISession::ShowForm methods. The last one utilizes Outlook automation.
As a result, the code is smaller at expense of performance. For example,
the following code (Forms/Launch) shows how you can launch a new form IPM.Note.MyMessage,
which you should install before you run the code:
#include <afxwin.h>
#include <edk.h>
int main()
{
/*
* Algorithm:
* 1. Create a new message in Outbox.
* 2. Call IMAPISession::PrepareForm
* 3. Call IMAPISession::ShowForm
*/
HRESULT hr;
LPMAPISESSION pSession = NULL;
// Initialize MAPI
hr = MAPIInitialize(NULL);
if (FAILED(hr)) throw -1;
// Obtain MAPI session
hr = MAPILogonEx(0, // Handle
to parent window
"MS Exchange Settings", // Profile name
NULL, // Password
MAPI_NEW_SESSION |
MAPI_EXTENDED |
MAPI_LOGON_UI, // Logon flags
&pSession); // Resulting MAPI
session
if (FAILED(hr)) throw -1;
// Find default message store
ULONG cbDefStoreEid = 0;
LPENTRYID pDefStoreEid = NULL;
hr = HrMAPIFindDefaultMsgStore(pSession, &cbDefStoreEid,
&pDefStoreEid);
if (FAILED(hr)) throw -1;
// Open default message store
LPMDB pDefMsgStore = NULL;
hr = pSession->OpenMsgStore(0, cbDefStoreEid, pDefStoreEid,
NULL,
MDB_WRITE | MAPI_DEFERRED_ERRORS,
&pDefMsgStore);
if (FAILED(hr)) throw -1;
// Obtain Entry ID for Outbox.
ULONG ulValues;
LPSPropValue pPropValues = NULL;
hr = pDefMsgStore->GetProps(NULL,
0,
&ulValues,
&pPropValues);
if (FAILED(hr)) throw -1;
// Find PR_IPM_OUTBOX_ENTRYID
BOOL bOutboxFound = FALSE;
for (ULONG ul = 0; ul < ulValues; ul++)
{
if (PR_IPM_OUTBOX_ENTRYID
== pPropValues[ul].ulPropTag)
{
bOutboxFound = TRUE;
break;
}
}
assert(bOutboxFound);
// We have PR_IPM_OUTBOX_ENTRYID here
// Try to open the Outbox
ULONG ulObjType = 0;
LPMAPIFOLDER pOutbox = NULL;
hr = pDefMsgStore->OpenEntry(pPropValues[ul].Value.bin.cb,
(ENTRYID *) pPropValues[ul].Value.bin.lpb,
NULL,
MAPI_BEST_ACCESS,
&ulObjType,
(LPUNKNOWN *) &pOutbox);
if (FAILED(hr)) throw -1;
// We have the Outbox opened...
// Create a new message in Outbox. We'll need it
to associate
// with a form.
LPMESSAGE pMessage = NULL;
hr = pOutbox->CreateMessage(NULL, 0, &pMessage);
if (FAILED(hr)) throw -1;
// Prepare form
ULONG ulToken = 0;
hr = pSession->PrepareForm(NULL, pMessage, &ulToken);
if (FAILED(hr)) throw -1;
// Show the form
hr = pSession->ShowForm(NULL,
pDefMsgStore,
pOutbox,
NULL,
ulToken,
NULL,
MAPI_NEW_MESSAGE,
0,
MSGFLAG_UNSENT,
MAPI_ACCESS_MODIFY,
"IPM.Note.MyMessage");
// Cleanup
if (pMessage)
pMessage->Release();
if (pOutbox)
pOutbox->Release();
if (pPropValues)
MAPIFreeBuffer(pPropValues);
if (pDefMsgStore)
pDefMsgStore->Release();
if (pSession)
pSession->Release();
::MAPIUninitialize();
return 0;
}
This algorithm is quite straightforward: I locate the Outbox, create
a message in there, then call the IMAPISession::PrepareForm followed by
IMAPISession::ShowForm. If you run this code under debugger and observe
what happens in the system when you execute the ShowForm statement you
will see that Outlook.exe appears in list of running process displayed
by the Task Manager. Also, the performance appears to be miserable here
because of huge amount of work associated with automation.
[ Contents |
Home
]
Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff
|