Настройка IAdviseSink для перехвата событий документов MSWord - PullRequest
5 голосов
/ 24 декабря 2011

Вот код, в котором я пытаюсь настроить интерфейс IAdviseSink, реализованный в моем классе TForm1, для перехвата некоторых событий недавно созданного документа MSWord. У меня нет никаких ошибок во время выполнения кода, но я не могу перехватить какое-либо событие при сохранении или закрытии документа. Как правильно настроить IAdviseSink для документа MSWord?


    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 голосов
/ 08 мая 2012

Не совсем ответ, но ...

Есть ли какая-то особая причина, по которой вы хотите заново изобрести колесо и сделать целое Advise - все самостоятельно?Почему бы просто не использовать класс-оболочку TWordDocument из Word2000 -объекта, поставляемого в комплекте с Delphi (все, что вам нужно будет сделать в этом случае, это вызвать ConnectTo() и назначить обработчики событий)?Однако у объекта Document нет события OnSave (по крайней мере, в версии TLB 2000 года, которая обычно является хорошим общим знаменателем, если вы хотите, чтобы ваше приложение было совместимо с несколькими версиями Office).У объекта Application есть BeforeDocumentSave событие, хотя ...

0 голосов
/ 24 декабря 2011

Изменить:

Не обращайте внимания на этот ответ. Оставив его в образовательных целях.


Почему актерский состав IAdviseSink(Self)?

Если вы объявили интерфейс в объявлении класса формы:

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

, ты не должен был.

Тот факт, что вы используете приведение (и жесткое приведение, которое просто говорит компилятору замолчать), может указывать на то, что вы этого не сделали. И это может привести к тому, что механизм диспетчеризации обнаружит, что ваша форма не реализует IAdviseSink и, следовательно, не имеет ничего для вызова метода OnSave.


Объяснение, почему вышеупомянутое не является проблемой:

Я не понял комментария Сертака «Но тогда код не скомпилируется». Он имел в виду, что IAdviseSink не является частью объявления класса формы, строка

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

может вызвать [Ошибка DCC] Unit1.pas (41): E2010 Несовместимые типы: 'IAdviseSink' и 'TForm1'

* * * * * * * * * * * * * * * * IAdviseSink(Self), очевидно, не является простым жестким приведением типа TForm(SomePointer), который в основном говорит компилятору замолчать и рассматривать SomePointer как TForm. Затем приведение интерфейса побуждает компилятор проверить, поддерживает ли приведенный экземпляр интерфейс. Не знал этого. Узнайте что-то новое каждый день.

...