IAdviseSink setup for catching MSWord document events

本秂侑毒 提交于 2019-12-12 10:57:51

问题


Here is the code where I try to setup IAdviseSink interface implemented in my TForm1 class for catching some events of the newly created MSWord document. I have not any errors while the code runs, but I can't catch any event, while save the document or close it. How-to setup IAdviseSink for MSWord document correctly?


    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;


回答1:


Edit:

Never mind this answer. Leaving it in for eductional purposes.


Why the cast IAdviseSink(Self)?

If you declared the interface in the Form's class declaration:

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

, you shouldn't have to.

The fact that you use the cast (and a hard cast which just tells the compiler to shut up), may indicate that you didn't. And that may well cause the dispatch mechanism to find that your form does not implement IAdviseSink and therefore has nothing on which to call the OnSave method.


Explanation of why the above is not the issue:

I didn't understood Sertac's comment 'But then the code wouldn't compile' at first. He meant that without IAdviseSink being part of the form's class declaration, the line

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

would cause a [DCC Error] Unit1.pas(41): E2010 Incompatible types: 'IAdviseSink' and 'TForm1'

The IAdviseSink(Self) obviously isn't a simple hard cast like TForm(SomePointer) is, which basically tells the compiler to shut up and treat SomePointer as a TForm. An interface cast then, prompts the compiler to check whether the instance being cast actually supports the interface. Didn't know that. Learn something new every day.




回答2:


Not exactly an answer, but...

Is there a particular reason why you want to reinvent the wheel and do the whole Advise-thing yourself? Why not just use the TWordDocument wrapper class from the Word2000-unit that comes bundled with Delphi (all you'd have to do in that case would be to call ConnectTo() and assign your event handlers)? However, the Document object doesn't have an OnSave event (at least not in the 2000 version of the TLB, which is generally a good common denominator if you want your app to be compatible with multiple versions of Office). The Application object does have a BeforeDocumentSave-event, though...



来源:https://stackoverflow.com/questions/8625340/iadvisesink-setup-for-catching-msword-document-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!