将 LibreOffice 实例嵌入到应用程序中(使用 TOLEContainer)

Embedding Instance of LibreOffice into Application (with TOLEContainer)

我正在尝试在我的应用程序中嵌入带有 Delphi 的 LibreOffice 实例。我的主要目标是在将 LibreOffice 文档嵌入到 MS Office 中时获得类似 MS Office 的结果。如果可能的话,我想用TOLEConatiner来实现。

为了测试,我编写了一个带有 TOleContainer 组件的程序:

procedure TForm1.btn1Click(Sender: TObject);
begin
  if OpenDialog.Execute then
  if FileExists(OpenDialog.FileName) then
    OleContainer.CreateObjectFromFile(OpenDialog.FileName, false)
end;

对于 MS Office(打开 .docx 文件),这已经可以正常工作了。打开 .odt 文件然后激活 OLEContainer 会导致一个空框架,或多或少不显示任何内容,因此不可查看或不可编辑。

所以我试图了解更多关于 LibreOffice、OLE 和 COM 的信息。我发现我可以使用 OO API 来访问它的功能,我首先需要创建一个 OO ServiceManager 的 OLEObject,然后创建一个桌面服务来创建一个文档,就像这样:

Server := CreateOleObject('com.sun.star.ServiceManager');
Desktop := Server.CreateInstance('com.sun.star.frame.Desktop')
LoadParams := VarArrayCreate([0, 0], varVariant);
Param := Server.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
Param.Name := 'Hidden';
Param.Value := True;
LoadParams[0] := Param;
Document := Desktop.LoadComponentFromURL('private:factory/swriter', '_default', 0, LoadParams);

我的问题是我不知道如何将它与 OLEContainer 结合起来以获得我预期的结果。我发现的示例(例如 this one)也无​​法真正帮助我,因为它们打开了一个单独的 LibreOffice 实例。我也了解了 LibreOffice 的一些服务以找到任何解决方案,但是我很难通过文档。

OLE、COM 和 LibreOffice API 对我来说是一个新话题,我感到很迷茫。所以我想出了以下问题:

甚至可以在嵌入 OleContainer 的 LibreOffice 实例中显示和编辑文档吗? 如果是,我该如何实现? 如果不是,是否有其他方法可以在我的应用程序中显示 LibreOffice 实例?

很久以前的事了,但是我找到了容器中空框的原因:

在使用 MSOffice 时,方法 DoVerb 在内部调用 TOleContainerIOleDocumentSite.ActivateMe,它设置了不同的属性,包括 FDocObj。对于 LibreOffice,接口 IOleDocumentSite 似乎不受支持(QueryInterface 引发错误),因此永远不会调用 ActivateMe。这导致未设置 FDocObj,因此在 TOleContainer.GetWindow 中接收到错误的句柄(而不是 OleContainer 自己的句柄,其父句柄被接收),并且文档未显示在容器中。

为了解决这个问题,我在调用DoVerb之前将FDocObj设置为True。这可能不是最终的解决方案,因为我仍然不完全理解 TOleContainer 究竟是如何工作的,但目前这个解决方案对我有用。