问题
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