Delphi: Get the RTF for a paragraph in a rich edit
To the best of my knowledge, the only way to get the RTF for a portion of the contents in a rich edit control---without changing the selection---is as follows:
I tried to follow this plan, passing an Unassigned Variant to ITextRange.Copy(), but found that it was still Unassigned afterwards. I decided to get hold of proper declarations for ITextRange so that I need not go via Variant IDispatch. I found tom_TLB.pas on a Japanese site and took a copy. The file had obviously been produced by some automatic means. It declared ITextRange.Copy() as:
procedure Copy(out pVar: OleVariant); safecall;
Sadly, using tom_TLB.pas did not help: my variant was still Unassigned. I noticed in the documentation for ITextRange.Copy() has some strange requirements for its argument:
By tracing into Delphi's call I found that Delphi was clearing my Variant and setting it to Unassigned on the way in. Clearly it could never satisfy the requirement that pVar->vt = (VT_UNKNOWN | VT_BYREF). To work around this, I build my variant argument manually:
Id love to know of a simpler way.
- Obtain an ITextRange as described in a previous post.
- Call ITextRange.Copy(), passing it a pointer to a variant. (Otherwise it will copy the text to the clipboard.)
- The variant should now contain an IDataObject interface pointer.
- Call IDataObject.GetData() requesting CF_RTF.
I tried to follow this plan, passing an Unassigned Variant to ITextRange.Copy(), but found that it was still Unassigned afterwards. I decided to get hold of proper declarations for ITextRange so that I need not go via Variant IDispatch. I found tom_TLB.pas on a Japanese site and took a copy. The file had obviously been produced by some automatic means. It declared ITextRange.Copy() as:
procedure Copy(out pVar: OleVariant); safecall;
Sadly, using tom_TLB.pas did not help: my variant was still Unassigned. I noticed in the documentation for ITextRange.Copy() has some strange requirements for its argument:
pVar->vt = (VT_UNKNOWN | VT_BYREF)
pVar is not null
pVar->ppunkVal is not null
By tracing into Delphi's call I found that Delphi was clearing my Variant and setting it to Unassigned on the way in. Clearly it could never satisfy the requirement that pVar->vt = (VT_UNKNOWN | VT_BYREF). To work around this, I build my variant argument manually:
- Change the declaration of ITextRange.Copy to:
procedure Copy(pVar: PVariantArg); safecall; - Construct the argument manually:
var
data_var: IUnknown;
data_var_arg: TVariantArg;
begin
data_var := range.FormattedText; // Copy range to ensure no interference.
data_var_arg.vt := VT_UNKNOWN or VT_BYREF;
data_var_arg.wReserved1 := 0;
data_var_arg.wReserved2 := 0;
data_var_arg.wReserved2 := 0;
data_var_arg.punkVal := @data_var;
range.Copy(@data_var_arg); - Your IDataObject will now be in data_var:
OleCheck(IUnknown(data_var).QueryInterface(IDataObject, data));
Id love to know of a simpler way.