Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding multiple MS Word instances in TOleContainer

This is giving me a headache...

The delphi App I'm working on opens one or more forms with Word in a TOLEContainer. The problem I have is that when more than one form is opened with an embedded instance of Word, the controls of one instance affects all other instances whilst the controls on the first instance are unusable.

The controls for the first TOleContainer, for example, are still visible and appear to be enabled but are non-functional, selecting text in the first instance and using the controls in the second instance cause the changes to be reflected in first instance (clear as mud?!?) All very confusing so I've included a picture:

OleControls toolbar controlling both instances of word

The intention is to have each instance of word embedded in it's own form and utilising it's own controls. So what causes my undesired behaviour and what can I do about it? I'm sure it's something simple, like catching the "activate" property and setting (I dont know what to set) of the OleContainer, but I've had no luck with this.

I figure one alternative might be to create my own instances of TWordApplication and either re-parent via Windows.SetParent() (this does work, btw, each instance does control itself but would require a lot of rework of the application) or embed in an OleContainer... can I embed TWordApplication instances their own OleContainers? If so how so? Alternatively changing the default open behaviour of CreateObjectFromFile (but I think this is controlled by the COM server which is Word)...

For reference.... Test the following by instantiating a couple of forms...

// This embed into an OleContainer, but opening two forms 
// leaves me with one that has working controls and another 
// that has non-working controls (this code on it's own form)
// If this code is on TForm2 and you create two instances of TForm2
// Word behaves incorrectly
OleContainer1.CreateObjectFromFile('C:\Test.docx', false);
OleContainer1.AutoActivate := aaGetFocus;
OleContainer1.DoVerb(ovOpen);

OleContainer1.Run;


//  To embed Word on a TPanel (this code on it's own form)
//  This code on TForm3, create two instance of TForm3 to see 
//  word work independently as desired
wordApp := TWordApplication.Create(Self);
wordApp.ConnectKind := TConnectKind.ckNewInstance;
wordApp.Caption := IntToStr(AppId);
wordApp.Visible := True;

WordHandle := FindWindow('OpusApp', PWideChar(wordApp.Caption));

Windows.SetParent(WordHandle, Panel1.Handle);

if AppId = 1 then
begin
  lFilename := 'C:\Test.docx';
end else begin
  lFilename := 'C:\Test2.docx';
end;
wordApp.Documents.Open(lFileName, EmptyParam, EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
like image 766
0909EM Avatar asked Jan 14 '13 23:01

0909EM


1 Answers

You could try working with IOleInPlaceActiveObject and activate and deactivate when your form activates and deactivates. See the accepted answer to my question: Context menu disappears with Word automation

like image 168
The_Fox Avatar answered Dec 06 '22 17:12

The_Fox