用于捕获MSWord文档事件的IAdviseSink设置

时间:2011-12-24 15:25:39

标签: delphi events ms-word ole-automation

以下是我尝试设置IAdviseSink类中实现的TForm1接口的代码,用于捕获新创建的MSWord文档的某些事件。代码运行时我没有任何错误,但我无法捕获任何事件,同时保存文档或关闭它。 如何正确设置MSWord文档的IAdviseSink


    var
      Form1 : TForm1;
      doc_ole_obj : IOleObject;
      word : IDispatch;
      Connection: LongInt;

    implementation

     //------------ Setup IAdviseSink
    procedure TForm1.Setup;
    begin
     word := CreateOleObject('Word.Application');
     OleVariant(word).Visible := True;

     IUnknown(OleVariant(word).Documents.Open('file.doc')).QueryInterface(IOleObject,doc_ole_obj);
     doc_ole_obj.Advise(IAdviseSink(Self), Connection);
    end;

     //------------- catch Sink events
    procedure TForm1.OnSave;
    begin
      Caption := 'saved at ' + TimeToStr(Now);
    end;

2 个答案:

答案 0 :(得分:0)

修改

别介意这个答案。将它留在教育目的。


为何选择演员IAdviseSink(Self)

如果在Form的类声明中声明了接口:

TForm1 = class(TForm, IAdviseSink)
   ...
end;

,你不应该这样做。

您使用强制转换(以及只是告诉编译器关闭的强制转换)这一事实可能表明您没有。这可能会导致调度机制发现您的表单没有实现IAdviseSink,因此没有任何内容可以调用OnSave方法。


解释为什么以上不是问题:

我没有理解Sertac的评论'但那时代码不会编译'。他的意思是,如果没有IAdviseSink成为表单类声明的一部分,那么

doc_ole_obj.Advise(IAdviseSink(Self), Connection);

会导致[DCC错误] Unit1.pas(41):E2010不兼容的类型:'IAdviseSink'和'TForm1'

IAdviseSink(Self)显然不是像TForm(SomePointer)这样的简单硬转换,它基本上告诉编译器关闭并将SomePointer视为TForm。然后,接口强制转换,提示编译器检查正在强制转换的实例是否实际支持该接口。不知道那个。每天学习新东西。

答案 1 :(得分:0)

不完全是答案,但是......

你有没有特别的理由想要重新发明轮子并自己完成整个Advise的事情?为什么不使用TWordDocument中的Word2000包装类 - 与Delphi捆绑在一起的单元(在这种情况下你只需要调用ConnectTo()并分配你的事件处理程序)?但是,Document对象没有OnSave事件(至少在2000版本的TLB中没有,如果您希望您的应用与多个版本兼容,这通常是一个很好的共同点)办公室)。 Application对象确实有BeforeDocumentSave - 事件,但是......