📄 0,1410,26734,00.html
字号:
<HTML>
<HEAD>
<TITLE>How to sink events from a COM server.</TITLE>
</HEAD>
<BODY>
<A NAME="top"></A>
<table>
<TR>
<td>
<P>
<SPAN CLASS="title3">How to sink events from a COM server.</SPAN>
- by Borland Developer Support Staff
<BLOCKQUOTE CLASS="abstract"><B>Abstract:</B>This article describes how to respond to and handle events that are surfaced from a COM Automation server.</BLOCKQUOTE>
<table width="100%" border=0 cellpadding=5 cellspacing=0>
<tr><td align = left>
<font face="Arial">Topic</font>
</td></tr>
<tr><td>
<p>
<big>H</big>ow to sink events from a COM server.
</p>
</td></tr>
<tr><td align = left>
<font face="Arial">Explanation</font>
</td></tr>
<tr><td>
<p>
<big>S</big>inking events from a COM server can be horrible and tedious when done completely from scratch. This
is why the VCL provides the <code>TEventDispatcher</code> template class. This class allows you to easily respond
to events surfaced from a server.
</p>
<p>
Consider the following:<br>
Your server does some data access (e.g. gets something from a web site). You need to notify the client that
this has happened. In order to accomplish this, you've checked the "Generate event support code" box when creating
your server. This is all well and good, you say to yourself, but now how do I respond to those events from my client??
</p>
<p>
The answer: <code>TEventDispatcher!</code> This handy little template class allows you to easily sink events from
any server that will provide them. The rest of this article will be contained within commented sample-code. We will
need to concern ourselves with our server's *Impl.cpp file (firing the events), and the client-side unit.cpp and unit.h
files.
</p>
<table border=1 cellpadding=3 width="90%" align=center cellspacing=0>
<tr><td bgcolor=blue><font color=white>*Impl.cpp</font></td></tr>
<tr><td>
<pre><code>
STDMETHODIMP TTestEventsImpl::Trigger()
{
<font color="#0000AA"><i>//fire off our event</i></font>
Fire_Event1(WideString(<font color="#0000FF">"Mesage message message message!"</font>));
<b>return</b> S_OK;
}
</code></pre>
</td></tr>
</table>
<br><br>
<table border=1 cellpadding=3 width="90%" align=center cellspacing=0>
<tr><td bgcolor=blue><font color=white>unit.h</font></td></tr>
<tr><td>
<pre><code>
<font color="#0000AA"><i>//---------------------------------------------------------------------------</i></font>
<font color="202020">#ifndef Unit1H</font>
<font color="202020">#define Unit1H</font>
<font color="#0000AA"><i>//---------------------------------------------------------------------------</i></font>
<b>class</b> TForm1; <font color="#0000AA"><i>//forward ref to TForm1</i></font>
<font color="#0000AA"><i>//here we derive from TEventDispatcher specialized on our class</i></font>
<font color="#0000AA"><i>//and the dispatch ID of the event interface</i></font>
<b>class</b> EventHandler:
<b>public</b> TEventDispatcher<EventHandler,&DIID_ITestEventsEvents>
{
<b>private</b>:
<b>bool</b> connected;
TForm1 *theform;
ITestEventsPtr server;
<b>protected</b>:
<font color="#0000AA"><i>//overloaded from TEventDispatcher.</i></font>
HRESULT InvokeEvent(DISPID id, TVariant *params);
<b>public</b>:
EventHandler();
~EventHandler();
<b>void</b> Connect(TForm1 *form, ITestEventsPtr srv);
<b>void</b> Disconnect();
<b>void</b> <b>__fastcall</b> HandleEvent1(BSTR Message);
};
<font color="202020">#endif</font>
</code></pre>
</td></tr>
</table>
<br><br>
<table border=1 cellpadding=3 width="90%" align=center cellspacing=0>
<tr><td bgcolor=blue><font color=white>unit.cpp</font></td></tr>
<tr><td>
<pre><code>
<font color="#0000AA"><i>//---------------------------------------------------------------------------</i></font>
<font color="202020">#include <vcl.h></font>
<font color="202020">#pragma hdrstop</font>
<font color="202020">#include "Unit1.h"</font>
<font color="#0000AA"><i>//---------------------------------------------------------------------------</i></font>
<font color="202020">#pragma package(smart_init)</font>
EventHandler::EventHandler()
{
connected = <b>false</b>; <font color="#0000AA"><i>//not connected;</i></font>
theform = <b>false</b>; <font color="#0000AA"><i>//backptr to form is null</i></font>
}
EventHandler::~EventHandler()
{
<b>if</b> (connected)
Disconnect();
}
<font color="#0000AA"><i>/*
Here we do a switch on the DISPID (can be gotten from the type library).
params is an array of TVariant's. These we delegate to our event handlers.
*/</i></font>
HRESULT EventHandler::InvokeEvent(DISPID id, TVariant *params)
{
<b>switch</b>(id)
{
<b>case</b> 1:
HandleEvent1(WideString(*params));
<b>break</b>;
<b>default</b>:
ShowMessage(<font color="#0000FF">"we shouldn't be here!"</font>);
}
}
<font color="#0000AA"><i>/*
This function attaches our event handler to a running instance of the server.
This is the method that actually sinks our events.
*/</i></font>
<b>void</b> EventHandler::Connect(TForm1 *form, ITestEventsPtr srv)
{
server = srv;
theform = form; <font color="#0000AA"><i>//back pointer to form to do stuff with it.</i></font>
server->AddRef(); <font color="#0000AA"><i>//addref the server</i></font>
ConnectEvents(server); <font color="#0000AA"><i>//helper function to connect us
//to the events interface</i></font>
}
<b>void</b> EventHandler::Disconnect()
{
DisconnectEvents(server); <font color="#0000AA"><i>//disconnect the events</i></font>
server->Release(); <font color="#0000AA"><i>//release our referece</i></font>
}
<font color="#0000AA"><i>/* here we actually handle the event in any way we want */</i></font>
<b>void</b> <b>__fastcall</b> EventHandler::HandleEvent1(BSTR Message)
{
theform->Label1->Caption = WideString(Message);
}
</code></pre>
</td></tr>
</table>
</td></tr>
</table>
</table>
</BODY>
</htm>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -