// Comp1.cpp
#include "stdafx.h"
#include "interface.h"
#include <afxdllx.h>
#include <objbase.h>
#include <assert.h>
#include "component1wnd.h"
#include "ComponentWndMenu.h"
#include "resource.h"
#include <objbase.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//------------------------------------------//
//Definition of the class of the component 1
//-----------------------------------------//
class CComponent1 :public IComponent1
{
private:
long m_cRef;// reference count
CComponent1Wnd* m_pWnd;//pointer to the Components window
public:
//IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
//Desired functionality for Component
virtual void __stdcall DefineWindow_Com1(bool inner);
virtual void __stdcall ShowWndBackground_Com1(COLORREF bgcolor);
virtual IUnknown* __stdcall Queryitself1();
virtual void __stdcall MenuitemNotselected1();
virtual void __stdcall Night();
CComponent1();
~CComponent1();
};
///////////////////////////////////////////////
IUnknown* __stdcall CComponent1::Queryitself1()
{
IUnknown* pIunkown=NULL;
QueryInterface(IID_IUnknown,(void**)&pIunkown);
m_cRef-=3;
return pIunkown;
}
////////////////////////////////////////////////////////////////////////
HRESULT __stdcall CComponent1::QueryInterface(const IID& iid,void** ppv)
////////////////////////////////////////////////////////////////////////
{
if(iid==IID_IUnknown)
{
TRACE(_T("Returning a pointer to IUnkown interface\n"));
*ppv=static_cast<IComponent1*>(this);
}
else if(iid==IID_IComponent1)
{
TRACE(_T("Returing a pointer to IComponent interface\n"));
*ppv=static_cast<IComponent1*>(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 CComponent1::AddRef()
////////////////////////////////////
{
CPoint point;
CRect rect;
char buf[10];
TRACE(_T("Increamenting the Refrance count\n"));
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 CComponent1::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 component 1 in progress..."));
delete this;
::DestroyWindow (::GetActiveWindow());
//The client uses this file in order to know the componet exsists,before using the interfaces
fw.Open ("C:\\Comp1IUnknown.txt",CFile::modeWrite);
fw.WriteString ("0");
fw.Close();
return 0;
}
TRACE(_T("Decermenting the Refrance count\n"));
TRACE(_T("The Refrance count is:\n"));
TRACE(_T(itoa(m_cRef,buf,10)));
return m_cRef;
}
///////////////////////////////////////////////////////////
void __stdcall CComponent1::DefineWindow_Com1(bool inner)
{
CString wndtxt="COM Component 1";
if(inner)
wndtxt+=",inner";
//Registering the windows class
CString strWndClass= AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
LoadCursor(NULL, IDC_ARROW),
(HBRUSH)GetStockObject(WHITE_BRUSH),
0);
//having a window object for Component1
m_pWnd = new CComponent1Wnd();
//------------------------------------------------//
//Creating component1's window with popup style
//------------------------------------------------//
m_pWnd->CreateEx(WS_OVERLAPPED,//windows syle
strWndClass,//class name
wndtxt,//Window text
WS_EX_TOOLWINDOW,//windows extended style
140,//rect.right,
330,//rect.bottom,
180,//windows width
120,//windows hight
0,//top-level window and no parent
0,//no menu will be loaded at creation time
0);//no data
/*
//---------------------------------------------------------------------------------//
// use this function if the client is a Multiple Document and the components window
//is a child window
//---------------------------------------------------------------------------------//
m_pWnd->Create(strWndClass,
"COMPONENT 1",
WS_CHILD |WS_VISIBLE | WS_OVERLAPPEDWINDOW,
rect,
NULL,
NULL);
*/
//------------------------------------------------------------------------------------//
//pointing to the own interface from the components own inner window
//in order to be able to handel menuitem selections regarding to AddRef() and Release()
//------------------------------------------------------------------------------------//
m_pWnd->m_pComponent1sIUnknown=Queryitself1();
//------------------------------------------//
//--------------------------------------------------------------------//
//loading a menu resource from the application�s executable file and
//attach it to the m_WndMenu object
if(!inner)//no menu for inner components
{
m_pWnd->m_WndMenu.LoadMenu("IDR_COM1MENU");
m_pWnd->SetMenu(&m_pWnd->m_WndMenu);
}
//-------------------------------------------------------------------//
//showing component1
m_pWnd->ShowWindow(SW_SHOW);
}
//----------------------------------------------------------------------------//
//This function is called from the client,indicating that a menu item from the
//componnents window has not been selected.
//---------------------------------------------------------------------------//
//////////////////////////////////////////////////
void __stdcall CComponent1::MenuitemNotselected1()
{
TRACE(_T("MenuitemNotselected\n"));
if(NULL!=m_pWnd)
//(white/black color code).. client area of the clients view window
m_pWnd->m_color_hittest=16777215;//white as default
}
///////////////////////////////////////////////////////////////////
void __stdcall CComponent1::ShowWndBackground_Com1(COLORREF bgcolor)
{
CPoint point;
CRect rect;
CDC* pDC=m_pWnd->GetDC();
m_pWnd->GetClientRect (&rect);
CBrush bgbrush;
bgbrush.CreateSolidBrush (bgcolor);
pDC->FillRect(&rect,&bgbrush);
HICON HI=::LoadIcon(AfxGetResourceHandle(),"IDI_SUN");
point.x =rect.left /2;
point.y=rect.bottom /2;
pDC->DrawIcon(point,HI);
}
////////////////////////////////////
void __stdcall CComponent1::Night ()
{
CRect rect;
CDC* pDC=m_pWnd->GetDC();
m_pWnd->GetClientRect (&rect);
CBrush brush;
brush.CreateSolidBrush (RGB(0,0,0));
pDC->FillRect(&rect,&brush);
CBitmap bmp, *poldbmp;
CDC memdc;
//----------------------------------------------------------------------//
//The dll is loaded into the same address space as the client,(look at
//the third parameter in the CoCreateInstance(...) function which defines
//server type (CLSCTX_INPROC_SERVER))
//therefor the dll have access to the clients resources
//as en example here,a bitmap is loaded from the client's exe file
//in the following line:
//------------------------------------------------------------------------//
bmp.LoadBitmap("IDB_MOON" );
//------------------------------------------------------------------------//
memdc.CreateCompatibleDC( pDC );
poldbmp = memdc.SelectObject( &bmp );
pDC->BitBlt( rect.right -122,rect.bottom -64, 100, 100, &memdc, 0, 0, SRCCOPY );
memdc.SelectObject( poldbmp );
}
///////////////
//Counstructor
CComponent1::CComponent1():m_cRef(1),m_pWnd(NULL)
{
TRACE(_T("Component1:constructor is called\n"));
TRACE(_T("Initializing the Refrance conut to one\n"));
}
//////////////
//Destructor
CComponent1::~CComponent1()
{
TRACE(_T("~CComponent1: Destructor is called\n"));
}
///////////////////////////////////////////////////////////
//
// 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 Component1 \n"));
CComponent1* pComponent1 = new CComponent1 ;
if (pComponent1 == NULL)
{
TRACE(_T("No memory available\n"));
return E_OUTOFMEMORY ;
}
// Get the requested interface.
TRACE(_T("Calling QueryInterface(IID_Component1,(void**)&pIComponent1\n"));
HRESULT hr = pComponent1->QueryInterface(iid,(void**) ppv) ;
//if Query faild the comp will delete itself
if(FAILED(hr))
{
TRACE(_T("Problem in calling Queryinterface\n"));
pComponent1->Release() ;
}
return hr ;
}
//-----------------------------------------------------------------------//
// LockServer
// Called by the client of a class object to keep a server open in memory,
// allowing instances to be created more quickly.
//-----------------------------------------------------------------------//
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
return S_OK ;
}
//--------------------------------------------------------------------------//
// Getting the class factory
// DllGetClassObject :
// Retrieves the class object from a DLL object handler or object application.
// DllGetClassObject is called from within the CoGetClassObject function when
// the class context is a DLL.
//-------------------------------------------------------------------------//
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
TRACE(_T("DllGetClassObject:\tCreate class factory.\n"));
// Can we create component1?
if (clsid != CLSID_Component1)
{
TRACE(_T("Unable to create Component1\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 a poiner to the IClassFactory 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 ;
}
///////////////////////////////////////////
BOOL APIENTRY DllMain(HINSTANCE InsModule,
DWORD dwReason,
void* lpReserved)
{
return TRUE;
}