Copyright © 2024 IMIBO. Privacy Statement
Extended MAPI in DELPHI
Experimental # 7
Ole Attachments inside RTF?
„How to render Microsoft Office Excel Table or Microsoft Office Word document inside RTF Body?“
What about PR_RENDERING_POSITION, PR_RTF_COMPRESSED, PR_ATTACH_METHOD?
Embedded OLE attachments are valid only inside RTF formatted messages.
This example application is trying to answer all these questions.
Procedure TfrmMain.LoadRTFBody; Var OleStreamC, OleStreamU: IStream; Stream: TMemoryStream; StreamBuffer: Array [0 .. 4095] Of Byte; iBytesRead: Longint; Begin RichEdit.Lines.Clear; If Not FPropExists(FMessage, PR_RTF_COMPRESSED) Then Begin RichEdit.Lines.Add('There is not PR_RTF_COMPRESSED Body!'); Exit; End; Stream := nil; Try hr := FMessage.OpenProperty(PR_RTF_COMPRESSED, @IID_IStream, 0, 0, IUnknown(OleStreamC)); If failed(hr) Then Raise EMAPIError.CreateMAPI(FMessage, hr); hr := WrapCompressedRTFStream(OleStreamC, 0, OleStreamU); If failed(hr) Then Raise EMAPIError.CreateMAPI(nil, hr); Stream := TMemoryStream.Create; hr := OleStreamU.Read(@StreamBuffer, Length(StreamBuffer) - 1, @iBytesRead); Repeat Stream.WriteBuffer(StreamBuffer, iBytesRead); hr := OleStreamU.Read(@StreamBuffer, Length(StreamBuffer), @iBytesRead); Until iBytesRead <= 0; Stream.Position := 0; RichEdit.Lines.LoadFromStream(Stream); LoadAttachments; Finally If Assigned(Stream) Then FreeAndNil(Stream); OleStreamU := nil; OleStreamC := nil; End; End; Procedure TfrmMain.LoadAttachments; Var AttachmentTable: IMAPITable; AttCount: ULONG; iCount: Integer; Attachment: IAttach; RowSet: PSRowSet; PropValue: PSPropValue; ListItem: TListItem; NUM: ULONG; Const AttachmentPropTagArray: Record cValues: ULONG; aulPropTag: Array [0 .. 2] Of ULONG; end = (cValues: 3; aulPropTag: (PR_ATTACH_NUM, PR_ATTACH_METHOD, PR_RENDERING_POSITION); ); SortOrderSet: TSSortOrderSet = (cSorts: 1; cCategories: 0; cExpanded: 0; aSort: ( (ulPropTag: PR_RENDERING_POSITION; ulOrder: TABLE_SORT_ASCEND) ); ); Begin ListView.Items.Clear; If Not FPropExists(FMessage, PR_HASATTACH) Or Not GetPropBoolean(FMessage, PR_HASATTACH) Then Exit; AttachmentTable := nil; RowSet := nil; Attachment := nil; Try hr := FMessage.GetAttachmentTable(fMapiUnicode, AttachmentTable); If failed(hr) Then Raise EMAPIError.CreateMAPI(FMessage, hr); hr := AttachmentTable.GetRowCount(0, AttCount); If failed(hr) Then Raise EMAPIError.CreateMAPI(AttachmentTable, hr); If AttCount < 1 Then Exit; // Retrieves all rows of a table. hr := HrQueryAllRows(AttachmentTable, @AttachmentPropTagArray, nil, @SortOrderSet, 0, RowSet); If failed(hr) Then Raise EMAPIError.CreateMAPI(AttachmentTable, hr); If Not Assigned(RowSet) Or (RowSet.cRows < 1) Then Exit; For iCount := 0 To RowSet.cRows - 1 Do Begin ListItem := ListView.Items.Add; // PR_ATTACH_NUM PropValue := PpropFindProp(RowSet.aRow[iCount].lpProps, RowSet.aRow[iCount].cValues, PR_ATTACH_NUM); If Assigned(PropValue) Then Begin NUM := ConvertMAPIPropValueToVariant(PropValue); ListItem.Caption := IntToStr(NUM); hr := FMessage.OpenAttach(NUM, nil, 0, Attachment); If failed(hr) Then Raise EMAPIError.CreateMAPI(FMessage, hr); End Else Continue; // PR_ATTACH_METHOD PropValue := PpropFindProp(RowSet.aRow[iCount].lpProps, RowSet.aRow[iCount].cValues, PR_ATTACH_METHOD); If Assigned(PropValue) Then ListItem.SubItems.Add(GetMAPIPascalString('AttachMethod', ConvertMAPIPropValueToVariant(PropValue))) Else ListItem.SubItems.Add(''); // PR_RENDERING_POSITION PropValue := PpropFindProp(RowSet.aRow[iCount].lpProps, RowSet.aRow[iCount].cValues, PR_RENDERING_POSITION); If Assigned(PropValue) Then ListItem.SubItems.Add(ConvertMAPIPropValueToVariant(PropValue)) Else ListItem.SubItems.Add(''); ProcessAttachmentForRTF(RichEdit.Handle, Attachment); Attachment := nil; End; Finally If Assigned(RowSet) Then FreePRows(RowSet); Attachment := nil; AttachmentTable := nil; End; End;