将ole对象插入TRxRichEdit

时间:2010-01-01 20:34:09

标签: delphi richtext

我在我的程序中使用TRxRichEdit。如何在运行时将ole对象插入RxRichEdit。

1 个答案:

答案 0 :(得分:1)

如果调用RxRichEdit的“InsertObjectDialog”方法,控件将执行“插入对象”对话框,用户可以在该对话框中选择要重新创建的对象类型或从现有文件中选择。

我不认为在不使用对话框的情况下插入对象是不可能的,因为IRichEditOle接口(FRichEditOle)是该类的私有。

修改

无论接口是否为私有接口,显然,可以使用IRichEditOle直接从RichEdit控件本身请求EM_GETOLEINTERFACE接口。下面是D3示例代码(我使用RX控件的最后一个版本),但它也可能适合JVCL的'TJvRichEdit',它最初是相同的控件。代码在运行时从文件名中插入Ole对象:

uses
  activex, richedit, comobj;

type
  _ReObject = record
    cbStruct: DWORD;
    cp: ULONG;
    clsid: TCLSID;
    poleobj: IOleObject;
    pstg: IStorage;
    polesite: IOleClientSite;
    sizel: TSize;
    dvAspect: Longint;
    dwFlags: DWORD;
    dwUser: DWORD;
  end;
  TReObject = _ReObject;

  IRichEditOle = interface(IUnknown)
    ['{00020d00-0000-0000-c000-000000000046}']
    function GetClientSite(out clientSite: IOleClientSite): HResult; stdcall;
    function GetObjectCount: HResult; stdcall;
    function GetLinkCount: HResult; stdcall;
    function GetObject(iob: Longint; out reobject: TReObject;
        dwFlags: DWORD): HResult; stdcall;
    function InsertObject(var reobject: TReObject): HResult; stdcall;
    function ConvertObject(iob: Longint; rclsidNew: TIID;
        lpstrUserTypeNew: LPCSTR): HResult; stdcall;
    function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;
    function SetHostNames(lpstrContainerApp: LPCSTR;
        lpstrContainerObj: LPCSTR): HResult; stdcall;
    function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;
    function SetDvaspect(iob: Longint; dvaspect: DWORD): HResult; stdcall;
    function HandsOffStorage(iob: Longint): HResult; stdcall;
    function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;
    function InPlaceDeactivate: HResult; stdcall;
    function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
    function GetClipboardData(var chrg: TCharRange; reco: DWORD;
        out dataobj: IDataObject): HResult; stdcall;
    function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;
        hMetaPict: HGLOBAL): HResult; stdcall;
  end;

const
  REO_CP_SELECTION    = ULONG(-1);
  REO_RESIZABLE       = $00000001;
  IID_IOleObject: TGUID = (
      D1:$00000112;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));

procedure InsertOleObjectFromFile(RichEdit: TRxRichEdit; FileName: string);
var
  RichEditOle: IRichEditOle;
  LockBytes: ILockBytes;
  Storage: IStorage;
  FormatEtc: TFormatEtc;
  ClientSite: IOleClientSite;
  OleObject: IOleObject;
  ClassID: TCLSID;
  ReObject: TReObject;
begin
  SendMessage(RichEdit.Handle, EM_GETOLEINTERFACE, 0, Longint(@RichEditOle));
  if not Assigned(RichEditOle) then
    raise EOleError.Create('Failed to retrieve IRichEditOle');
  OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes));
  OleCheck(StgCreateDocfileOnILockBytes(LockBytes,
      STGM_SHARE_EXCLUSIVE or STGM_CREATE or STGM_READWRITE, 0, Storage));
  LockBytes := nil;

  OleCheck(RichEditOle.GetClientSite(ClientSite));
  FillChar(FormatEtc, SizeOf(FormatEtc), 0);
  FormatEtc.dwAspect := DVASPECT_CONTENT;
  FormatEtc.lIndex := -1;
  OleCheck(OleCreateFromFile(GUID_NULL, PWideChar(WideString(FileName)),
      IID_IOleObject, OLERENDER_DRAW, @FormatEtc, ClientSite, Storage,
      OleObject));
  OleCheck(OleSetContainedObject(OleObject, True));

  OleCheck(OleObject.GetUserClassID(ClassID));
  FillChar(ReObject, SizeOf(TReObject), 0);
  ReObject.cbStruct := SizeOf(TReObject);
  ReObject.cp := REO_CP_SELECTION;
  ReObject.clsid := ClassID;
  ReObject.poleobj := OleObject;
  ReObject.pstg := Storage;
  ReObject.polesite := ClientSite;
  ReObject.dvAspect := DVASPECT_CONTENT;
  ReObject.dwFlags := REO_RESIZABLE;
  OleCheck(RichEditOle.InsertObject(ReObject));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  InsertOleObjectFromFile(RxRichEdit1,
      ExtractFilePath(Application.ExeName) + 'xltest.xls');
end;