Re: Hooking automation object Events
- From: "Paul E. Schoen" <pstech@xxxxxxxxx>
- Date: Thu, 11 Jan 2007 00:55:44 -0500
"Rob Kennedy" <me3@xxxxxxxxxxx> wrote in message
news:50lfndF1gq0pfU1@xxxxxxxxxxxxxxxxxxxxx
Paul E. Schoen wrote:[snip VB example]
I have had a lot of success with my automation client program to do
periodic autosaves, but now I have added a feature that requires
interception and handling of Events, namely the Document.SelectionChange
Event. The Help shows that the prototype is: Document_SelectionChange().
The C++ version implements a "Sink". I could supply the code but it
probably doesn't translate well to Delphi.
C++ code frequently translates _very_ well into Delphi. You can be sure
that the VB code implements a sink, too. You just don't get to see it.
I tried using various ways to hook my event handler to the
SelectionChange event. I always got runtime errors that the method is
not supported by the object.
var
App1: Variant;
Doc1: Variant;
Can't you get any more specific type than Variant? You imported the type
library, right? When you did that, Delphi should have declared a bunch of
interfaces for you. Use those interfaces. Variant and OleVariant are for
when you have absolutely no idea what you're really working with. Using
more specific type names lets you (and the compiler) know what you're
trying to do.
Procedure TForm1.OnSelectionChange;
begin
Application.MessageBox('Selection Changed', 'PADS OLE', MB_OKCANCEL);
end;
App1 := GetActiveOleObject(Type1);
Doc1 := App1.ActiveDocument;
Doc1.Document_SelectionChange := OnSelectionChange;
Doc1.SelectionChange := OnSelectionChange;
I assume that's where you got the "method is not supported by the object"
message.
I tried using the (Delphi4) Automation Object Wizard, but I was unsure
of the Class Name, Instancing, and Threading Model.
I think that wizard is for when you have a class and you want to turn it
into a COM object. That's the opposite direction from what you're trying
to do.
I thought so. It didn't look right.
The PowerPCB_TLB has the following:
const
LIBID_PowerPCB: TGUID = '{0821EF00-B880-11CF-8268-0020AF937987}';
DIID__PowerPCBAppEvents: TGUID =
'{0821EF22-B880-11CF-8268-0020AF937987}';
DIID__PowerPCBDocEvents: TGUID =
'{0821EF24-B880-11CF-8268-0020AF937987}';
IID_IPowerPCBDoc: TGUID = '{0821EF04-B880-11CF-8268-0020AF937987}';
IID_IPowerPCBApp: TGUID = '{0821EF02-B880-11CF-8268-0020AF937987}';
Elsewhere in the file you should declarations for IPowerPCBDoc and
IPowerPCBApp interfaces. Does one of them have a property named
SelectionChange?
--
Rob
The next few lines of my post show the procedure SelectionChange:
type
_PowerPCBDocEvents = dispinterface;
_PowerPCBDocEvents = dispinterface
['{0821EF24-B880-11CF-8268-0020AF937987}']
procedure Save; dispid 11700;
procedure SelectionChange; dispid 11701;
I did not have good luck previously with using more specific type names.
private
App: IPowerPCBApp;
App := GetActiveOleObject('PowerPCB.Application');
Error: Incompatible Types. IPowerPCBApp and IDispatch
Then I tried:
private
App: IDispatch;
The APP assignment was OK, but
Doc := App.ActiveDocument;
Gave an error: Undeclared Identifier ActiveDocument
Following is the C++ Sink module:
============================================================================
// PowerPCBSink
// IMPLEMENT_DYNCREATE(PowerPCBSink, CCmdTarget)
PowerPCBSink::PowerPCBSink()
{
EnableAutomation();
}
PowerPCBSink::~PowerPCBSink()
{
}
void PowerPCBSink::OnFinalRelease()
{
// When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// deletes the object. Add additional cleanup required for your
// object before calling the base class.
CCmdTarget::OnFinalRelease();
}
BEGIN_MESSAGE_MAP(PowerPCBSink, CCmdTarget)
//{{AFX_MSG_MAP(PowerPCBSink)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(PowerPCBSink, CCmdTarget)
//{{AFX_DISPATCH_MAP(PowerPCBSink)
DISP_FUNCTION_ID(PowerPCBSink, "OnOpenDocument",
IPOWERPCBAPP_OPENDOCUMENTEVENT, OnOpenDocument, VT_EMPTY, VTS_DISPATCH)
DISP_FUNCTION_ID(PowerPCBSink, "OnSelectionChange",
IPOWERPCBDOC_SELECTIONCHANGEEVENT, OnSelectionChange, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(PowerPCBSink, "OnQuit", IPOWERPCBAPP_QUITEVENT, OnQuit,
VT_EMPTY, VTS_NONE)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
// Note: we add support for IID_IPowerPCBSink to support typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .ODL file.
// {667FDFC1-D446-11D0-BCBF-444553540000}
static const IID IID_IPowerPCBSink =
{ 0x667fdfc1, 0xd446, 0x11d0, { 0xbc, 0xbf, 0x44, 0x45, 0x53, 0x54, 0x0,
0x0 } };
BEGIN_INTERFACE_MAP(PowerPCBSink, CCmdTarget)
INTERFACE_PART(PowerPCBSink, DIID__PowerPCBAppEvents, Dispatch)
INTERFACE_PART(PowerPCBSink, DIID__PowerPCBDocEvents, Dispatch)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// PowerPCBSink message handlers
void PowerPCBSink::OnOpenDocument(LPDISPATCH pDoc)
{
((CClientDlg *)AfxGetMainWnd())->SetDlgItemText(IDC_TXT_STATUS, "Received
OnOpenDocument from server.");
((CClientDlg *)AfxGetMainWnd())->Refresh();
}
void PowerPCBSink::OnSelectionChange()
{
((CClientDlg *)AfxGetMainWnd())->SetDlgItemText(IDC_TXT_STATUS, "Received
OnSelectionChange from server.");
((CClientDlg *)AfxGetMainWnd())->Refresh();
}
void PowerPCBSink::OnQuit()
{
((CClientDlg *)AfxGetMainWnd())->SetDlgItemText(IDC_TXT_STATUS, "Received
OnQuit from server.");
((CClientDlg *)AfxGetMainWnd())->Disconnect();
((CClientDlg *)AfxGetMainWnd())->Refresh();
}
==========================================================================
If you can tell me how to convert that to Delphi I would be most grateful.
I would probably spend hours trying all sorts of wrong things. I am still
having a hard time wrapping my brain around OOP.
Thanks,
Paul
.
- Follow-Ups:
- Re: Hooking automation object Events
- From: Maarten Wiltink
- Re: Hooking automation object Events
- References:
- Hooking automation object Events
- From: Paul E. Schoen
- Re: Hooking automation object Events
- From: Rob Kennedy
- Hooking automation object Events
- Prev by Date: Re: Hooking automation object Events
- Next by Date: Re: Hooking automation object Events
- Previous by thread: Re: Hooking automation object Events
- Next by thread: Re: Hooking automation object Events
- Index(es):
Relevant Pages
|