Quitar la definición de formulario personalizada que se guarda con un mensaje
Hace referencia a: Outlook 2013 | Outlook 2016
En este tema se muestra un ejemplo de código en C++ que convierte un mensaje que se ha guardado con una definición de formulario personalizada en un mensaje normal sin la definición del formulario.
En Microsoft Outlook 2010 o Microsoft Outlook 2013, puede compartir formularios que contienen páginas de formulario personalizadas publicándolas en una biblioteca de formularios o guardando la definición de formulario correspondiente con un mensaje. Un formulario personalizado guardado con un mensaje se conoce normalmente como "formulario único", ya que el formulario solo se comparte para ver ese mensaje específico como una instancia única. Normalmente, lo hace cuando el formulario no se publica en una biblioteca de formularios, pero quiere que el destinatario use el formulario personalizado al abrir el elemento. Puede especificar que un formulario sea un elemento único en el Designer Formularios; para ello, active la casilla Enviar definición de formulario con elemento en la página Propiedades del formulario.
Los formularios que contienen páginas de formulario se pueden personalizar con código en Visual Basic Scripting Edition (VBScript). Los mensajes que se guardan con definiciones de formulario suelen ser de mayor tamaño. Por motivos de seguridad y almacenamiento, Outlook 2010 y Outlook 2013 omiten las definiciones de formulario guardadas con cualquier elemento.
Para convertir un mensaje que se guarda con una definición de formulario personalizada en una sin, debe quitar cuatro propiedades con nombre:
Además, también debe quitar la propiedad canónica PidLidPropertyDefinitionStream que contiene las definiciones de propiedades personalizadas guardadas con ese mensaje. Un efecto secundario de quitar esta propiedad es que los modelos de objetos de Outlook 2010 o Outlook 2013 y la interfaz de usuario de Outlook 2010 o Outlook 2013 ya no podrán acceder a las propiedades de usuario que se han establecido en el mensaje. Todavía puede acceder a estas propiedades y sus valores a través de MAPI. Tenga en cuenta que si no quita esta propiedad y el mensaje se guarda con otra definición de formulario, la propiedad canónica PidLidPropertyDefinitionStream se sobrescribe parcialmente con nuevos datos y no se garantiza la integridad de los datos.
Si quita la propiedad canónica PidLidPropertyDefinitionStream, también debe quitar la marca INSP_PROPDEFINITION de la propiedad canónica PidLidCustomFlag.
La función siguiente, RemoveOneOff
, acepta como parámetros de entrada un puntero a un mensaje y un indicador de si se va a quitar la propiedad canónica PidLidPropertyDefinitionStream. Con el puntero de mensaje, llama a IMAPIProp::GetIDsFromNames para obtener los identificadores de propiedad adecuados y, a continuación, llama a IMAPIProp::D eleteProps para quitar las propiedades con nombre. También llama a IMAPIProp::GetProps para obtener la propiedad canónica PidLidCustomFlag y borra la marca de INSP_ONEOFFFLAGS y INSP_PROPDEFINITION marca según corresponda de esa propiedad, de modo que Outlook 2010 y Outlook 2013 no busquen las propiedades con nombre que se han quitado.
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;
}