📄 inboxmenuext.cpp
字号:
//
// Runs a context menu command when the user selects one that was
// inserted with QueryContextMenu. This method is called by the shell when one
// of the items added by the menu extension is actioned uponed
//
// Arguments:
// [IN] LPCMINVOKECOMMANDINFO lpici - a pointer to a CMINVOKECOMMANDINFO
// structure which contains data about the menu item clicked on by a
// user.
//
// Return Values:
// HRESULT - S_OK on success. E_INVALIDARG, E_FAIL and other HRESULTS are
// possible on failure
//
HRESULT STDMETHODCALLTYPE MenuExtension::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
HRESULT hr = S_OK;
if (lpici->lpVerb)
{
switch(m_ExtensionType)
{
case Context:
if (!_tcscmp(cszAddSender, (LPCTSTR)lpici->lpVerb))
{
hr = AddSenderToContacts();
CHR(hr);
}
else
{
CHR(E_INVALIDARG);
}
break;
case Softkey:
if (!_tcscmp(cszMarkAll, (LPCTSTR)lpici->lpVerb))
{
hr = MarkAllInFolderAsRead();
CHR(hr);
}
else if (!_tcscmp(cszDeleteAll, (LPCTSTR)lpici->lpVerb))
{
hr = DeleteAllInFolder();
CHR(hr);
}
else
{
CHR(E_INVALIDARG);
}
break;
}
}
Error:
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// GetCommandString - IContextMenu interface Method
//
// Called by the shell to validate that the command exists, to get the command
// name, or to get the command help text.
//
// Arguments:
// [IN] Specifies the menu item ID, offset from the idCmdFirst
// parameter of QueryContextMenu.
// [IN] UINT uType - Bitmask that specifies that GetCommandString should
// either validate that the command exists, get the command name
// string, or get the help text string. For a list of possible flag
// values, see the table in IContextMenu::GetCommandString Documentation
// NOTE: The inbox application will only ever send GCS_VERB
// [IN] UINT *pwReserved - Reserved (ignored, must pass NULL).
// [OUT] LPSTR pszName - Specifies the string buffer.
// [IN] UINT cchMax - Specifies the size of the string buffer (pszName)
//
// Return Values:
// HRESULT - S_OK on success. E_INVALIDARG, E_FAIL and other HRESULTS are
// possible on failure
//
HRESULT STDMETHODCALLTYPE MenuExtension::GetCommandString(UINT_PTR idCmd,
UINT uType, UINT* pwReserved, LPSTR pszName, UINT cchMax)
{
return GetCommandStringHelper(idCmd, (TCHAR *) pszName, cchMax);
}
///////////////////////////////////////////////////////////////////////////////
// Create (Static method)
//
// When the applications's menu is rendered, it checks to see if there are any
// menu extensions registered. If so DllGetClassObject (See Main.cpp) will be
// called for each extension. DllGetClassObject instantiates MyClassFactory
// (see ClassFactory.cpp) which will call MyClassFactory::CreateInstance which
// will in turn call this method
//
// Create then calls the MenuExtension constructor.
//
// Arguments:
// [OUT] IObjectWithSite** ppNew - a pointer to our new Menu Extension
// [IN] ExtensionType extensionType - which type of extension is this
//
// Return Values:
// HRESULT - S_OK on success. E_OUTOFMEMORY, E_FAIL and other HRESULTS are
// possible on failure
//
HRESULT MenuExtension::Create(IObjectWithSite** ppNew, ExtensionType extensionType)
{
HRESULT hr = S_OK;
MenuExtension* pte = NULL;
pte = new MenuExtension(extensionType);
CPR(pte);
hr = pte->Initialize();
if (SUCCEEDED(hr))
{
*ppNew = pte;
pte = NULL;
}
Error:
delete(pte);
return(hr);
}
///////////////////////////////////////////////////////////////////////////////
// EnableAddSenderToContacts
//
// Determine if the folder we are on is an incoming mail folder. Drafts,
// Outbox, and Sent Items are NOT incoming mail folders, all others are
//
// Determine if there is only 1 selected message. If there are more than
// 1 selected we can not do Add Sender to contacts
//
// Notes: We know that the first item in the ItemRefArray is always a FOLDER
// item if this is a ListView Extension. We also know that the rest of the
// items are selected messages.
//
// Arguments:
// none
//
// Return Values:
// BOOL - TRUE if the menu item should be enabled
//
BOOL MenuExtension::EnableAddSenderToContacts()
{
BOOL fResult = FALSE;
HRESULT hr = E_FAIL;
ItemRefArray *pItemArray = NULL;
ItemRef *pRef = NULL;
IMAPIFolder *pFolder = NULL;
IMAPIProp *pProp = NULL;
// Get the ItemRefArray
hr = GetItemRefArray(&pItemArray);
CHR(hr);
// Make sure we have a valid pointer the ItemRefArray
if (pItemArray)
{
// REMINDER
// ItemRefArray and ItemRef stuctures
//
// struct ItemRefArray
// {
// int cRefs; // count of ItemRefs in rgRefs
// ItemRef rgRefs[]; // rgRefs has cRefs entries
// };
// struct ItemRef
// {
// ITEM_TYPE_ID* pType; // identifies the the type of pRef
// void* pRef; // a pointer to the data
// };
// Make sure that there are only 2 items in the array
// 1st is the folder
// 2nd is the selected message
fResult = (2 == pItemArray->cRefs);
if (fResult)
{
// Get the 1st ItemRef from the ItemRefArray
pRef = &pItemArray->rgRefs[0];
// Check if the 1st item is a folder
fResult = IsFolder(pRef);
// Check if the folder is NOT Drafts, Outbox or Sent Items
if (fResult)
{
ULONG cbEntry = 0;
ENTRYID *pEntryID = NULL;
ULONG cValues = 0;
ULONG rgTags[] = {1, PR_FOLDER_TYPE};
SPropValue *rgProps= NULL;
// We know that pRef is an ItemRef and that
// pRef->pType == ITI_FolderItemRef see IsFolder(pRef)
// pRef->pRef is of type SBinary
// REMINDER
//typedef struct _SBinary
// {
// ULONG cb; // count in bytes of lpb
// LPBYTE lpb; // pointer (to an EntryID)
// } SBinary
// 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 Type property
hr = pProp->GetProps((LPSPropTagArray)rgTags, MAPI_UNICODE, &cValues, &rgProps);
CHR(hr);
CBR(PR_FOLDER_TYPE == rgProps[0].ulPropTag);
// Make sure that this folder is NOT Drafts, Outbox, or Sent Items
if ((rgProps[0].Value.ul & FOLDER_OUTBOX) ||
(rgProps[0].Value.ul & FOLDER_DRAFTS) ||
(rgProps[0].Value.ul & FOLDER_SENT_ITEMS))
{
fResult = FALSE;
}
MAPIFreeBuffer(rgProps);
}
if (fResult)
{
// Now we are sure that there are only 2 elements in the array
// Now we are sure we are in a valid folder for this feature
// Now make sure that the 2nd item is indeed a message
pRef = &pItemArray->rgRefs[1];
fResult= IsMessage(pRef);
}
}
}
Error:
if FAILED(hr)
{
fResult = FALSE;
}
RELEASE_OBJ(pProp);
RELEASE_OBJ(pFolder);
RELEASE_OBJ(m_pSession);
return fResult;
}
///////////////////////////////////////////////////////////////////////////////
// AreThereMessagesInFolder
//
// Determine if there are messages in the current folder.
//
// Arguments:
// none
//
// Return Values:
// BOOL - TRUE if there are messages in the current folder
//
BOOL MenuExtension::AreThereMessagesInFolder()
{
BOOL fResult = FALSE;
HRESULT hr = E_FAIL;
ItemRefArray *pItemArray = NULL;
ItemRef *pRef = NULL;
IMAPIFolder *pFolder = NULL;
IMAPIProp *pProp = NULL;
SPropValue *rgProps= NULL;
hr = GetItemRefArray(&pItemArray);
CHR(hr);
if (pItemArray)
{
// Check if the item 1 is a folder
pRef = &pItemArray->rgRefs[0];
fResult = IsFolder(pRef);
// Check if the COUNT of items in the folder
if (fResult)
{
ULONG cbEntry = 0;
ENTRYID *pEntryID = NULL;
ULONG cValues = 0;
ULONG rgTags[] = {1, PR_CONTENT_COUNT};
// 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, &rgProps);
CHR(hr);
CBR(PR_CONTENT_COUNT == rgProps[0].ulPropTag);
fResult = (rgProps[0].Value.ul > 0);
}
}
Error:
if FAILED(hr)
{
fResult = FALSE;
}
MAPIFreeBuffer(rgProps);
RELEASE_OBJ(pProp);
RELEASE_OBJ(pFolder);
RELEASE_OBJ(m_pSession);
return fResult;
}
///////////////////////////////////////////////////////////////////////////////
// GetCommandStringHelper
//
// Determines which Command string we should use based on
// the current ExtensionType and current command ID
//
// Arguments:
// [IN] int idCmd - the command ID
// [OUT] TCHAR *pszName - a buffer to place the string into
// [IN] UINT idCmd - the size of the buffer (pszName)
//
// Return Values:
// HRESULT - S_OK on success, E_INVALIDARG if idCmd does not make sense
// plus other failing HRESULTS are possible
//
HRESULT MenuExtension::GetCommandStringHelper(int idCmd, TCHAR *pszName, UINT cchName)
{
HRESULT hr = E_INVALIDARG;
if (pszName)
{
switch (m_ExtensionType)
{
case Context:
{
if (idCmd == m_idc1)
{
// Add Sender to Contacts
hr = StringCchCopy(pszName, cchName, cszAddSender);
CHR(hr);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -