Microsoft KB Archive/280512

= SAMPLE: ATLCPImplMT encapsulates ATL event firing across COM apartments =

Article ID: 280512

Article Last Modified on 8/10/2004

-

APPLIES TO


 * Microsoft ActiveX Template Library 3.0

-



This article was previously published under Q280512



SUMMARY
ATL-based ActiveX COM objects (including Automation objects and ActiveX controls) typically fire events from the same thread in which they were created.

Sometimes it is desirable to start secondary threads in the COM object that fire events to the container. ATLCPImplMT.h provides an enhanced implementation of the ATL IConnectionPointImpl class, IConnectionPointImplMT, that provides this capability.

Because IConnectionPointImplMT uses the Global Interface Table, it requires Windows NT 4.0 Service Pack 3 or later, or Windows 95 (or later) with DCOM version 1.1 or later.



MORE INFORMATION
The following file is available for download from the Microsoft Download Center:

Download the ATLCPImplMT.exe package now. Release Date: Apr-26-2001

For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:

119591 How to Obtain Microsoft Support Files from Online Services

Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file. The ATLCPImplMT.EXE (or ATLCPImplMT.hqx) file contains the following files:

Using ATLCPImplMT.h in Your ATL Project
Notes  The following steps must be performed on files containing implementations of proxy classes generated through the Implement Connection Point Wizard. These classes are named CProxy{EventInterfaceName} by convention, and your ATL COM class would derive from them. For additional information, see the following Microsoft Web page:

Adding Connection Points to an Object

http://msdn.microsoft.com/library/devprods/vs6/visualc/vcmfc/_atl_adding_connection_points_to_an_object.htm

 Because the Connection Point Wizard overwrites the generated proxy classes every time it is invoked, these steps must be repeated at that point.

 Copy the file ATLCPImplMT.h to your project folder.  Add the following #include statement near the top of the wizard-generated files:  Derive the proxy class, CProxy{EventInterfaceName}, from IConnectionPointImplMT, instead of IConnectionPointImpl. IConnectionPointImplMT has the same set of parameters. For example:   If you are using Visual Studio 6.0, use the following code: // Derive from IConnectionPointImplMT, instead of IConnectionPointImpl: // template <class T> // class CProxy_IEvntFirerEvents : public IConnectionPointImpl<T, &DIID__IEvntFirerEvents, CComDynamicUnkArray> template <class T> class CProxy_IEvntFirerEvents : public IConnectionPointImplMT<T, &DIID__IEvntFirerEvents, CComDynamicUnkArray> </li>  If you are using Visual Studio .NET, use the following code: // Derive from IConnectionPointImplMT, instead of IConnectionPointImpl: // template<class T> // class CProxy_IEvntFirerEvents : public IConnectionPointImpl<T, &__uuidof(_IEvntFirerEvents), CComDynamicUnkArray> template <class T> class CProxy_NicEvents : public IConnectionPointImplMT<T, &__uuidof(_IEvntFirerEvents), CComDynamicUnkArray> </li></ol> </li> For each generated function (named Fire_{EventName}) within the proxy class: Comment out the following lines within the generated for loop: <ol style="list-style-type: lower-alpha;">  If you are using Visual Studio 6.0, use the following code: // pT->Lock; // CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); // pT->Unlock; Insert the following lines in their place: CComPtr<IUnknown> sp; sp.Attach (GetInterfaceAt(nConnectionIndex)); </li>  If you are using Visual Studio .NET, use the following code: // pT->Lock; // CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); // pT->Unlock; Insert the following lines in their place: CComPtr<IUnknown> punkConnection; punkConnection.Attach (GetInterfaceAt(iConnection)); </li></ol> </li> The Fire_{EventName} functions can now be called from any other COM thread (in the same apartment, or a different apartment) that has access to the object in question.</li></ol>
 * 1) include &quot;ATLCPImplMT.h&quot;

Procedure to Use ATLCPImplMT.h in a sample project
<ol> Follow Steps 1 through 7 in the &quot;Steps to Create an ATL Project with Visual C++&quot; section in the following Microsoft Knowledge Base article:

196026 PRB: Firing event in second Thread causes IPF or GPF

</li>  Add the following code to the MyAtl.cpp file. In the code below, the event is being fired through the worker thread in the multi-threaded apartment (MTA), not through the thread in the main single-threaded apartment (STA): DWORD WINAPI justDoIt(LPVOID lpParameter) {        // Initialize COM, // MTA worker thread: HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);

CMyAtl *myAtl = (CMyAtl*)lpParameter;

long result; for (int i = 1; i <= myAtl->m_number; ++i) result = i * 2;

myAtl->Fire_TaskFinished(result);



return 0; }                   </li> Follow steps 9 and 10 in the &quot;Steps to Create an ATL Project with Visual C++&quot; section in article Q196026.</li> Follow the steps outlined in this article in the &quot;Using ATLCPImplMT.h Within Your ATL Project&quot; section to add support for IConnectionPointImplMT.</li> Build the ATL project, and the control will be registered automatically.</li> Follow the steps outlined under the &quot;Steps to Create the Visual Basic 6.0 Project&quot; heading in article Q196026. Notice that when you click the CommandButton, unlike in article Q196026, the event firing works correctly.</li></ol>

<div class="references_section">