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.
4 Comments:
Here you go:
function GetDataObjectForRange( Range : ITextRange; var ADataObject : IDataObject) : HRESULT;
var
AIn : IUnknown;
AInVar : OleVariant;
begin
with TVarData(AInVar) do begin
VType := VT_UNKNOWN or VT_BYREF;
VPointer := @AIn;
end;
Range.Copy(AInVar);
Result := AIn.QueryInterface(IDataObject, ADataObject);
end;
This theme is simply matchless :), it is interesting to me)))
It agree, a remarkable idea
Hi,
procedure Copy(out pVar: OleVariant); safecall; does not work
but
procedure Copy(var pVar: OleVariant); safecall; works.
So,
var
pp : Olevariant;
begin
...
data_var := textRange.FormattedText;
TVariantArg(pp).vt := VT_UNKNOWN or VT_BYREF;
TVariantArg(pp).punkVal := @data_var;
textRange.Copy(pp);
Its all right.
Post a Comment
<< Home