5

これは、新しく作成された MSWord ドキュメントのいくつかのイベントをキャッチするためIAdviseSinkに、クラスに実装されたインターフェイスをセットアップしようとするコードです。TForm1コードの実行中にエラーは発生しませんが、ドキュメントを保存または閉じるときにイベントをキャッチできません。IAdviseSinkMSWord ドキュメントを正しくセットアップする方法


    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;

4

2 に答える 2

0

正確な答えではありませんが...

車輪の再発明を行い、すべてを自分でやりたいという特定の理由はありAdviseますか? Delphi にバンドルされている -unitのTWordDocumentラッパー クラスを使用しないのはなぜですか(その場合、イベント ハンドラを呼び出して割り当てるだけで済みます)。ただし、オブジェクトにはイベントがありません (少なくとも 2000 バージョンの TLB にはありません。これは、アプリが複数のバージョンの Office と互換性を持つようにする場合に一般的に適切な共通点です)。ただし、オブジェクトには-event があります...Word2000ConnectTo()DocumentOnSaveApplicationBeforeDocumentSave

于 2012-05-08T14:51:36.457 に答える
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 として扱うように指示します。インターフェイス キャストは、キャストされているインスタンスが実際にインターフェイスをサポートしているかどうかを確認するようにコンパイラに指示します。それは知りませんでした。毎日何か新しいことを学びましょう。

于 2011-12-24T17:03:57.393 に答える