How to use Word in TOleContainer in TForm properly, layout-wise?

11,936

Subform is a correct way to do it. We used this approach in a production environment and it worked. We hosted our "sub" form in a panel. However, we modified TOleContainer and TOleForm with a flag whether to use the parent form, or the topmost form:

procedure TOurOleContainer.InitObject;
...
begin
  if FDrawInTopForm then
    DocForm := GetParentForm(Self)
  else
    DocForm := TCustomForm(Parent);
...

Where FDrawInTopForm is a property we introduced. We also modified:

function GetVCLFrameForm(Form: TCustomForm; DrawInTopForm: Boolean): IVCLFrameForm;
begin
  if Form.OleFormObject = nil then TOleForm.Create(Form, DrawInTopForm); 
  Result := Form.OleFormObject as IVCLFrameForm;
end;

Unfortunately, due to agreements with the customer, I cannot post the complete solution here.

Share:
11,936
SOUser
Author by

SOUser

Updated on June 28, 2022

Comments

  • SOUser
    SOUser almost 2 years

    I wonder what is the suggested way to embed and control MS Word in a TForm, layout-wise? Currently, I (1) put two TPanel on TForm. The alBottom TPanel has one TButton, and the alClient TPanel has a alNone TOleContainer. (2) set up the layout in TMainForm.FormCreate event handler.

    The problem is MS Word likes to take up all the space of its parent form. Only the fourth way as shown below seems to give acceptable layout. Based on trial-and-error, it seems necessary to use a sub-form instead of TPanel to host TOleContainer. (Also, Windows.SetParent seems necessary.) I wonder whether a sub-form is the correct way to go?

    PS: Delphi XE, Word 2010, Windows 7

    PS: web pages related to "hosting external applications":

    Binh Ly's site

    Deborah's site

    How to shell to another app and have it appear in a delphi form

    TOleContainer Revisited

    Open word document in delphi?

    Delphi & Word (SimpChn)

    PS: web pages related to "Form in Panel (sub-form)":

    how to make a transparent form inside Panel?

    Delphi - OleContainer - PowerPoint - AutoPlay

    FreePascal/Lazarus MultiDoc

    TForm in a panel

    How to create a delphi form containing multiple 'child' forms that can be moved/sized and show activated

    sample code

    unit uMainForm;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, OleCtnrs, ExtCtrls, StdCtrls;
    
    type
      TMainForm = class(TForm)
        PanelOle: TPanel;
        PanelBtn: TPanel;
        OleContainer1: TOleContainer;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      MainForm: TMainForm;
    
    implementation
    
    {$R *.dfm}
    
    procedure TMainForm.FormCreate(Sender: TObject);
    var
      OleForm: TForm;
    begin
    ////
    //// 1
    ////
    //  OleContainer1.Parent := PanelOle;
    //  OleContainer1.Align := alClient;
    //
    ////
    //// 2
    ////
    //  Windows.SetParent(OleContainer1.Handle, PanelOle.Handle);
    //  OleContainer1.Align := alClient;
    //
    ////
    //// 3
    ////
    //  OleForm := TForm.Create(Self);
    //  OleForm.Parent := PanelOle;
    //  OleForm.Align := alClient;
    //  OleForm.Visible := True;
    //  OleContainer1.Parent := OleForm;
    //  OleContainer1.Align := alClient;
    //
    ////
    //// 4 Works!
    ////
    //  OleForm := TForm.Create(Self);
    //  Windows.SetParent(OleForm.Handle, PanelOle.Handle);
    //  OleForm.Align := alClient;
    //  OleForm.Visible := True;
    //  OleContainer1.Parent := OleForm;
    //  OleContainer1.Align := alClient;
    //
    ////
    //// 5
    ////
    //  OleForm := TForm.Create(Self);
    //  OleForm.Parent := PanelOle;
    //  OleForm.Align := alClient;
    //  OleForm.Visible := True;
    //  Windows.SetParent(OleContainer1.Handle,OleForm.Handle);
    //  OleContainer1.Align := alClient;
    //
    ////
    //// 6
    ////
    //  OleForm := TForm.Create(Self);
    //  Windows.SetParent(OleForm.Handle, PanelOle.Handle);
    //  OleForm.Align := alClient;
    //  OleForm.Visible := True;
    //  Windows.SetParent(OleContainer1.Handle,OleForm.Handle);
    //  OleContainer1.Align := alClient;
    
    end;
    
    procedure TMainForm.Button1Click(Sender: TObject);
    var
    // Declare the item to be a generic OleVariant to force late binding
      Ds: OleVariant;
      D: OleVariant;
    begin
      OleContainer1.CreateObjectFromFile('sample.docx', False);
    
      OleContainer1.Run;
    
      OleContainer1.AutoActivate := aaManual;
      OleContainer1.DoVerb(ovShow);  // not in FormCreate, in or after FormShow
    
      Ds := OleContainer1.OleObject.Application.Documents;
      Caption := IntToStr(Ds.Count);
    end;
    
    end.