Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

COM from scratch - PART TWO

, 17 Apr 2004
An article about COM Library.
demoapp.zip
ComDemo.exe
demoappsource.zip
ComDemo
ComDemo.clw
ComDemo.dsp
ComDemo.dsw
Comp1
Comp1.clw
Comp1.def
Comp1.dsp
Comp1.dsw
Debug
icon1.ico
Release
res
Comp2
Comp2.clw
Comp2.def
Comp2.dsp
Comp2.dsw
Debug
Release
res
Comp3
Comp3.clw
Comp3.def
Comp3.dsp
Comp3.dsw
Debug
res
Debug
Release
res
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bitmap5.bmp
bitmap6.bmp
bitmap7.bmp
bitmap8.bmp
bitmap9.bmp
bmp00001.bmp
bmp00002.bmp
bmp00003.bmp
bmp00004.bmp
bmp00005.bmp
bmp00006.bmp
butterfl.ico
com.bmp
ComDemo.ico
ComDemoDoc.ico
ico00001.ico
ico00002.bmp
ico00002.ico
ico00003.ico
ico00004.ico
icon1.ico
Toolbar.bmp
parttwosources.zip
part_two
part_two_client
Debug
part_two_client.dsp
part_two_client.dsw
part_two_component
component.def
Component.dll
MAKEFILE
part_two_improved_client_server
client
client.dsp
client.dsw
Debug
Component
Component.clw
Component.def
Component.dsp
Component.dsw
Debug
Component.dll
res
part_two_rebuildproblem
client
client.dsp
client.dsw
Debug
DLL.dll
DLL
Debug
DLL.dsp
DLL.dsw
// Comp2.cpp 

#include "stdafx.h"
#include "interface.h"
#include <afxdllx.h>
#include <objbase.h>
#include <assert.h>
#include "component2wnd.h"
#include "resource.h"
#include <objbase.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//////////////////////////////////////////
BOOL APIENTRY DllMain(HINSTANCE InsModule, 
                      DWORD dwReason, 
                      void* lpReserved)
{

	return TRUE ;
}


//------------------------------------------//
//Definition of the class of the component 1
//-----------------------------------------//

class CComponent2 :public IComponent2

{	
private:
       long m_cRef;
       CComponent2Wnd*   m_pWnd;
        
public:
	virtual HRESULT  __stdcall QueryInterface(const IID& iid,void** ppv);
	virtual ULONG	 __stdcall AddRef();
	virtual ULONG	 __stdcall Release();
    virtual void __stdcall DefineWindow_Com2(bool inner);
	virtual void __stdcall ShowWndBackground_Com2(COLORREF bgcolor);
    virtual IUnknown* __stdcall Queryitself2();
	virtual void __stdcall MenuitemNotselected2();
   	virtual void __stdcall StopFlying();
	virtual void __stdcall StartFlying();
	CComponent2();
	~CComponent2();
};

///////////////////////////////////////////////
IUnknown*  __stdcall CComponent2::Queryitself2()
{
    IUnknown* pIunkown=NULL;
	QueryInterface(IID_IUnknown,(void**)&pIunkown);
  	m_cRef-=3;
	return pIunkown;
}

///////////////
//Counstructor
CComponent2::CComponent2():m_cRef(1),m_pWnd(NULL)
{
	TRACE(_T("Component2:constructor is called\n"));
	TRACE(_T("Initializing the Refrance conut to one\n"));
}

//////////////
//Destructor
CComponent2::~CComponent2()
{
	TRACE(_T("~CComponent2: Destructor is called\n"));
    
}

////////////////////////////////////////////////////////////////////////
HRESULT __stdcall CComponent2::QueryInterface(const IID& iid,void** ppv)
////////////////////////////////////////////////////////////////////////
{
	if(iid==IID_IUnknown)
	{
		TRACE(_T("Returning a pointer to IUnkown interface\n"));
		*ppv=static_cast<IComponent2*>(this);
	   
	}
	   

	else if(iid==IID_IComponent2)
	{
		TRACE(_T("Returing a pointer to IComponent interface\n"));
		*ppv=static_cast<IComponent2*>(this);
	    
	}
	
else
{
	TRACE(_T("Interface is not supported\n"));
	*ppv=NULL;
	return E_NOINTERFACE;
}

reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
	return S_OK ;

}




/////////////////////////////////////
//AddRef
ULONG __stdcall CComponent2::AddRef()
////////////////////////////////////
{
    CPoint point;
    CRect rect;
	char buf[10];
	TRACE(_T("Increamenting the Refrance count\n"));
	//TRACE(_T("The Refrance count is:\n"));
    //TRACE(_T(itoa(m_cRef+1,buf,10)));
    if(NULL!=m_pWnd)
	{
		m_pWnd->m_cRef++;
		CRect rect;
        CDC* pDC=m_pWnd->GetDC();
		pDC->GetClipBox (&rect);
	    pDC->DrawText(itoa(m_pWnd->m_cRef,buf,10),&rect,DT_RIGHT);
	}
	return ++m_cRef;
}


/////////////////////////////////////	
//Release
/////////////////////////////////////
ULONG __stdcall CComponent2::Release()
{
	char buf[10];
	CStdioFile fw;
	if(NULL!=m_pWnd)
	{
		m_pWnd->m_cRef--;
		CRect rect;
        CDC* pDC=m_pWnd->GetDC();
		pDC->GetClipBox (&rect);
		pDC->DrawText(itoa(m_pWnd->m_cRef,buf,10),&rect,DT_RIGHT);
	}
	// Win32 functions InterlockedDecrement and InterlockedIncrement are used
	// to make sure that only one thread accesses the refrance count variable at a time
	if(InterlockedDecrement(&m_cRef)==0)
	{
		TRACE(_T("Deleting of component 2 in progress..."));
		delete this;
		//if(NULL!=m_pWnd)delete m_pWnd;
		::DestroyWindow (::GetActiveWindow());
	    //The client uses this file in order to know the componet exsists,
		//befor using the interfaces
     	fw.Open ("C:\\Comp2IUnknown.txt",CFile::modeWrite);
					fw.WriteString ("0");
					fw.Close();	
		return 0;
	}
	TRACE(_T("Decermenting the Refrance count\n"));

return m_cRef;
}
 


//////////////////////////////////////////
void __stdcall CComponent2::DefineWindow_Com2(bool inner)
{
	CString wndtxt="COM Component 2";
	if(inner)
		wndtxt+=",inner";

	//Registering the windows class
	CString strWndClass= AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
		                                    LoadCursor(NULL, IDC_ARROW),
	                                        (HBRUSH)GetStockObject(WHITE_BRUSH),
	                                         0);
	//Create a window object
	m_pWnd = new CComponent2Wnd();
   
	//Creating the component2 window with popup style
    m_pWnd->CreateEx(WS_OVERLAPPED,//windows syle
					  strWndClass,//class name
					  wndtxt,//Windows text
					  WS_EX_TOOLWINDOW,//windows extended style
					  330,//rect.right,
					  330,//rect.bottom,
					  180,//widows width
					  120,//windows hight
					  0,//top-level window and no parent
					  0,//no menu loaded yet
					  0);//no data
    
	//pointing to the own interface from the components own inner window
	//in order to be able to handel menuitem selections
	m_pWnd->m_pComponent2sIUnknown=Queryitself2();
	
	//loading a menu resource from the application�s executable file and
	//attach it to the m_WndMenu object
	if(!inner)
	{
		m_pWnd->m_WndMenu.LoadMenu("IDR_COM2MENU");
		m_pWnd->SetMenu(&m_pWnd->m_WndMenu);
	}
	
	//showing component2s window
	m_pWnd->ShowWindow(SW_SHOW);

}
void __stdcall CComponent2::MenuitemNotselected2()
{
   TRACE(_T("Menu item not selected\n"));     
	if(NULL!=m_pWnd)
	    //(white color code).. client area of the clients view window
		m_pWnd->m_color_hittest=16777215;

}


////////////////////////////////////////
void __stdcall CComponent2::ShowWndBackground_Com2(COLORREF bgcolor)
{
 
    CRect rect;
    CDC*  pDC=m_pWnd->GetDC();
    m_pWnd->GetClientRect (&rect);
    CBrush brush;
	brush.CreateSolidBrush (bgcolor);
    pDC->FillRect(&rect,&brush);	
	CBitmap bmp, *poldbmp;
    CDC memdc;
    bmp.LoadBitmap("IDB_BITMAP");
  	memdc.CreateCompatibleDC( pDC );
    poldbmp = memdc.SelectObject( &bmp );
    pDC->BitBlt( rect.right -100,rect.bottom/4, 100, 100, &memdc, 0, 0, SRCCOPY );
    memdc.SelectObject( poldbmp );
    
	
}
////////////////////////////////////
 void __stdcall CComponent2::StopFlying ()
{
   m_pWnd->m_bStop=true;	 
   m_pWnd->_KillTimer ();
 }

 ////////////////////////////////////
 void __stdcall CComponent2::StartFlying ()
{
   m_pWnd->StartTimer ();
   m_pWnd->m_bStop=false;
} 


///////////////////////////////////////////////////////////
//
// Class factory
//
class CFactory : public IClassFactory
{
public:
	// IUnknown
	virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv) ;
	virtual ULONG   __stdcall AddRef() ;
	virtual ULONG   __stdcall Release() ;
	
	// Interface IClassFactory
	virtual HRESULT __stdcall CreateInstance(IUnknown* pUnkOuter,
	                                         const IID& iid,
	                                         void** ppv) ;
	virtual HRESULT __stdcall LockServer(BOOL bLock) ; 

	// Constructor
	CFactory() : m_cRef(1) {}

	// Destructor
	~CFactory() {}

private:
	long m_cRef ;
} ;

//
// Class factory IUnknown implementation
////////////////////////////////////////////////////////////////////////
HRESULT __stdcall CFactory::QueryInterface(const IID& iid,LPVOID* ppv)
{ 	
	if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
		*ppv = static_cast<IClassFactory*>(this) ; 
	else
	{
		*ppv = NULL ;
		return E_NOINTERFACE ;
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
	return S_OK ;
}

ULONG __stdcall CFactory::AddRef()
{
	return ::InterlockedIncrement(&m_cRef) ;
}

ULONG __stdcall CFactory::Release() 
{
	TRACE(_T("Release() from CFactroy in progress..."));
	if (::InterlockedDecrement(&m_cRef) == 0)
	{
		delete this ;
		return 0 ;
	}
	return m_cRef ;
}

//
// IClassFactory implementation
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnkOuter,
                                           const IID& iid,
                                           void** ppv) 
{
	
	TRACE(_T("CreateInstance is called\n"));
	// Cannot aggregate
	if (pUnkOuter != NULL)
	{
		return CLASS_E_NOAGGREGATION ;
	}
	// Create component.
    TRACE(_T("Creating Component2 \n"));
	CComponent2* pComponent2 = new CComponent2 ;
	if (pComponent2 == NULL)
	{
		TRACE(_T("No memory available\n"));
		return E_OUTOFMEMORY ;
	}
	

	// Get the requested interface.
    TRACE(_T("Calling QueryInterface(IID_Component2,(void**)&pIComponent2\n"));
	HRESULT	hr = pComponent2->QueryInterface(iid,(void**) ppv) ;
	//if Query faild the comp will delete itself
	
	
	if(FAILED(hr))
	{
	    TRACE(_T("Problem in calling Queryinterface\n"));
		pComponent2->Release() ;
	}

	return hr ;   
}

// LockServer
HRESULT __stdcall CFactory::LockServer(BOOL bLock) 
{
	
	return S_OK ;
}


//
// Get class factory
///////////////////////////////////////////
STDAPI DllGetClassObject(const CLSID& clsid,
                         const IID& iid,
                         void** ppv)
{
	TRACE(_T("DllGetClassObject:\tCreate class factory.\n")) ;

	// Can we create this component?
	if (clsid != CLSID_Component2)
	{
		TRACE(_T("Unable to create Component2\n"));
		return CLASS_E_CLASSNOTAVAILABLE ;
	}

	// Create class factory.
	CFactory* pFactory = new CFactory ;  // No AddRef in constructor
	if (pFactory == NULL)
	{
		TRACE(_T("No memory available\n"));
		return E_OUTOFMEMORY ;
	}

	TRACE(_T("Getting the requested interface\n"));
	// Get requested interface.
	HRESULT hr = pFactory->QueryInterface(iid, ppv) ;
    TRACE(_T("Calling Release() member of CFactory object\n"));
	pFactory->Release() ;
    TRACE(_T("CFactory: Releasing itself,done\n"));
	return hr ;
}







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

Share

About the Author

Aria Ansari
Software Developer
Denmark Denmark
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 18 Apr 2004
Article Copyright 2004 by Aria Ansari
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid