删除随邮件一起保存的自定义表单定义
适用于:Outlook 2013 | Outlook 2016
本主题演示 C++ 中的代码示例,该示例将已使用自定义表单定义保存的消息转换为没有表单定义的常规消息。
在 Microsoft Outlook 2010 或 Microsoft Outlook 2013 中,可以通过将自定义窗体页发布到表单库或保存包含自定义窗体页的表单定义与消息一起共享。 随邮件一起保存的自定义表单通常称为“一次性表单”,因为该表单仅用于将特定邮件作为一次性实例进行查看。 通常在窗体未在窗体库中发布,但您希望收件人在打开项目时使用自定义窗体时执行此操作。 通过在窗体的“属性”页上选择“使用项检查发送表单定义”框,可以在“窗体”Designer将窗体指定为一次性表单。
可以使用 Visual Basic Scripting Edition (VBScript) 中的代码自定义包含表单页的表单。 与表单定义一起保存的消息的大小通常更大。 出于安全和存储原因,Outlook 2010 和 Outlook 2013 忽略随任何项目一起保存的表单定义。
若要将使用自定义表单定义保存的消息转换为不使用的表单定义,必须删除四个命名属性:
此外,还应删除 PidLidPropertyDefinitionStream 规范属性 ,该属性包含随该消息一起保存的自定义属性的定义。 删除此属性的副作用是 Outlook 2010 或 Outlook 2013 对象模型以及 Outlook 2010 或 Outlook 2013 用户界面将不再能够访问已在邮件上设置的用户属性。 你仍可以通过 MAPI 访问这些属性及其值。 请注意,如果不删除此属性,并且消息是使用另一个表单定义保存的, 则 PidLidPropertyDefinitionStream 规范属性 将被新数据部分覆盖,并且无法保证数据完整性。
如果删除 PidLidPropertyDefinitionStream 规范属性,则还应从 PidLidCustomFlag 规范属性中删除 INSP_PROPDEFINITION 标志。
以下函数 RemoveOneOff
接受一个指向消息的指针和指示是否删除 PidLidPropertyDefinitionStream 规范属性的输入参数。 它使用消息指针调用 IMAPIProp::GetIDsFromNames 以获取相应的属性标识符,然后调用 IMAPIProp::D eleteProps 以删除命名属性。 它还调用 IMAPIProp::GetProps 获取 PidLidCustomFlag 规范属性 ,并清除该属性中的 INSP_ONEOFFFLAGS 标志和 INSP_PROPDEFINITION 标志,以便 Outlook 2010 和 Outlook 2013 不会查找已删除的命名属性。
ULONG aulOneOffIDs[] = {dispidFormStorage,
dispidPageDirStream,
dispidFormPropStream,
dispidScriptStream,
dispidPropDefStream, // dispidPropDefStream must remain next to last in list
dispidCustomFlag}; // dispidCustomFlag must remain last in list
#define ulNumOneOffIDs (sizeof(aulOneOffIDs)/sizeof(aulOneOffIDs[0]))
HRESULT RemoveOneOff(LPMESSAGE lpMessage, BOOL bRemovePropDef)
{
if (!lpMessage) return MAPI_E_INVALID_PARAMETER;
HRESULT hRes = S_OK;
MAPINAMEID rgnmid[ulNumOneOffIDs];
LPMAPINAMEID rgpnmid[ulNumOneOffIDs];
LPSPropTagArray lpTags = NULL;
ULONG i = 0;
for (i = 0 ; i < ulNumOneOffIDs ; i++)
{
rgnmid[i].lpguid = (LPGUID)&PSETID_Common;
rgnmid[i].ulKind = MNID_ID;
rgnmid[i].Kind.lID = aulOneOffIDs[i];
rgpnmid[i] = &rgnmid[i];
}
hRes = lpMessage->GetIDsFromNames(
ulNumOneOffIDs,
rgpnmid,
0,
&lpTags);
if (lpTags)
{
// The last prop is the flag value
// to be updated, don't count it
lpTags->cValues = ulNumOneOffIDs-1;
// If the prop def stream is not to be removed, don't count it
if (!bRemovePropDef)
{
lpTags->cValues = lpTags->cValues-1;
}
hRes = lpMessage->DeleteProps(
lpTags,
0);
if (SUCCEEDED(hRes))
{
SPropTagArray pTag = {0};
ULONG cProp = 0;
LPSPropValue lpCustomFlag = NULL;
// Grab dispidCustomFlag, the last tag in the array
pTag.cValues = 1;
pTag.aulPropTag[0] = CHANGE_PROP_TYPE(
lpTags->aulPropTag[ulNumOneOffIDs-1],
PT_LONG);
hRes = lpMessage->GetProps(
&pTag,
fMapiUnicode,
&cProp,
&lpCustomFlag);
if (SUCCEEDED(hRes) &&
1 == cProp && lpCustomFlag &&
PT_LONG == PROP_TYPE(lpCustomFlag->ulPropTag))
{
// Clear the INSP_ONEOFFFLAGS bits so Outlook
// doesn't look for the props that have been deleted
lpCustomFlag->Value.l =
lpCustomFlag->Value.l & ~(INSP_ONEOFFFLAGS);
if (bRemovePropDef)
{
lpCustomFlag->Value.l =
lpCustomFlag->Value.l & ~(INSP_PROPDEFINITION);
}
hRes = lpMessage->SetProps(
1,
lpCustomFlag,
NULL);
}
hRes = lpMessage->SaveChanges(KEEP_OPEN_READWRITE);
}
}
MAPIFreeBuffer(lpTags);
return hRes;
}