Search code examples
delphicomolelibreofficedelphi-xe4

Embedding Instance of LibreOffice into Application (with TOLEContainer)


I am trying to embed an instance of LibreOffice with Delphi in my Application. My main goal is it to achieve a result like in MS office when im embedding LibreOffice documents into it. If possible, i want to use TOLEConatiner to achieve this.

For testing i wrote a program with a TOleContainer Component:

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

For MS Office (opening a .docx-file), this already works without problems. Opening an .odt-file and then activating the OLEContainer results in an empty frame, showing more or less nothing, therefore not viewable or editable.

So i tried to find out more about LibreOffice, OLE and COM. I have found out that i can use OO API to access its functionality , I first need to create an OLEObject of the OO ServiceManager, then creating a desktop service to create a document, something like this:

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);

My problem is that i don't see how to combine this with OLEContainer to get my expected result. Examples I have found (for example this one) couldn't really help me either as they open a seperate instance of LibreOffice. I also informed myself about some services of LibreOffice to find any solution, but its quite hard for me to get through the documentation.

OLE, COM and LibreOffice API is a new topic for me and i feel quite lost there. So i come up with the following question:

Is it even possible to show and edit a document in a LibreOffice instance embedded in an OleContainer? If yes, how can i achieve that? If no, are there any alternatives to show a LibreOffice Instance in my application?


Solution

  • It is a while ago, but i have found the reason for the empty frame in the container:

    While working with MSOffice, the method DoVerb internally calls IOleDocumentSite.ActivateMe of TOleContainer which sets different attributes, including FDocObj. For LibreOffice, the interface IOleDocumentSite does not seem to be supported (QueryInterface raises an error), therefore ActivateMe is never called. This results in not setting FDocObj, therefore receiving a wrong handle in TOleContainer.GetWindow (instead of OleContainer's own handle its parent's handle is received), and the document is not shown in the Container.

    To solve the problem, I have set FDocObj to True before calling DoVerb. This might not be the final solution as i still dont understand completely how TOleContainer exactly works but for the moment this solution works for me.