I
import
Unregistered / Unconfirmed
GUEST, unregistred user!
用TWordApplication的方式,有事件支持,但是,我用OLE的时候,如何也能支持事件呢?
请看下面的代码:
uses Word_TLB, activex, comobj, ConnectionObject
// ConnectionObject is the unit containing TWordConnection
// Follow link at the bottom of the page for TWordConnection sample code
procedure StartWordConnection(WordApp: _Application;
WordDoc: _Document;
var WordSink: TWordConnection);
var
PointContainer: IConnectionPointContainer;
Point: IConnectionPoint;
begin
try
// TWordConnection is the COM object which receives the
// notifications from Word. Make sure to free WordSink when
// you are done with it.
WordSink := TWordConnection.Create;
WordSink.WordApp := WordApp;
WordSink.WordDoc := WordDoc;
// Sink with a Word application
OleCheck(WordApp.QueryInterface(IConnectionPointContainer, PointContainer));
if Assigned(PointContainer) then begin
OleCheck(PointContainer.FindConnectionPoint(ApplicationEvents, Point));
if Assigned(Point) then
Point.Advise((WordSink as IUnknown), WordSink.AppCookie);
end;
// Sink with a Word document
OleCheck(WordDoc.QueryInterface(IConnectionPointContainer, PointContainer));
if Assigned(PointContainer) then begin
OleCheck(PointContainer.FindConnectionPoint(DocumentEvents, Point));
if Assigned(Point) then
Point.Advise((WordSink as IUnknown), WordSink.DocCookie);
end;
except
on E: Exception do ShowMessage(E.Message);
end;
end;
//////////////////////////////
unit ConnectionObject;
interface
uses Word_TLB;
type
TWordConnection = class(TObject, IUnknown, IDispatch)
protected
{IUnknown}
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
{ IDispatch }
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
public
WordApp: _Application;
WordDoc: _Document;
AppCookie, DocCookie: Integer;
end;
implementation
{ IUnknown Methods }
uses windows, activex, main;
procedure LogComment(comment: string);
begin
Form1.Memo1.Lines.Add(comment);
end;
function TWordConnection._AddRef: Integer;
begin
Result := 2;
end;
function TWordConnection._Release: Integer;
begin
Result := 1;
end;
function TWordConnection.QueryInterface(const IID: TGUID;
out Obj): HResult;
begin
Result := E_NOINTERFACE;
Pointer(Obj) := nil;
if (GetInterface (IID, Obj)) then Result := S_OK;
if not Succeeded (Result) then
if (IsEqualIID(IID, DocumentEvents) or IsEqualIID(IID, ApplicationEvents)) then
if (GetInterface(IDispatch, Obj)) then Result := S_OK;
end;
{ IDispatch Methods }
function TWordConnection.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
begin
Result := E_NOTIMPL;
end;
function TWordConnection.GetTypeInfo(Index, LocaleID: Integer;
out TypeInfo): HResult;
begin
Pointer(TypeInfo) := nil;
Result := E_NOTIMPL;
end;
function TWordConnection.GetTypeInfoCount(out Count: Integer): HResult;
begin
Count := 0;
Result := E_NOTIMPL;
end;
function TWordConnection.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;
begin
//This is the entry point for Word event sinking
Result := S_OK;
case DispID of
1: // Startup
2: // Quit
3: // Document change
4: // New document
5: // Open document
6: // Close document
else Result := E_INVALIDARG;
end;
end;
end.
使用方法,ConnectionObject是一个单独的单元,在其中的Invoke过程中的case DispID后面,你可以添加你的事件支持代码!如果需要全部的事件常量,请自己查看相关资料即可。
如果要OLE创建的东西支持事件,可以利用StartWordConnection函数来进行关联即可!
************************************
下面是Ex-Ex的解答,比较好的:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_10237322.html#1
Title: Word-close event with OLE and dp3.0
From: dr_gonzo
Date: 11/23/1999 04:16AM PST
Answer Grade: A Points: 60
Hi!
I have an app written in Delphi 3.0 that controles an instance of word via OLE. Word does not exactly behave the way one could expect in some cases.
I posted this to the Office group also, but since nowone of you reads those group I add it here too. I'm aware that this is a question that does not really commit to any area. This is the closest though.
I want my word document to tell me when the user has clicked the x-button(or control menu Close[Ctrl+F4].
If I make a template and writes an event handler for the Close-event it works so neat with a normal document, but my OLE-document never sends me any close-event it just kills the window...
How am I supposed to make word let my app know when it is closing rather than when it has closed. I want to be able to pop up some own dialogs before the actual close of the document...
by the way. It's the samething with the dirty-flag. It's always considered to be "False" if it's an OLE-document...
why the hell is that?
What can I do about it? How do I write my own Dirty-flag for a document?
请看下面的代码:
uses Word_TLB, activex, comobj, ConnectionObject
// ConnectionObject is the unit containing TWordConnection
// Follow link at the bottom of the page for TWordConnection sample code
procedure StartWordConnection(WordApp: _Application;
WordDoc: _Document;
var WordSink: TWordConnection);
var
PointContainer: IConnectionPointContainer;
Point: IConnectionPoint;
begin
try
// TWordConnection is the COM object which receives the
// notifications from Word. Make sure to free WordSink when
// you are done with it.
WordSink := TWordConnection.Create;
WordSink.WordApp := WordApp;
WordSink.WordDoc := WordDoc;
// Sink with a Word application
OleCheck(WordApp.QueryInterface(IConnectionPointContainer, PointContainer));
if Assigned(PointContainer) then begin
OleCheck(PointContainer.FindConnectionPoint(ApplicationEvents, Point));
if Assigned(Point) then
Point.Advise((WordSink as IUnknown), WordSink.AppCookie);
end;
// Sink with a Word document
OleCheck(WordDoc.QueryInterface(IConnectionPointContainer, PointContainer));
if Assigned(PointContainer) then begin
OleCheck(PointContainer.FindConnectionPoint(DocumentEvents, Point));
if Assigned(Point) then
Point.Advise((WordSink as IUnknown), WordSink.DocCookie);
end;
except
on E: Exception do ShowMessage(E.Message);
end;
end;
//////////////////////////////
unit ConnectionObject;
interface
uses Word_TLB;
type
TWordConnection = class(TObject, IUnknown, IDispatch)
protected
{IUnknown}
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
{ IDispatch }
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
public
WordApp: _Application;
WordDoc: _Document;
AppCookie, DocCookie: Integer;
end;
implementation
{ IUnknown Methods }
uses windows, activex, main;
procedure LogComment(comment: string);
begin
Form1.Memo1.Lines.Add(comment);
end;
function TWordConnection._AddRef: Integer;
begin
Result := 2;
end;
function TWordConnection._Release: Integer;
begin
Result := 1;
end;
function TWordConnection.QueryInterface(const IID: TGUID;
out Obj): HResult;
begin
Result := E_NOINTERFACE;
Pointer(Obj) := nil;
if (GetInterface (IID, Obj)) then Result := S_OK;
if not Succeeded (Result) then
if (IsEqualIID(IID, DocumentEvents) or IsEqualIID(IID, ApplicationEvents)) then
if (GetInterface(IDispatch, Obj)) then Result := S_OK;
end;
{ IDispatch Methods }
function TWordConnection.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
begin
Result := E_NOTIMPL;
end;
function TWordConnection.GetTypeInfo(Index, LocaleID: Integer;
out TypeInfo): HResult;
begin
Pointer(TypeInfo) := nil;
Result := E_NOTIMPL;
end;
function TWordConnection.GetTypeInfoCount(out Count: Integer): HResult;
begin
Count := 0;
Result := E_NOTIMPL;
end;
function TWordConnection.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;
begin
//This is the entry point for Word event sinking
Result := S_OK;
case DispID of
1: // Startup
2: // Quit
3: // Document change
4: // New document
5: // Open document
6: // Close document
else Result := E_INVALIDARG;
end;
end;
end.
使用方法,ConnectionObject是一个单独的单元,在其中的Invoke过程中的case DispID后面,你可以添加你的事件支持代码!如果需要全部的事件常量,请自己查看相关资料即可。
如果要OLE创建的东西支持事件,可以利用StartWordConnection函数来进行关联即可!
************************************
下面是Ex-Ex的解答,比较好的:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_10237322.html#1
Title: Word-close event with OLE and dp3.0
From: dr_gonzo
Date: 11/23/1999 04:16AM PST
Answer Grade: A Points: 60
Hi!
I have an app written in Delphi 3.0 that controles an instance of word via OLE. Word does not exactly behave the way one could expect in some cases.
I posted this to the Office group also, but since nowone of you reads those group I add it here too. I'm aware that this is a question that does not really commit to any area. This is the closest though.
I want my word document to tell me when the user has clicked the x-button(or control menu Close[Ctrl+F4].
If I make a template and writes an event handler for the Close-event it works so neat with a normal document, but my OLE-document never sends me any close-event it just kills the window...
How am I supposed to make word let my app know when it is closing rather than when it has closed. I want to be able to pop up some own dialogs before the actual close of the document...
by the way. It's the samething with the dirty-flag. It's always considered to be "False" if it's an OLE-document...
why the hell is that?
What can I do about it? How do I write my own Dirty-flag for a document?