/*
* DATAOBJ.CPP
* Data Object Chapter 10
*
* Implementation of CDataObject and CImpIDataObject that work
* in either an EXE or DLL.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "dataobj.h"
extern HINSTANCE g_hInst;
DWORD g_dwID=0;
//Names of data sizes
static TCHAR * rgszSize[3]={TEXT("Small"), TEXT("Medium")
, TEXT("Large")};
/*
* CDataObject::CDataObject
* CDataObject::~CDataObject
*
* Parameters (Constructor):
* pUnkOuter LPUNKNOWN of controlling unknown, if it exists.
* pfnDestroy PFNDESTROYED to call when object is destroyed.
* iSize UINT specifying the size of the data set to use.
*/
CDataObject::CDataObject(LPUNKNOWN pUnkOuter
, PFNDESTROYED pfnDestroy, UINT iSize)
{
UINT i;
m_cRef=0;
m_pUnkOuter=pUnkOuter;
m_pfnDestroy=pfnDestroy;
m_iSize=iSize;
m_hWndAdvise=NULL;
m_dwAdvFlags=ADVF_NODATA;
//NULL any contained interfaces initially.
m_pImpIDataObject=NULL;
m_pIDataAdviseHolder=NULL;
//Initilize the FORMATETCs arrays we use for EnumFormatEtc
m_cfeGet=CFORMATETCGET;
SETDefFormatEtc(m_rgfeGet[0], CF_METAFILEPICT, TYMED_MFPICT);
SETDefFormatEtc(m_rgfeGet[1], CF_BITMAP, TYMED_GDI);
SETDefFormatEtc(m_rgfeGet[2], CF_TEXT, TYMED_HGLOBAL);
for (i=0; i < DOSIZE_CSIZES; i++)
m_rghBmp[i]=NULL;
return;
}
CDataObject::~CDataObject(void)
{
UINT i;
for (i=0; i < DOSIZE_CSIZES; i++)
{
if (NULL!=m_rghBmp[i])
DeleteObject(m_rghBmp[i]);
}
ReleaseInterface(m_pIDataAdviseHolder);
DeleteInterfaceImp(m_pImpIDataObject);
if (NULL!=m_hWndAdvise)
DestroyWindow(m_hWndAdvise);
return;
}
/*
* CDataObject::Init
*
* Purpose:
* Performs any intiailization of a CDataObject that's prone to
* failure that we also use internally before exposing the
* object outside.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if the function is successful,
* FALSE otherwise.
*/
BOOL CDataObject::Init(void)
{
LPUNKNOWN pIUnknown=this;
UINT i;
TCHAR szTemp[80];
UINT cy;
if (NULL!=m_pUnkOuter)
pIUnknown=m_pUnkOuter;
//Allocate contained interfaces.
m_pImpIDataObject=new CImpIDataObject(this, pIUnknown);
if (NULL==m_pImpIDataObject)
return FALSE;
for (i=0; i < DOSIZE_CSIZES; i++)
{
m_rghBmp[i]=LoadBitmap(g_hInst, MAKEINTRESOURCE(i+IDB_MIN));
if (NULL==m_rghBmp[i])
return FALSE;
}
/*
* Register the Advise window class first time through
* (g_dwID==0)
*/
if (0L==g_dwID)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = AdvisorWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(PCDataObject);
wc.hInstance = g_hInst;
wc.hIcon = LoadIcon(g_hInst
, MAKEINTRESOURCE(IDR_ADVISORICON));
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = TEXT("Advisor");
if (!RegisterClass(&wc))
return FALSE;
}
/*
* Create an advise window with a unique caption:
* "<size> <module> Advisor #xx" where <size> is Small,
* Medium, or Large, <module> is EXE or DLL, and xx is
* counted globally every time a CDataObject is created.
*/
g_dwID++;
#ifdef EXEDATAOBJECT
wsprintf(szTemp, TEXT("%s EXE Advisor #%lu")
, (LPTSTR)rgszSize[m_iSize], g_dwID);
#else
wsprintf(szTemp, TEXT("%s DLL Advisor #%lu")
, (LPTSTR)rgszSize[m_iSize], g_dwID);
#endif
cy=(GetSystemMetrics(SM_CYBORDER)*2)+GetSystemMetrics(SM_CYMENU)
+ GetSystemMetrics(SM_CYCAPTION);
m_hWndAdvise=CreateWindow(TEXT("Advisor"), szTemp
, WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER
| WS_VISIBLE, 400, 35+(g_dwID*(cy+30)), 200, cy
, HWND_DESKTOP, NULL, g_hInst, this);
if (NULL==m_hWndAdvise)
return FALSE;
return TRUE;
}
/*
* CDataObject::QueryInterface
* CDataObject::AddRef
* CDataObject::Release
*
* Purpose:
* IUnknown members for CDataObject object.
*/
STDMETHODIMP CDataObject::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv=this;
if (IID_IDataObject==riid)
*ppv=m_pImpIDataObject;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CDataObject::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CDataObject::Release(void)
{
if (0!=--m_cRef)
return m_cRef;
if (NULL!=m_pfnDestroy)
(*m_pfnDestroy)();
delete this;
return 0;
}
/*
* AdvisorWndProc
*
* Purpose:
* Standard window class procedure.
*/
LRESULT APIENTRY AdvisorWndProc(HWND hWnd, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
PCDataObject pDO;
DWORD i;
DWORD iAdvise;
DWORD dwTime;
DWORD dwAvg;
TCHAR szTime[128];
TCHAR szTitle[80];
HCURSOR hCur, hCurT;
pDO=(PCDataObject)GetWindowLong(hWnd, 0);
switch (iMsg)
{
case WM_NCCREATE:
pDO=(PCDataObject)(((LPCREATESTRUCT)lParam)
->lpCreateParams);
SetWindowLong(hWnd, 0, (LONG)pDO);
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_CLOSE:
//Forbid task manager from closing us.
return 0L;
case WM_COMMAND:
if (NULL==pDO->m_pIDataAdviseHolder)
break;
//Send IAdviseSink::OnDataChange many times.
i=(DWORD)(LOWORD(wParam)-IDM_ADVISEITERATIONSMIN+1);
iAdvise=(i*i)*16;
hCur=LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
hCurT=SetCursor(hCur);
ShowCursor(TRUE);
dwTime=GetTickCount();
i=0;
while (TRUE)
{
#ifdef EXEDATAOBJECT
#ifndef WIN32
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
#endif
#endif
{
pDO->m_pIDataAdviseHolder->SendOnDataChange
(pDO->m_pImpIDataObject, 0, ADVF_NODATA);
if (++i >= iAdvise)
break;
}
}
dwTime=GetTickCount()-dwTime;
dwAvg=dwTime/iAdvise;
SetCursor(hCurT);
ShowCursor(FALSE);
wsprintf(szTime
, TEXT("Total=%lu ms\n\rAverage=%lu ms")
, dwTime, dwAvg);
GetWindowText(hWnd, szTitle, sizeof(szTitle));
MessageBox(hWnd, szTime, szTitle, MB_OK);
break;
default:
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
}
return 0L;
}