Inserting ole object to TRxRichEdit

坚强是说给别人听的谎言 提交于 2019-12-11 05:38:44

问题


I'm using TRxRichEdit in my program. How can I insert ole object to RxRichEdit at run time.


回答1:


If you call "InsertObjectDialog" method of the RxRichEdit, the control executes the Insert Object dialog where the user can choose the type of the object to create anew or from an existing file.

I don't think it would be possible to insert an object without using the dialog, because the IRichEditOle interface (FRichEditOle) is private to the class.

edit:

Regardless the interface being private or not to the class, apparently, one can request the IRichEditOle interface directly from the RichEdit control itself by using EM_GETOLEINTERFACE. Below is D3 sample code (the last version I used RX controls with), but it would also probably suit the 'TJvRichEdit' of JVCL, which is originally the same control. The code inserts an Ole object from a file name at run-time:

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;


来源:https://stackoverflow.com/questions/1989555/inserting-ole-object-to-trxrichedit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!