Click here to Skip to main content
15,886,063 members
Articles / Desktop Programming / ATL

How to Use IMessageFilter: the complete edition

Rate me:
Please Sign up or sign in to vote.
4.00/5 (8 votes)
19 Feb 20066 min read 51.1K   536   23  
This article shows you exactly how to create a COM object that uses IMessageFilter - both in client and server sides.
// MessageFilterClientConsole.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <objbase.h>

#include "ClientMessageFilter.h"

#import "../MessageFilterServer/MessageFilterServer.tlb" no_auto_exclude /*warning C4192, IMessageFilter*/

const int c_nNumCalls = 10;
const int c_nNumThreads = 2;

#define WM_MY_QUIT (WM_USER+1)

/****************************************************/

//to let the CreateInstance of the ClientMF:
class CMyModule : public CAtlModuleT<CMyModule> {};
CMyModule _AtlModule;

/****************************************************/

struct SMainThreadData
{
	DWORD		m_dwMainThreadId;
	int			m_nThreadIndex;
	IStream*	p_pStream;
};

DWORD WINAPI ThreadFunc( LPVOID lpParam ) 
{ 
	HRESULT hr = CoInitialize(NULL);

	SMainThreadData* pMainThreadData = (SMainThreadData*)lpParam;
	/***********************/
	// To install the message filter:
	CComObject<CClientMessageFilter>* pFilter;
	CComObject<CClientMessageFilter>::CreateInstance(&pFilter);
	pFilter->AddRef();
	CComPtr<IMessageFilter> spOldFilter;
	CoRegisterMessageFilter(pFilter, &spOldFilter);
	/***********************/
	
	IStream*& pStream = pMainThreadData->p_pStream;

	//read marshaled object reference from global variable:
	MessageFilterServerLib::IServerPtr serverPtr;
	MessageFilterServerLib::IServer* pServerInfc = NULL;
	hr = CoGetInterfaceAndReleaseStream(
		pStream,
		__uuidof(MessageFilterServerLib::IServerPtr),
		(void**)&pServerInfc
		);
	pStream = NULL;
	if(FAILED(hr))
	{
		MessageBox( NULL, "CoGetInterfaceAndReleaseStream() failed", "ThreadFunc", MB_OK );
	}
	else
	{
		for(int i = 0; i < c_nNumCalls; ++i)
		{
			//if i call Foo(), in case of fail COM throws exception. so i use raw_Foo:
			hr = pServerInfc->raw_Foo();	
		}
	}

	if( ! PostThreadMessage( 
		pMainThreadData->m_dwMainThreadId,
		WM_MY_QUIT,
		0,
		0) )
	{
		MessageBox( NULL, "PostThreadMessage() failed", "ThreadFunc", MB_OK );
	}

	// To remove
	CComPtr<IMessageFilter> spDummy;
	CoRegisterMessageFilter(spOldFilter, &spDummy);
	pFilter->Release();

	CoUninitialize();
	return 0; 
} 

/*****************************************************************************/

int _tmain(int argc, _TCHAR* argv[])
{
	CoInitialize(NULL);

	HRESULT hr;
	//creating the server:
	MessageFilterServerLib::IServerPtr serverPtr;
	hr = serverPtr.CreateInstance(__uuidof(MessageFilterServerLib::Server));
	if(FAILED(hr))
	{
		return 0;
	}

	DWORD dwThreadId;
	char szMsg[80];

	static SMainThreadData MainThreadData[c_nNumThreads];

	for(int nThreadIndex = 0; nThreadIndex < c_nNumThreads; ++nThreadIndex)
	{
		//for each thread X, do the following:
		
		//marshal the interface pointer to the worker thread
		hr = CoMarshalInterThreadInterfaceInStream(
			__uuidof(MessageFilterServerLib::IServerPtr),
			serverPtr.GetInterfacePtr(),
			&MainThreadData[nThreadIndex].p_pStream);
		if(FAILED(hr))
		{
			MessageBox( NULL, "CoMarshalInterThreadInterfaceInStream() failed", "main()", MB_OK );
		}

		MainThreadData[nThreadIndex].m_dwMainThreadId = GetCurrentThreadId();;
		MainThreadData[nThreadIndex].m_nThreadIndex = nThreadIndex;
		//create the worker thread:
		HANDLE hWorkerThreadA = CreateThread( 
			NULL,							// default security attributes 
			0,								// use default stack size  
			ThreadFunc,						// thread function 
			(void*)&MainThreadData[nThreadIndex],		// argument to thread function 
			0,								// use default creation flags 
			&dwThreadId);					// returns the thread identifier 
	}


	int nThreadCounter(0);
	MSG msg;
	while (GetMessage(&msg, 0, 0, 0))
	{
		DispatchMessage(&msg);

		switch(msg.message)
		{
		case WM_MY_QUIT:
			{
				if(++nThreadCounter == c_nNumThreads)
				{
					char c;
					std::cin >> c;
					return 0;
				}
			}
			break;
		}
	}
	

	return 0;
}

/*****************************************************************************/

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Israel Israel
working for Intel

My Linkedin Profile

Visit my photography gallery

Comments and Discussions