7

我想知道在 TForm 中嵌入和控制 MS Word 的建议方法是什么?目前,我(1)在 TForm 上放了两个 TPanel。TPanelalBottom有一个 TButton,alClientTPanel 有一个alNoneTOleContainer。(2) 在 TMainForm.FormCreate 事件处理程序中设置布局。

问题是 MS Word 喜欢占用其父窗体的所有空间。只有如下所示的第四种方式似乎可以提供可接受的布局。基于反复试验,似乎有必要使用子表单而不是 TPanel 来托管 TOleContainer。(另外,Windows.SetParent 似乎是必要的。)我想知道子表单是否是正确的方法?

PS:德尔福 XE,Word 2010,Windows 7

PS:与“托管外部应用程序”相关的网页:

Binh Ly 的网站

黛博拉的网站

如何外壳到另一个应用程序并让它以德尔福形式出现

重访 TOleContainer

在delphi中打开word文档?

Delphi & Word (SimpChn)

PS:与“Form in Panel(子表单)”相关的网页:

如何在 Panel 内制作透明表单?

Delphi - OleContainer - PowerPoint - 自动播放

FreePascal/Lazarus MultiDoc

面板中的 TForm

如何创建一个包含多个“子”表单的delphi表单,这些表单可以移动/调整大小并显示为激活状态

示例代码

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.
4

1 回答 1

2

子表单是一种正确的方法。我们在生产环境中使用了这种方法,并且效果很好。我们在一个面板中托管了我们的“子”表单。但是,我们修改了 TOleContainer 和 TOleForm 并带有一个标志是使用父窗体还是最顶层的窗体:

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

其中 FDrawInTopForm 是我们引入的一个属性。我们还修改了:

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

不幸的是,由于与客户的协议,我无法在此处发布完整的解决方案。

于 2012-07-05T08:44:33.183 回答