建立複雜的週期性約會專案
適用於:Outlook 2013 |Outlook 2016
MAPI 可用來建立週期性約會專案。
如需如何從 MFCMAPI 應用程式下載、檢視及執行程式代碼以及本主題所參考 CreateOutlookItemsAddin 專案的相關信息,請參閱 安裝本節中使用的範例。
若要建立約會專案
開啟訊息存放區。 如需如何開啟訊息存放區的相關信息,請 參閱開啟訊息存放區。
在訊息存放區中開啟 [行事曆] 資料夾。 請 參閱 PR_IPM_APPOINTMENT_ENTRYID (PidTagIpmAppointmentEntryId) 。
呼叫 Calendar 資料夾上的 IMAPIFolder::CreateMessage 方法,以建立新的約會專案。
設定 dispidApptRecur (PidLidAppointmentRecur) 屬性和建立週期性約會所需的其他屬性。
儲存新的約會專案。
AddAppointment
CreateOutlookItemsAddin 專案Appointments.cpp原始程式檔中的 函式會示範這些步驟。 函AddAppointment
式會從 [新增約會] 對話框取得參數,當您在 MFCMAPI 範例應用程式的 [載入宏] 功能表上按兩下 [新增約會] 時,就會顯示這些參數。
DisplayAddAppointmentDialog
Appointments.cpp中的函式會顯示對話框,並將值從對話框傳遞至函式AddAppointment
。 函 DisplayAddAppointmentDialog
式與使用MAPI建立約會項目沒有直接關聯,因此不會列於此處。
重要事項
當您按一下 [載入宏] 選單上的 [新增約會] 命令時,MFCMAPI 應用程式中的程式代碼無法確保已選取 [行事曆] 資料夾。 在 Calendar 資料夾以外的資料夾中建立約會專案可能會導致未定義的行為。 在 MFCMAPI 應用程式中使用 [新增約會] 命令之前,請確定您已選取 [行事曆] 資料夾。
方法 AddAppointment
如下所列。 請注意,傳遞至 方法的 AddAppointment
lpFolder 參數是 IMAPIFolder 介面的指標,代表建立週期性約會的資料夾。 假設 lpFolder 參數代表 IMAPIFolder 介面,程式代碼會呼叫 IMAPIFolder::CreateMessage 方法。
CreateMessage 方法會傳回成功程式代碼和 IMessage 介面指標的指標。 大部分的 AddAppointment
函式程式代碼會處理指定屬性的工作,以準備呼叫 IMAPIProp::SetProps 方法。 如果 SetProps 方法的呼叫成功,則會呼叫 IMAPIProp::SaveChanges 方法來認可對存放區的變更,並建立新的行事歷專案。
函 AddAppointment
式會設定一些具名屬性。 如需具名屬性及其建立方式的相關信息,請參閱 使用MAPI建立 Outlook 2007 專案。 由於用於約會專案的具名屬性會佔用多個屬性集,因此在建置參數以傳遞至 IMAPIProp::GetIDsFromNames 方法時,必須小心謹慎。
函 AddAppointment
式會使用數個協助程式函式來建置各種約會相關屬性的結構。 和 BuildTimeZoneStruct
BuildTimeZoneDefinition
協助程式函式可用來建置結構,以指定時區相關的屬性。 時區相關的屬性為 dispidTimeZoneStruct (PidLidTimeZoneStruct) 、 dispidTimeZoneDesc (PidLidTimeZoneDescription) 、 dispidApptTZDefRecur (PidLidAppointmentTimeZoneDefinitionRecur) 、 dispidApptTZDefStartDisplay (PidLidAppointmentTimeZoneDefinitionStartDisplay) ,以及 dispidApptTZDefEndDisplay (PidLidAppointmentTimeZoneDefinitionEndDisplay) ,並會在 [MS-OXOCAL] 的對應章節中討論。
函 BuildGlobalObjectID
式是用來建置結構,指定 LID_GLOBAL_OBJID (PidLidGlobalObjectId) 和 dispidCleanGlobalObjId (PidLidCleanGlobalObjectId) 属性,這些屬性會在 [MS-OXOCAL] 的對應章節中討論。 指定 dispidApptRecur 屬性的結構是使用 BuildWeeklyAppointmentRecurrencePattern
函式所建置。
如需函式所建置結構的 BuildWeeklyAppointmentRecurrencePattern
相關信息,請參閱 PidLidAppointmentRecur Canonical 屬性。 請注意,雖然可能會有各種不同的約會週期模式, BuildWeeklyAppointmentRecurrencePattern
但此函式只會建立每周約會週期模式。 它也會使用數個硬式編碼值,例如公曆類型 (公曆) 、星期 (星期日) 的第一天,以及修改或刪除的實例數目 (沒有) 。 較一般用途的約會週期模式建立函式必須接受這類變數作為參數。
以下是函式的 AddAppointment
完整清單。
HRESULT AddAppointment(LPMAPIFOLDER lpFolder,
SYSTEMTIME* lpstStartDateLocal, // PidLidAppointmentRecur
SYSTEMTIME* lpstEndDateLocal, // PidLidAppointmentRecur
SYSTEMTIME* lpstStartFirstUST, // PidLidAppointmentStartWhole, PidLidCommonStart, PR_START_DATE
SYSTEMTIME* lpstEndFirstUST, // PidLidAppointmentEndWhole, PidLidCommonEnd, PR_END_DATE
SYSTEMTIME* lpszClipStartUST, // PidLidClipStart
SYSTEMTIME* lpstClipEndUST, // PidLidClipEnd
SYSTEMTIME* lpstFirstDOW, // PidLidAppointmentRecur
DWORD dwStartOffsetLocal, // PidLidAppointmentRecur
DWORD dwEndOffsetLocal, // PidLidAppointmentRecur
DWORD dwPeriod, // PidLidAppointmentRecur
DWORD dwOccurrenceCount, // PidLidAppointmentRecur
DWORD dwPatternTypeSpecific, // PidLidAppointmentRecur
ULONG ulDuration, // PidLidAppointmentDuration
LPWSTR szSubject, // PR_SUBJECT_W
LPWSTR szLocation, // PidLidLocation
LPWSTR szPattern) // PidLidRecurrencePattern
{
if (!lpFolder) return MAPI_E_INVALID_PARAMETER;
HRESULT hRes = S_OK;
LPMESSAGE lpMessage = 0;
// create a message and set its properties
hRes = lpFolder->CreateMessage(0,
0,
&lpMessage);
if (SUCCEEDED(hRes))
{
MAPINAMEID rgnmid[ulAppointmentProps];
LPMAPINAMEID rgpnmid[ulAppointmentProps];
LPSPropTagArray lpNamedPropTags = NULL;
ULONG i = 0;
for (i = 0 ; i < ulAppointmentProps ; i++)
{
if (i < ulFirstMeetingProp)
rgnmid[i].lpguid = (LPGUID)&PSETID_Appointment;
else if (i < ulFirstCommonProp)
rgnmid[i].lpguid = (LPGUID)&PSETID_Meeting;
else
rgnmid[i].lpguid = (LPGUID)&PSETID_Common;
rgnmid[i].ulKind = MNID_ID;
rgnmid[i].Kind.lID = aulAppointmentProps[i];
rgpnmid[i] = &rgnmid[i];
}
hRes = lpFolder->GetIDsFromNames(
ulAppointmentProps,
(LPMAPINAMEID*) &rgpnmid,
NULL,
&lpNamedPropTags);
if (SUCCEEDED(hRes) && lpNamedPropTags)
{
// Because the properties to be set are known in advance,
// most of the structures involved can be statically declared
// to minimize expensive MAPIAllocateBuffer calls.
SPropValue spvProps[NUM_PROPS] = {0};
spvProps[p_PidLidAppointmentSequence].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentSequence],PT_LONG);
spvProps[p_PidLidBusyStatus].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidBusyStatus],PT_LONG);
spvProps[p_PidLidLocation].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidLocation],PT_UNICODE);
spvProps[p_PidLidAppointmentStartWhole].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentStartWhole],PT_SYSTIME);
spvProps[p_PidLidAppointmentEndWhole].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentEndWhole],PT_SYSTIME);
spvProps[p_PidLidAppointmentDuration].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentDuration],PT_LONG);
spvProps[p_PidLidAppointmentColor].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentColor],PT_LONG);
spvProps[p_PidLidResponseStatus].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidResponseStatus],PT_LONG);
spvProps[p_PidLidRecurring].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidRecurring],PT_BOOLEAN);
spvProps[p_PidLidClipStart].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidClipStart],PT_SYSTIME);
spvProps[p_PidLidClipEnd].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidClipEnd],PT_SYSTIME);
spvProps[p_PidLidTimeZoneStruct].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidTimeZoneStruct],PT_BINARY);
spvProps[p_PidLidTimeZoneDescription].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidTimeZoneDescription],PT_UNICODE);
spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentTimeZoneDefinitionRecur],
PT_BINARY);
spvProps[p_PidLidAppointmentTimeZoneDefinitionStartDisplay].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentTimeZoneDefinitionStartDisplay],
PT_BINARY);
spvProps[p_PidLidAppointmentTimeZoneDefinitionEndDisplay].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentTimeZoneDefinitionEndDisplay],
PT_BINARY);
spvProps[p_PidLidAppointmentRecur].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidAppointmentRecur],PT_BINARY);
spvProps[p_PidLidRecurrenceType].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidRecurrenceType],PT_LONG);
spvProps[p_PidLidRecurrencePattern].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidRecurrencePattern],PT_UNICODE);
spvProps[p_PidLidIsRecurring].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidIsRecurring],PT_BOOLEAN);
spvProps[p_PidLidGlobalObjectId].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidGlobalObjectId],PT_BINARY);
spvProps[p_PidLidCleanGlobalObjectId].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidCleanGlobalObjectId],PT_BINARY);
spvProps[p_PidLidCommonStart].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidCommonStart],PT_SYSTIME);
spvProps[p_PidLidCommonEnd].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidCommonEnd],PT_SYSTIME);
spvProps[p_PidLidSideEffects].ulPropTag
= CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[p_PidLidSideEffects],PT_LONG);
spvProps[p_PR_SUBJECT_W].ulPropTag = PR_SUBJECT_W;
spvProps[p_PR_START_DATE].ulPropTag = PR_START_DATE;
spvProps[p_PR_END_DATE].ulPropTag = PR_END_DATE;
spvProps[p_PR_MESSAGE_CLASS_W].ulPropTag = PR_MESSAGE_CLASS_W;
spvProps[p_PR_ICON_INDEX].ulPropTag = PR_ICON_INDEX;
spvProps[p_PR_CONVERSATION_INDEX].ulPropTag = PR_CONVERSATION_INDEX;
spvProps[p_PR_MESSAGE_FLAGS].ulPropTag = PR_MESSAGE_FLAGS;
spvProps[p_PidLidAppointmentSequence].Value.l = 0;
spvProps[p_PidLidBusyStatus].Value.l = olBusy;
spvProps[p_PidLidLocation].Value.lpszW = szLocation;
SystemTimeToFileTime(lpstStartFirstUST,&spvProps[p_PidLidAppointmentStartWhole].Value.ft);
SystemTimeToFileTime(lpstEndFirstUST,&spvProps[p_PidLidAppointmentEndWhole].Value.ft);
spvProps[p_PidLidAppointmentDuration].Value.l = ulDuration;
spvProps[p_PidLidAppointmentColor].Value.l = 0; // No color
spvProps[p_PidLidResponseStatus].Value.l = respNone;
spvProps[p_PidLidRecurring].Value.b = true;
SystemTimeToFileTime(lpszClipStartUST,&spvProps[p_PidLidClipStart].Value.ft);
SystemTimeToFileTime(lpstClipEndUST,&spvProps[p_PidLidClipEnd].Value.ft);
SYSTEMTIME stStandard = {0};
stStandard.wMonth = 0xB;
stStandard.wDay = 0x1;
stStandard.wHour = 0x2;
SYSTEMTIME stDaylight = {0};
stDaylight.wMonth = 0x3;
stDaylight.wDay = 0x2;
stDaylight.wHour = 0x2;
hRes = BuildTimeZoneStruct(
300,
0,
(DWORD)-60,
&stStandard,
&stDaylight,
&spvProps[p_PidLidTimeZoneStruct].Value.bin.cb,
&spvProps[p_PidLidTimeZoneStruct].Value.bin.lpb);
spvProps[p_PidLidTimeZoneDescription].Value.lpszW = L"(GMT-05:00) Eastern Time (US & Canada)";
SYSTEMTIME stRule1Standard = {0};
stRule1Standard.wMonth = 0xA;
stRule1Standard.wDay = 0x5;
stRule1Standard.wHour = 0x2;
SYSTEMTIME stRule1Daylight = {0};
stRule1Daylight.wMonth = 0x4;
stRule1Daylight.wDay = 0x1;
stRule1Daylight.wHour = 0x2;
if (SUCCEEDED(hRes)) hRes = BuildTimeZoneDefinition(
L"Eastern Standard Time",
0, // TZRule Flags
2006, // wYear
300, // lbias
0, // lStandardBias,
(DWORD)-60, // lDaylightBias,
&stRule1Standard, // stStandardDate
&stRule1Daylight, // stDaylightDate
TZRULE_FLAG_EFFECTIVE_TZREG, // TZRule Flags
2007, // wYear
300, // lbias
0, // lStandardBias,
(DWORD)-60, // lDaylightBias,
&stStandard, // stStandardDate
&stDaylight, // stDaylightDate
&spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.cb,
&spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.lpb);
spvProps[p_PidLidAppointmentTimeZoneDefinitionStartDisplay].Value.bin.cb
= spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.cb;
spvProps[p_PidLidAppointmentTimeZoneDefinitionStartDisplay].Value.bin.lpb
= spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.lpb;
spvProps[p_PidLidAppointmentTimeZoneDefinitionEndDisplay].Value.bin.cb
= spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.cb;
spvProps[p_PidLidAppointmentTimeZoneDefinitionEndDisplay].Value.bin.lpb
= spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.lpb;
if (SUCCEEDED(hRes)) hRes = BuildWeeklyAppointmentRecurrencePattern(
lpstStartDateLocal,
lpstEndDateLocal,
lpstFirstDOW,
dwStartOffsetLocal,
dwEndOffsetLocal,
dwPeriod,
dwOccurrenceCount,
dwPatternTypeSpecific,
&spvProps[p_PidLidAppointmentRecur].Value.bin.cb,
&spvProps[p_PidLidAppointmentRecur].Value.bin.lpb);
spvProps[p_PidLidRecurrenceType].Value.l = rectypeWeekly;
spvProps[p_PidLidRecurrencePattern].Value.lpszW = szPattern;
spvProps[p_PidLidIsRecurring].Value.b = true;
if (SUCCEEDED(hRes)) hRes = BuildGlobalObjectId(
&spvProps[p_PidLidGlobalObjectId].Value.bin.cb,
&spvProps[p_PidLidGlobalObjectId].Value.bin.lpb);
spvProps[p_PidLidCleanGlobalObjectId].Value.bin.cb = spvProps[p_PidLidGlobalObjectId].Value.bin.cb;
spvProps[p_PidLidCleanGlobalObjectId].Value.bin.lpb = spvProps[p_PidLidGlobalObjectId].Value.bin.lpb;
SystemTimeToFileTime(lpstStartFirstUST,&spvProps[p_PidLidCommonStart].Value.ft);
SystemTimeToFileTime(lpstEndFirstUST,&spvProps[p_PidLidCommonEnd].Value.ft);
spvProps[p_PidLidSideEffects].Value.l
= seOpenToDelete | seOpenToCopy | seOpenToMove | seCoerceToInbox | seOpenForCtxMenu;
spvProps[p_PR_SUBJECT_W].Value.lpszW = szSubject;
SystemTimeToFileTime(lpstStartFirstUST,&spvProps[p_PR_START_DATE].Value.ft);
SystemTimeToFileTime(lpstEndFirstUST,&spvProps[p_PR_END_DATE].Value.ft);
spvProps[p_PR_MESSAGE_CLASS_W].Value.lpszW = L"IPM.Appointment";
spvProps[p_PR_ICON_INDEX].Value.l = 0x00000401; // Recurring Appointment
if (SUCCEEDED(hRes)) hRes = BuildConversationIndex(
&spvProps[p_PR_CONVERSATION_INDEX].Value.bin.cb,
&spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb);
spvProps[p_PR_MESSAGE_FLAGS].Value.l = MSGFLAG_READ;
if (SUCCEEDED(hRes)) hRes = lpMessage->SetProps(NUM_PROPS, spvProps, NULL);
if (SUCCEEDED(hRes))
{
hRes = lpMessage->SaveChanges(FORCE_SAVE);
}
if (spvProps[p_PidLidTimeZoneStruct].Value.bin.lpb)
delete[] spvProps[p_PidLidTimeZoneStruct].Value.bin.lpb;
if (spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.lpb)
delete[] spvProps[p_PidLidAppointmentTimeZoneDefinitionRecur].Value.bin.lpb;
// Do not delete p_PidLidAppointmentTimeZoneDefinitionStartDisplay,
// it was borrowed from p_PidLidAppointmentTimeZoneDefinitionStartDisplay
// Do not delete p_PidLidAppointmentTimeZoneDefinitionEndDisplay,
// it was borrowed from p_PidLidAppointmentTimeZoneDefinitionStartDisplay
if (spvProps[p_PidLidAppointmentRecur].Value.bin.lpb)
delete[] spvProps[p_PidLidAppointmentRecur].Value.bin.lpb;
if (spvProps[p_PidLidGlobalObjectId].Value.bin.lpb)
delete[] spvProps[p_PidLidGlobalObjectId].Value.bin.lpb;
// Do not delete p_PidLidCleanGlobalObjectId, it was borrowed from p_PidLidGlobalObjectId
if (spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb)
delete[] spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb;
}
MAPIFreeBuffer(lpNamedPropTags);
}
if (lpMessage) lpMessage->Release();
return hRes;
}