将 ole 对象插入 TRxRichEdit

发布于 2024-08-16 08:59:26 字数 55 浏览 9 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

傲影 2024-08-23 08:59:26

如果调用 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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文