📄 inboxmenuext.cpp
字号:
{
CHR(E_INVALIDARG);
}
}
break;
case Softkey:
{
if (idCmd == m_idc1)
{
// Mark all as read
hr = StringCchCopy(pszName, cchName, cszMarkAll);
CHR(hr);
}
else if (idCmd == m_idc2)
{
// Delete all
hr = StringCchCopy(pszName, cchName, cszDeleteAll);
CHR(hr);
}
else
{
CHR(E_INVALIDARG);
}
}
break;
}
}
Error:
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// IsMessage
//
// Determines if the incoming ItemRef is a Message
//
// Arguments:
// [IN] ItemRef *pir - pointer to an ItemRef to investigate
//
// Return Values:
// BOOL - true if this is a Message (ITI_MessageItemRef)
//
BOOL MenuExtension::IsMessage(ItemRef *pir)
{
return IsEqualGUID(*(pir->pType), ITI_MessageItemRef);
}
///////////////////////////////////////////////////////////////////////////////
// IsFolder
//
// Determines if the incoming ItemRef is a Folder
//
// Arguments:
// [IN] ItemRef *pir - pointer to an ItemRef to investigate
//
// Return Values:
// BOOL - true if this is a Folder (ITI_FolderItemRef)
//
BOOL MenuExtension::IsFolder(ItemRef *pir)
{
return IsEqualGUID(*(pir->pType), ITI_FolderItemRef);
}
///////////////////////////////////////////////////////////////////////////////
// GetItemRefArray
//
// Retrieve the ItemRefArray from the application site. The data which the
// application passes to the Menu Extension is packaged in an ItemRefArray.
//
// The contents of this ItemRefArray will vary depending on which type of
// menu extension you are implementing. See the SDK documentation for more
// details on what data is packed into this ItemRefArray for each of the
// different types of menu extensions
//
// Arguments:
// [OUT] ItemRef *pir - pointer to an ItemRefArray pulled from m_pSite
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::GetItemRefArray(ItemRefArray **ppItemArray)
{
HRESULT hr = E_FAIL;
IDataObject* pDataObj = NULL;
FORMATETC fmt;
ZeroMemory(&fmt, sizeof(fmt));
fmt.cfFormat = ::RegisterClipboardFormat(CFNAME_ITEMREFARRAY);
fmt.dwAspect = DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.ptd = NULL;
fmt.tymed = TYMED_HGLOBAL;
STGMEDIUM stg;
ZeroMemory(&stg, sizeof(stg));
// Be sure that there is a site. Remember the "site" is a pointer to the
// object in the UI that the menu extension will be acting on.
if(m_pSite)
{
// Get the IDataObject interface for the site
hr = m_pSite->QueryInterface(IID_IDataObject, (void**)&pDataObj);
CHR(hr);
if (pDataObj)
{
// Get the FORMATETC and the STGMEDIUM from the IDataObject
hr = pDataObj->GetData(&fmt, &stg);
CHR(hr);
if ( NULL != stg.hGlobal)
{
// Pull the ItemRefArray out of the STGMEDIUM stucture.
*ppItemArray = (ItemRefArray *)stg.hGlobal;
}
else
{
CHR(E_FAIL);
}
}
else
{
CHR(E_FAIL);
}
}
Error:
RELEASE_OBJ(pDataObj);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// AddSenderToContacts
//
// This method actually does the work of adding the sender of a message to the
// contacts store.
//
// Since we have good logic to prevent the Add Sender To Contacts menu item
// from being enabled when it should not - we should be able to trust that
// when this method is hit
// 1) the folder we are on is an incoming mail folder.
// 2) there is only 1 selected message.
// So we don't have to scrutinize the contents of the ItemRefArray as much
// in this method.
//
// Notes: We KNOW that the FIRST item is in the ItemRefArray is always a FOLDER
// item if are a ListView Extension. We also know that the rest of the
// items are selected messages.
//
// Arguments:
// none
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::AddSenderToContacts()
{
HRESULT hr = E_FAIL;
ItemRefArray *pItemArray = NULL;
ItemRef *pRef = NULL;
IMessage *pMsg = NULL;
IMAPIProp *pProp = NULL;
SPropValue *rgProps= NULL;
IPOutlookApp2 *pPOOM = NULL;
IContact *pContact = NULL;
hr = GetItemRefArray(&pItemArray);
CHR(hr);
if (pItemArray)
{
// If we have made it here... we are good to get
// the Display Name and Email Address of the sender
// We should be able to trust that
// 1) the folder we are on is an incoming mail folder.
// 2) there is only 1 selected message.
ULONG cbEntry = 0;
ENTRYID *pEntryID = NULL;
ULONG cValues = 0;
ULONG rgTags[] = {2, PR_SENDER_NAME, PR_SENDER_EMAIL_ADDRESS};
// Get the 2nd item and double check that the is indeed a Message item
pRef = &pItemArray->rgRefs[1];
CBR(IsMessage(pRef));
// Get the Entry Size - cbEntryID from the ItemRef
cbEntry = ((SBinary *)pRef->pRef)->cb;
CBR(cbEntry);
// Get the pointer to the EntryID from the ItemRef
pEntryID = (ENTRYID *) ((SBinary *)pRef->pRef)->lpb;
CPR(pEntryID);
// Logon to MAPI
hr = MAPILogonEx(0, NULL, NULL, 0, &m_pSession);
CHR(hr);
// Open the Message
// Note if you have a Message's Entry ID you can go straight to it
// no need to open the folder first
hr = m_pSession->OpenEntry(cbEntry, pEntryID, NULL, 0, NULL, (LPUNKNOWN *)&pMsg);
CHR(hr);
CPR(pMsg);
// Get an IMAPIProp Interface
hr = pMsg->QueryInterface(IID_IMAPIProp, (LPVOID *) &pProp);
CHR(hr);
CPR(pProp);
// Get the pMsg PR_SENDER_NAME and PR_SENDER_EMAIL_ADDRESS property
hr = pProp->GetProps((LPSPropTagArray)rgTags, MAPI_UNICODE, &cValues, &rgProps);
CHR(hr);
LPTSTR szDisplayName = NULL;
LPTSTR szEmailAddress = NULL;
// NOTE: Sender Name may be missing - so first validate that the prop came back
// then validate there is a value, then get the value.
//
// NOTE: Sender name may be "First Last" or "Last, First" or other
// but we are not doing any additional parsing here.
if (PR_SENDER_NAME == rgProps[0].ulPropTag)
{
if (rgProps[0].Value.lpszW)
{
szDisplayName = (LPTSTR)rgProps[0].Value.lpszW;
}
}
// NOTE: Email address may be missing - but it is unlikely - either way
// first validate that the prop came back, then validate
// that there is a value, then get the value.
//
// NOTE: The email address MAY be formed as
// "Display Name" <email@address.com>
// So additional parsing may be necessary here. It all depends on how
// the email address of the message was created.
if (PR_SENDER_EMAIL_ADDRESS == rgProps[1].ulPropTag)
{
if (rgProps[1].Value.lpszW)
{
szEmailAddress= (LPTSTR)rgProps[1].Value.lpszW;
}
}
// Create the contact
// Use POOM APIs to create new contact
hr = GetPOOM(&pPOOM);
CHR(hr);
// Create a Contact object
hr = pPOOM->CreateItem (olContactItem, (IDispatch **) &pContact);
CHR(hr);
// Although POOM and Contacts supports FIRST and LAST name fields
// We are not going parse the display name (PR_SENDER_NAME)
// Instead will will put the entire display name (PR_SENDER_NAME)
// in the "File As" field. First and Last name fields will be blank
if (szDisplayName)
{
hr = pContact->put_FileAs(szDisplayName);
CHR(hr);
}
// Store the Email Adddress
// NOTE: As noted above this may be more than just an email address
// depending on which software created the email
if (szEmailAddress)
{
hr = pContact->put_Email1Address(szEmailAddress);
CHR(hr);
}
// Save the new contact
hr = pContact->Save();
CHR(hr);
// Display the new Contact
hr = pContact->Display();
CHR(hr);
// NOTE: we could first LOOK-UP on "Email Address" or "File As" to prevent
// making lots of the same record. But that is outside the scope of this example
}
Error:
// Make sure we do not leak memory
MAPIFreeBuffer(rgProps);
if (pPOOM)
{ hr = pPOOM->Logoff();
}
RELEASE_OBJ(pPOOM);
RELEASE_OBJ(pContact);
RELEASE_OBJ(pProp);
RELEASE_OBJ(pMsg);
RELEASE_OBJ(m_pSession);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// DeleteAllInFolder
//
// This method actually does the work of deleting all of the email in the
// current folder
//
// Since we have good logic to prevent the Delete All In Folder menu item
// from being enabled when it should not - we should be able to trust that
// when this method is hit
// 1) the folder we are on is has mail in it.
//
// Deleting items in any folder other than the Deleted Items folder means
// moving the items to the Deleted Items folder. But in the Deleted Items
// Folder - deleting means deleting.
//
// Notes: We KNOW that the FIRST item is in the ItemRefArray is always a FOLDER
// item if are a ListView Extension.
//
// Arguments:
// none
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::DeleteAllInFolder()
{
HRESULT hr = E_FAIL;
ItemRefArray *pItemArray = NULL;
ItemRef *pRef = NULL;
IMAPIFolder *pFolder = NULL;
IMAPIProp *pProp = NULL;
IMAPIFolder *pWasteBasket= NULL;
LPENTRYLIST lpmsgEntryList = NULL;
SPropValue *rgFolderProps= NULL;
SRowSet *pRows = NULL;
hr = GetItemRefArray(&pItemArray);
CHR(hr);
if (pItemArray)
{
// Double check that the 1st item is indeed a Folder item
pRef = &pItemArray->rgRefs[0];
CBR(IsFolder(pRef));
ULONG cbEntry = 0;
ENTRYID *pEntryID = NULL;
ULONG cValues = 0;
ULONG rgTags[] = {2, PR_CONTENT_COUNT, PR_FOLDER_TYPE};
ULONG cMsgCount = 0;
BOOL IsDeletedItems = FALSE;
// Get the Entry Size - cbEntryID from the ItemRef
cbEntry = ((SBinary *)pRef->pRef)->cb;
CBR(cbEntry);
// Get the pointer to the EntryID from the ItemRef
pEntryID = (ENTRYID *) ((SBinary *)pRef->pRef)->lpb;
CPR(pEntryID);
// Logon to MAPI
hr = MAPILogonEx(0, NULL, NULL, 0, &m_pSession);
CHR(hr);
// Open the Folder
hr = m_pSession->OpenEntry(cbEntry, pEntryID, NULL, 0, NULL, (LPUNKNOWN *)&pFolder);
CHR(hr);
CPR(pFolder);
// Get an IMAPIProp Interface
hr = pFolder->QueryInterface(IID_IMAPIProp, (LPVOID *) &pProp);
CHR(hr);
CPR(pProp);
// Get the Folder PR_CONTENT_COUNT property
hr = pProp->GetProps((LPSPropTagArray)rgTags, MAPI_UNICODE, &cValues, &rgFolderProps);
CHR(hr);
CBR(PR_CONTENT_COUNT == rgFolderProps[0].ulPropTag);
CBR(PR_FOLDER_TYPE == rgFolderProps[1].ulPropTag);
// Store the COUNT of messages in this folder
cMsgCount = rgFolderProps[0].Value.ul;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -