Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1261 lines
31 KiB

/*
* DATAUSER.CPP
* Data Object User Chapter 6
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : [email protected]
* Compuserve: >INTERNET:[email protected]
*/
#define INIT_MY_GUIDS
#include "datausr.h"
#include "perror.h"
#include <stdio.h>
#ifdef WIN32
#define APP_TITLE TEXT("32 Bit IDataObject User")
#else
#define APP_TITLE TEXT("16 Bit IDataObject User")
#endif
//These are for displaying clipboard formats textually.
static TCHAR * rgszCF[13]={TEXT("Unknown"), TEXT("CF_TEXT")
, TEXT("CF_BITMAP"), TEXT("CF_METAFILEPICT")
, TEXT("CF_SYLK"), TEXT("CF_DIF"), TEXT("CF_TIFF")
, TEXT("CF_OEMTEXT"), TEXT("CF_DIB")
, TEXT("CF_PALETTE"), TEXT("CF_PENDATA")
, TEXT("CF_RIFF"), TEXT("CF_WAVE")};
static TCHAR szSuccess[] =TEXT("succeeded");
static TCHAR szFailed[] =TEXT("failed");
static TCHAR szExpected[] =TEXT("expected");
static TCHAR szUnexpected[] =TEXT("unexpected!");
TCHAR tcMessageBuf[4096]; // Misc use buffer for messages.
int cKSizes[NUM_POINTS] = { 1, 2, 4, 6, 8,
10, 12, 16, 20, 24,
28, 32, 40, 48, 56 };
/*
* WinMain
*
* Purpose:
* Main entry point of application.
*/
int PASCAL WinMain(
HINSTANCE hInst,
HINSTANCE hInstPrev,
LPSTR pszCmdLine,
int nCmdShow)
{
MSG msg;
PAPPVARS pAV;
#ifndef WIN32
int cMsg=96;
while (!SetMessageQueue(cMsg) && (cMsg-=8));
#endif
pAV=new CAppVars(hInst, hInstPrev, nCmdShow);
if (NULL==pAV)
return -1;
if (pAV->FInit())
{
while (GetMessage(&msg, NULL, 0,0 ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
delete pAV;
return msg.wParam;
}
/*
* DataUserWndProc
*
* Purpose:
* Window class procedure. Standard callback.
*/
LRESULT API_ENTRY DataUserWndProc(HWND hWnd, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
HRESULT hr;
PAPPVARS pAV;
HMENU hMenu;
FORMATETC fe;
WORD wID;
int i;
pAV=(PAPPVARS)GetWindowLong(hWnd, DATAUSERWL_STRUCTURE);
switch (iMsg)
{
case WM_NCCREATE:
pAV=(PAPPVARS)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLong(hWnd, DATAUSERWL_STRUCTURE, (LONG)pAV);
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
pAV->Paint();
break;
case WM_COMMAND:
SETDefFormatEtc(fe, 0, TYMED_HGLOBAL | TYMED_GDI| TYMED_MFPICT);
hMenu=GetMenu(hWnd);
wID=LOWORD(wParam);
if(wID >= IDM_OBJECTSETDATA && wID <= IDM_OBJECTSETDATA+64)
{
// Blast all possible SetData menu items. Some don't exist.
for(i=IDM_OBJECTSETDATA; i<=IDM_OBJECTSETDATA+64; i++)
CheckMenuItem(hMenu,i, MF_UNCHECKED);
CheckMenuItem(hMenu, wID, MF_CHECKED);
pAV->m_SetData_SetSize(wID-IDM_OBJECTSETDATA);
break;
}
switch (wID)
{
case IDM_USE16BITSERVER:
if (pAV->m_f16Bit)
break;
pAV->m_f16Bit = TRUE;
pAV->FReloadDataObjects(TRUE);
break;
case IDM_USE32BITSERVER:
if (!pAV->m_f16Bit)
break;
pAV->m_f16Bit = FALSE;
pAV->FReloadDataObjects(TRUE);
break;
case IDM_OBJECTQUERYGETDATA:
if (NULL==pAV->m_pIDataObject)
break;
fe.tymed=TYMED_HGLOBAL | TYMED_GDI
| TYMED_MFPICT;
pAV->TryQueryGetData(&fe, CF_TEXT, TRUE, 0);
pAV->TryQueryGetData(&fe, CF_BITMAP, TRUE, 1);
#ifdef NOT_SIMPLE
pAV->TryQueryGetData(&fe, CF_DIB, FALSE, 2);
pAV->TryQueryGetData(&fe, CF_METAFILEPICT, TRUE, 3);
pAV->TryQueryGetData(&fe, CF_WAVE, FALSE, 4);
#endif /* NOT_SIMPLE */
break;
case IDM_OBJECTGETDATA_TEXT:
case IDM_OBJECTGETDATA_BITMAP:
#ifdef NOT_SIMPLE
case IDM_OBJECTGETDATA_METAFILEPICT:
#endif /* NOT_SIMPLE */
if (pAV->m_GetData(wID) )
{
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
if(pAV->m_fDisplayTime)
pAV->m_DisplayTimerResults();
break;
case IDM_OBJECTGETDATAHERE_TEXT:
case IDM_OBJECTGETDATAHERE_NULLTEXT:
case IDM_OBJECTGETDATAHERE_BITMAP:
case IDM_OBJECTGETDATAHERE_NULLBITMAP:
if (pAV->m_GetDataHere(wID) )
{
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
if(pAV->m_fDisplayTime)
pAV->m_DisplayTimerResults();
break;
case IDM_OBJECTSETDATAPUNK_TEXT:
case IDM_OBJECTSETDATAPUNK_BITMAP:
pAV->m_SetData_WithPUnk(wID);
break;
case IDM_MEASUREMENT_1:
case IDM_MEASUREMENT_50:
case IDM_MEASUREMENT_300:
case IDM_MEASUREMENT_OFF:
case IDM_MEASUREMENT_ON:
case IDM_MEASUREMENT_TEST:
pAV->m_SetMeasurement(wID);
break;
case IDM_BATCH_GETDATA:
pAV->m_MeasureAllSizes(IDM_OBJECTGETDATA_TEXT,
TEXT("GetData w/HGLOBAL"),
NULL);
break;
case IDM_BATCH_GETDATAHERE:
pAV->m_MeasureAllSizes(IDM_OBJECTGETDATAHERE_TEXT,
TEXT("GetDataHere w/HGLOBAL"),
NULL);
break;
case IDM_BATCHTOFILE:
pAV->m_BatchToFile();
break;
case IDM_OBJECTEXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
#ifdef NOT_SIMPLE
case IDM_ADVISETEXT:
case IDM_ADVISEBITMAP:
case IDM_ADVISEMETAFILEPICT:
if (NULL==pAV->m_pIDataObject)
break;
//Terminate the old connection
if (0!=pAV->m_dwConn)
{
pAV->m_pIDataObject->DUnadvise(pAV
->m_dwConn);
}
CheckMenuItem(hMenu, pAV->m_cfAdvise
+IDM_ADVISEMIN, MF_UNCHECKED);
CheckMenuItem(hMenu, wID, MF_CHECKED);
//New format is wID-IDM_ADVISEMIN
pAV->m_cfAdvise=(UINT)(wID-IDM_ADVISEMIN);
fe.cfFormat=pAV->m_cfAdvise;
pAV->m_pIDataObject->DAdvise(&fe, ADVF_NODATA
, pAV->m_pIAdviseSink, &pAV->m_dwConn);
break;
case IDM_ADVISEGETDATA:
pAV->m_fGetData=!pAV->m_fGetData;
CheckMenuItem(hMenu, wID, pAV->m_fGetData
? MF_CHECKED : MF_UNCHECKED);
break;
case IDM_ADVISEREPAINT:
pAV->m_fRepaint=!pAV->m_fRepaint;
CheckMenuItem(hMenu, wID, pAV->m_fRepaint
? MF_CHECKED : MF_UNCHECKED);
break;
#endif /* NOT_SIMPLE*/
default:
break;
}
break;
default:
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
}
return 0L;
}
/*
* CAppVars::CAppVars
* CAppVars::~CAppVars
*
* Constructor Parameters: (from WinMain)
* hInst HINSTANCE of the application.
* hInstPrev HINSTANCE of a previous instance.
* nCmdShow UINT specifying how to show the app window.
*/
CAppVars::CAppVars(HINSTANCE hInst, HINSTANCE hInstPrev
, UINT nCmdShow)
{
m_hInst =hInst;
m_hInstPrev =hInstPrev;
m_nCmdShow =nCmdShow;
m_hWnd =NULL;
#ifdef NOT_SIMPLE
m_fEXE =FALSE;
m_pIAdviseSink =NULL;
m_dwConn =0;
m_cfAdvise =0;
m_fGetData =FALSE;
m_fRepaint =FALSE;
m_pIDataSmall =NULL;
m_pIDataMedium=NULL;
m_pIDataLarge =NULL;
#endif /* NOT_SIMPLE */
m_pIDataObject=NULL;
m_f16Bit=FALSE;
m_cfFormat=0;
m_stm.tymed=TYMED_NULL;
m_stm.lpszFileName=NULL; //Initializes union to NULL
m_stm.pUnkForRelease=NULL;
m_HereAllocCount=0; // For debugging
m_fInitialized=FALSE;
return;
}
CAppVars::~CAppVars(void)
{
//This releases the data object interfaces and advises
FReloadDataObjects(FALSE);
ReleaseStgMedium(&m_stm);
#ifdef NOT_SIMPLE
if (NULL!=m_pIAdviseSink)
m_pIAdviseSink->Release();
#endif /* NOT_SIMPLE */
if (IsWindow(m_hWnd))
DestroyWindow(m_hWnd);
if (m_fInitialized)
CoUninitialize();
return;
}
/*
* CAppVars::FInit
*
* Purpose:
* Initializes an CAppVars object by registering window classes,
* creating the main window, and doing anything else prone to
* failure such as calling CoInitialize. If this function fails
* the caller should insure that the destructor is called.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CAppVars::FInit(void)
{
WNDCLASS wc;
DWORD dwVer;
BOOL fRet;
dwVer=CoBuildVersion();
if (rmm!=HIWORD(dwVer))
return FALSE;
if (FAILED(CoInitialize(NULL)))
return FALSE;
m_fInitialized=TRUE;
//Register our window classes.
if (!m_hInstPrev)
{
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DataUserWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = CBWNDEXTRA;
wc.hInstance = m_hInst;
wc.hIcon = LoadIcon(m_hInst, TEXT("Icon"));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = TEXT("DATAUSER");
if (!RegisterClass(&wc))
return FALSE;
}
//Create the main window.
m_hWnd=CreateWindow(TEXT("DATAUSER"),
APP_TITLE,
WS_OVERLAPPEDWINDOW,
35, 35, 350, 250,
NULL, NULL,
m_hInst, this);
if (NULL==m_hWnd)
return FALSE;
ShowWindow(m_hWnd, m_nCmdShow);
UpdateWindow(m_hWnd);
m_iDataSizeIndex=1;
CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTSETDATA+1, MF_CHECKED);
for(int i=0; i<64; i++)
m_hgHereBuffers[i] = NULL;
m_cIterations = 1;
CheckMenuItem(GetMenu(m_hWnd), IDM_MEASUREMENT_1, MF_CHECKED);
m_fDisplayTime = FALSE;
CheckMenuItem(GetMenu(m_hWnd), IDM_MEASUREMENT_OFF, MF_CHECKED);
#ifdef NOT_SIMPLE
m_pIAdviseSink=new CImpIAdviseSink(this);
if (NULL==m_pIAdviseSink)
return FALSE;
m_pIAdviseSink->AddRef();
CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTUSEDLL, MF_CHECKED);
CheckMenuItem(GetMenu(m_hWnd), IDM_OBJECTDATASIZESMALL
, MF_CHECKED);
#endif /* NOT_SIMPLE */
//Load the initial objects
fRet=FReloadDataObjects(TRUE);
#ifdef NOT_SIMPLE
m_pIDataObject=m_pIDataSmall;
#endif /* NOT_SIMPLE */
m_swTimer.m_ClassInit();
return fRet;
}
/*
* CAppVars::FReloadDataObjects
*
* Purpose:
* Releases the old data objects we're holding on to and reloads
* the new ones from either EXE or DLL depending on m_fEXE.
*
* Parameters:
* fReload BOOL indicating if we are to recreate everything
* or just release the old ones (so we can use this
* from the destructor).
*
* Return Value:
* BOOL TRUE if there are usable objects in us now.
*/
BOOL CAppVars::FReloadDataObjects(BOOL fReload)
{
HCURSOR hCur, hCurT;
//Clean out any data we're holding
m_cfFormat=0;
ReleaseStgMedium(&m_stm);
//Turn off whatever data connection we have
#ifdef NOT_SIMPLE
if (NULL!=m_pIDataObject && 0!=m_dwConn)
m_pIDataObject->DUnadvise(m_dwConn);
if (NULL!=m_pIDataLarge)
m_pIDataLarge->Release();
if (NULL!=m_pIDataMedium)
m_pIDataMedium->Release();
if (NULL!=m_pIDataSmall)
m_pIDataSmall->Release();
#else /* IS SIMPLE */
if (NULL != m_pIDataObject)
m_pIDataObject->Release();
#endif /* NOT_SIMPLE */
m_pIDataObject=NULL;
CoFreeUnusedLibraries();
//Exit if we just wanted to free.
if (!fReload)
return FALSE;
hCur=LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
hCurT=SetCursor(hCur);
ShowCursor(TRUE);
#ifdef NOT_SIMPLE
HRESULT hr1, hr2, hr3;
DWORD dwClsCtx;
dwClsCtx=(m_fEXE) ? CLSCTX_LOCAL_SERVER : CLSCTX_INPROC_SERVER;
hr1=CoCreateInstance(CLSID_DataObjectSmall, NULL, dwClsCtx
, IID_IDataObject, (PPVOID)&m_pIDataSmall);
hr2=CoCreateInstance(CLSID_DataObjectMedium, NULL, dwClsCtx
, IID_IDataObject, (PPVOID)&m_pIDataMedium);
hr3=CoCreateInstance(CLSID_DataObjectLarge, NULL, dwClsCtx
, IID_IDataObject, (PPVOID)&m_pIDataLarge);
#else /* IS SIMPLE */
HRESULT hr;
if(m_f16Bit)
{
hr = CoCreateInstance(CLSID_DataObjectTest16,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IDataObject,
(PPVOID)&m_pIDataObject);
}else
{
hr = CoCreateInstance(CLSID_DataObjectTest32,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IDataObject,
(PPVOID)&m_pIDataObject);
}
#endif /* NOT_SIMPLE */
ShowCursor(FALSE);
SetCursor(hCurT);
//If anything fails, recurse to clean up...
#ifdef NOT_SIMPLE
if (FAILED(hr1) || FAILED(hr2) || FAILED(hr3))
#else /* IS SIMPLE */
if (FAILED(hr))
#endif /* NOT_SIMPLE */
{
perror_OKBox(0, TEXT("CoCreateInstance Failed: "), hr);
return FReloadDataObjects(FALSE);
}
HMENU hMenu = GetMenu(m_hWnd);
UINT uTempD, uTempE;
if(m_f16Bit)
{
CheckMenuItem(hMenu, IDM_USE16BITSERVER, MF_CHECKED);
CheckMenuItem(hMenu, IDM_USE32BITSERVER, MF_UNCHECKED);
}
else
{
CheckMenuItem(hMenu, IDM_USE16BITSERVER, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_USE32BITSERVER, MF_CHECKED);
}
hMenu=GetMenu(m_hWnd);
for(int i=IDM_OBJECTSETDATA; i<=IDM_OBJECTSETDATA+64; i++)
{
CheckMenuItem(hMenu, i, MF_UNCHECKED);
}
m_iDataSizeIndex = 1;
CheckMenuItem(hMenu,
IDM_OBJECTSETDATA + m_iDataSizeIndex,
MF_CHECKED);
//Reset the state of the menus for Small, no advise, no options.
#ifdef NOT_SIMPLE
CheckMenuItem(hMenu, IDM_OBJECTDATASIZESMALL, MF_CHECKED);
CheckMenuItem(hMenu, IDM_OBJECTDATASIZEMEDIUM, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_OBJECTDATASIZELARGE, MF_UNCHECKED);
m_pIDataObject=m_pIDataSmall;
CheckMenuItem(hMenu, m_cfAdvise+IDM_ADVISEMIN, MF_UNCHECKED);
uTempE=m_fEXE ? MF_CHECKED : MF_UNCHECKED;
uTempD=!m_fEXE ? MF_CHECKED : MF_UNCHECKED;
CheckMenuItem(hMenu, IDM_OBJECTUSEDLL, uTempD);
CheckMenuItem(hMenu, IDM_OBJECTUSEEXE, uTempE);
CheckMenuItem(hMenu, IDM_ADVISEGETDATA, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_ADVISEREPAINT, MF_UNCHECKED);
m_fGetData=FALSE;
m_fRepaint=FALSE;
//Cannot request data using async advises, so disable these.
uTempE=m_fEXE ? MF_DISABLED | MF_GRAYED : MF_ENABLED;
EnableMenuItem(hMenu, IDM_ADVISEGETDATA, uTempE);
EnableMenuItem(hMenu, IDM_ADVISEREPAINT, uTempE);
#endif /* NOT_SIMPLE */
return TRUE;
}
/*
* CAppVars::TryQueryGetData
*
* Purpose:
* Centralized function call and output code for displaying results
* of various IDataObject::QueryGetData calls.
*
* Parameters:
* pFE LPFORMATETC to test.
* cf UINT specific clipboard format to stuff in pFE
* before calling. If zero, use whatever is
* already in pFE.
* fExpect BOOL indicating expected results
* y UINT line on which to print results.
*
* Return Value:
* None
*/
void CAppVars::TryQueryGetData(LPFORMATETC pFE, UINT cf
, BOOL fExpect, UINT y)
{
TCHAR szTemp[80];
LPTSTR psz1;
LPTSTR psz2;
UINT cch;
HRESULT hr;
HDC hDC;
if (0!=cf)
pFE->cfFormat=cf;
hr=m_pIDataObject->QueryGetData(pFE);
psz1=(NOERROR==hr) ? szSuccess : szFailed;
psz2=((NOERROR==hr)==fExpect) ? szExpected : szUnexpected;
hDC=GetDC(m_hWnd);
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
if (CF_WAVE < cf || 0==cf)
{
cch=wsprintf(szTemp, TEXT("QueryGetData on %d %s (%s).")
, cf, psz1, psz2);
}
else
{
cch=wsprintf(szTemp, TEXT("QueryGetData on %s %s (%s).")
, (LPTSTR)rgszCF[cf], psz1, psz2);
}
//Don't overwrite other painted display.
SetBkMode(hDC, TRANSPARENT);
TextOut(hDC, 0, 16*y, szTemp, cch);
ReleaseDC(m_hWnd, hDC);
return;
}
int
CAppVars::m_GetData(WORD wID)
{
FORMATETC fe;
HRESULT hr;
if (NULL == m_pIDataObject)
return(0); // Don't redraw.
//Clean up whatever we currently have.
m_cfFormat = 0;
ReleaseStgMedium(&m_stm);
switch (wID)
{
case IDM_OBJECTGETDATA_TEXT:
SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
break;
#ifdef NOT_SIMPLE
case IDM_OBJECTGETDATA_BITMAP:
SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
break;
case IDM_OBJECTGETDATA_METAFILEPICT:
SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
break;
#endif /* NOT_SIMPLE */
default:
MessageBox(0,
TEXT("Type is Unsupported in the Client"),
TEXT("GetData"),
MB_OK);
return(0);
}
m_swTimer.m_Start();
HRESULT didfail = NOERROR;
for(int i=0; i<m_cIterations; i++)
{
hr = m_pIDataObject->GetData(&fe, &m_stm);
if (SUCCEEDED(hr))
{
// If we are just whacking off for the benchmark.
// Then release all but the last one we recieve.
if(i < m_cIterations-1)
ReleaseStgMedium(&m_stm);
}
else
didfail = hr;
}
m_swTimer.m_Stop();
if (SUCCEEDED(didfail))
m_cfFormat=fe.cfFormat;
else
{
perror_OKBox(0,
TEXT("GetData Failed"),
didfail);
}
return(1); // Do redraw even if it failed (draw blank).
}
int
CAppVars::m_GetDataHere(WORD wID)
{
FORMATETC fe;
HRESULT hr;
if(NULL == m_pIDataObject)
return(0); // Don't redraw
m_cfFormat = 0;
// Don't Release the STGMedium. We recycle them!
switch(wID)
{
case IDM_OBJECTGETDATAHERE_TEXT:
SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
break;
case IDM_OBJECTGETDATAHERE_NULLTEXT:
SETDefFormatEtc(fe, CF_TEXT, TYMED_NULL);
break;
/* Other cases go here.... */
default:
MessageBox(0,
TEXT("Type is Unsupported in the Client"),
TEXT("GetDataHere"),
MB_OK);
return(0);
}
HGLOBAL* phg = &m_hgHereBuffers[m_iDataSizeIndex];
if(NULL == *phg)
{
++m_HereAllocCount;
*phg = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE,
DATASIZE_FROM_INDEX(m_iDataSizeIndex) );
if(NULL == *phg)
{
MessageBox(0,
TEXT("GlobalAlloc Return NULL"),
TEXT("Failure"),
MB_OK);
PostQuitMessage(0);
return(0); // Don't redraw
}
}
m_stm.hGlobal=*phg;
m_stm.tymed=TYMED_HGLOBAL;
m_stm.pUnkForRelease=NULL;
// The TYMED_NULL case tests code in olethk where it is written:
// "If tymed == TYMED_NULL then GetDataHere should behave like GetData."
// I can't find this in any manual (OLE2 or Ole). I wanted to see what
// good that code was. (there is also bug #15974) Aug 8th 1995 BChapman.
if (IDM_OBJECTGETDATAHERE_NULLTEXT == wID)
{
m_stm.hGlobal=NULL;
m_stm.tymed=TYMED_NULL;
}
// The other side "knows" the size of the data.
// (It is told via. SetData)
HRESULT didfail = NOERROR;
m_swTimer.m_Start();
for(int i=0; i<m_cIterations; i++)
{
hr = m_pIDataObject->GetDataHere(&fe, &m_stm);
if (FAILED(hr))
didfail = hr;
// We don't ReleaseSTGMedium because this
// is GetDataHere !
}
m_swTimer.m_Stop();
if (SUCCEEDED(didfail))
m_cfFormat=fe.cfFormat;
else
{
perror_OKBox(0,
TEXT("GetDataHere Failed"),
didfail);
}
return(1); // redraw (if FAILED(hr) then draw blank)
}
int
CAppVars::m_SetData_SetSize(long iSizeIndex)
{
FORMATETC fe;
HRESULT hr;
if (NULL == m_pIDataObject)
return 0;
SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
m_iDataSizeIndex = iSizeIndex;
HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(ULONG) );
if(NULL == hMem)
{
MessageBox(0,
TEXT("GlobalAlloc Return NULL"),
TEXT("Failure"),
MB_OK);
PostQuitMessage(0);
return 0;
}
long* pl=(long*)GlobalLock(hMem); // Lock
*((long*)pl) = DATASIZE_FROM_INDEX(m_iDataSizeIndex);
GlobalUnlock(hMem); // Unlock
m_stm.hGlobal=hMem;
m_stm.tymed=TYMED_HGLOBAL;
m_stm.pUnkForRelease=NULL;
hr = m_pIDataObject->SetData(&fe, &m_stm, FALSE); // Keep Ownership.
if (FAILED(hr))
{
perror_OKBox(0,
TEXT("SetData Failed"),
hr);
return 0;
}
return 1;;
// release the hMem HGLOBAL perhaps ???
}
int
CAppVars::m_SetData_WithPUnk(WORD wID)
{
FORMATETC fe;
HRESULT hr;
if(NULL == m_pIDataObject)
return 0;
switch(wID)
{
case IDM_OBJECTSETDATAPUNK_TEXT:
SETDefFormatEtc(fe, CF_TEXT, TYMED_HGLOBAL);
break;
/* Other cases go here.... */
default:
MessageBox(0,
TEXT("Type is Unsupported in the Client"),
TEXT("SetData"),
MB_OK);
return(0);
}
HGLOBAL hMem=GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, sizeof(ULONG) );
if(NULL == hMem)
{
MessageBox(0,
TEXT("GlobalAlloc Return NULL"),
TEXT("Failure"),
MB_OK);
PostQuitMessage(0);
return 0;
}
long* pl=(long*)GlobalLock(hMem); // Lock
*((long*)pl) = 0xffffffff; // Use
GlobalUnlock(hMem); // Unlock
m_stm.hGlobal=hMem;
m_stm.tymed=TYMED_HGLOBAL;
hr = GetStgMedpUnkForRelease(&m_stm.pUnkForRelease);
if(NOERROR != hr)
{
perror_OKBox(0, TEXT("Can't get pUnk For Release"), hr);
}
hr = m_pIDataObject->SetData(&fe, &m_stm, TRUE); // Pass Ownership.
// We passed ownership so SetData took the HGLOBAL from us.
if (FAILED(hr))
{
perror_OKBox(0,
TEXT("SetData Failed"),
hr);
return 0;
}
return 1;
}
#define NUM_RUNS 5
void
CAppVars::m_BatchToFile()
{
dataset_t dsGetDataText;
dataset_t dsGetDataHereText;
pm_ClearDataset(&dsGetDataText);
pm_ClearDataset(&dsGetDataHereText);
int iRun;
for(iRun=0; iRun < NUM_RUNS; iRun++)
{
m_MeasureAllSizes(IDM_OBJECTGETDATA_TEXT,
NULL,
&dsGetDataText);
m_MeasureAllSizes(IDM_OBJECTGETDATAHERE_TEXT,
NULL,
&dsGetDataHereText);
}
FILE *fp;
int i;
if(NULL == (fp = fopen(FILENAME, "w")))
{
MessageBox(0, TEXT("Cannot Open Output File"),
TEXT(FILENAME),
MB_OK | MB_ICONSTOP);
return;
}
fprintf(fp, " GetData w/ HGLOBAL GetDataHere w/ HGLOBAL\n");
fprintf(fp, " Size Best Worst Average Best Worst Average\n");
for (i=0; i<NUM_POINTS; i++)
{
fprintf(fp, "%5d\t", cKSizes[i]);
#define PR_TIME(fp, v) (fprintf(fp, "%3lu.%03lu\t", (v)/1000, (v)%1000))
PR_TIME(fp, dsGetDataText.cBest[i]);
PR_TIME(fp, dsGetDataText.cWorst[i]);
PR_TIME(fp, dsGetDataText.cTotal[i]/NUM_RUNS);
PR_TIME(fp, dsGetDataHereText.cBest[i]);
PR_TIME(fp, dsGetDataHereText.cWorst[i]);
PR_TIME(fp, dsGetDataHereText.cTotal[i]/NUM_RUNS);
fprintf(fp, "\n");
}
fclose(fp);
MessageBox(0, TEXT("Output Written to file.dat!"),
TEXT("Done"), MB_OK);
}
void
CAppVars::pm_ClearDataset(dataset_t *ds)
{
int i;
for(i=0; i<NUM_POINTS; i++)
{
ds->cTotal[i] = 0;
ds->cBest[i] = 0xFFFFFFFF;
ds->cWorst[i] = 0;
}
}
void
CAppVars::m_MeasureAllSizes(
WORD wID,
LPTSTR tstrTitle,
dataset_t *ds)
{
int i;
ULONG cUSecs[NUM_POINTS];
// Save some state.
ULONG iOldDataSizeIndex = m_iDataSizeIndex;
for (i=0; i<NUM_POINTS; i++)
{
m_SetData_SetSize(cKSizes[i]);
switch(wID)
{
case IDM_OBJECTGETDATA_TEXT:
case IDM_OBJECTGETDATA_BITMAP:
m_GetData(wID);
break;
case IDM_OBJECTGETDATAHERE_TEXT:
case IDM_OBJECTGETDATAHERE_BITMAP:
m_GetDataHere(wID);
break;
}
m_swTimer.m_Read(&cUSecs[i]);
cUSecs[i] /= m_cIterations;
}
// Restore save state.
m_iDataSizeIndex = iOldDataSizeIndex;
m_SetData_SetSize(m_iDataSizeIndex);
// If the caller provided memory then return the data in it.
if(NULL != ds)
{
for (i=0; i<NUM_POINTS; i++)
{
ds->cData[i] = cUSecs[i];
ds->cTotal[i] += cUSecs[i];
if(ds->cBest[i] > cUSecs[i])
ds->cBest[i] = cUSecs[i];
if( ds->cWorst[i] < cUSecs[i])
ds->cWorst[i] = cUSecs[i];
}
}
// If the caller passed a NULL Title then no message box.
if(NULL == tstrTitle)
return;
// Render Results.
LPTSTR tstr = &tcMessageBuf[0];
for (i=0; i<NUM_POINTS; i++)
{
wsprintf(tstr, TEXT("%dK: %lu.%03lu%c"),
cKSizes[i], cUSecs[i]/1000, cUSecs[i]%1000,
(i%4==3)? TEXT('\n'):TEXT('\t') );
tstr += lstrlen(tstr);
}
MessageBox(0, tcMessageBuf, tstrTitle, MB_OK);
}
void
CAppVars::m_SetMeasurement(WORD wID)
{
HMENU hMenu=GetMenu(m_hWnd);
switch (wID)
{
case IDM_MEASUREMENT_ON:
m_fDisplayTime = TRUE;
CheckMenuItem(hMenu, IDM_MEASUREMENT_ON, MF_CHECKED);
CheckMenuItem(hMenu, IDM_MEASUREMENT_OFF, MF_UNCHECKED);
break;
case IDM_MEASUREMENT_OFF:
m_fDisplayTime = FALSE;
CheckMenuItem(hMenu, IDM_MEASUREMENT_ON, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_MEASUREMENT_OFF, MF_CHECKED);
break;
case IDM_MEASUREMENT_1:
m_cIterations = 1;
goto set_menu;
case IDM_MEASUREMENT_50:
m_cIterations = 50;
goto set_menu;
case IDM_MEASUREMENT_300:
m_cIterations = 300;
goto set_menu;
set_menu:
CheckMenuItem(hMenu, IDM_MEASUREMENT_1, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_MEASUREMENT_50, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_MEASUREMENT_300, MF_UNCHECKED);
CheckMenuItem(hMenu, wID, MF_CHECKED);
break;
case IDM_MEASUREMENT_TEST:
m_swTimer.m_Start();
m_swTimer.m_Sleep(777);
m_swTimer.m_Stop();
m_DisplayTimerResults();
break;
}
}
void
CAppVars::m_DisplayTimerResults()
{
ULONG usecs;
m_swTimer.m_Read(&usecs);
usecs /= m_cIterations;
wprintf_OKBox(0, TEXT("MilliSeconds"),
TEXT("%lu.%03lu"),
usecs/1000, usecs%1000);
}
/*
* CAppVars::Paint
*
* Purpose:
* Handles WM_PAINT for the main window by drawing whatever
* data we have sitting in the STGMEDIUM at this time.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CAppVars::Paint(void)
{
PAINTSTRUCT ps;
HDC hDC;
#ifdef NOT_SIMPLE
HDC hMemDC;
LPMETAFILEPICT pMF;
#endif /* NOT_SIMPLE */
LPTSTR psz;
RECT rc;
FORMATETC fe;
GetClientRect(m_hWnd, &rc);
hDC=BeginPaint(m_hWnd, &ps);
//May need to retrieve the data with EXE objects
#ifdef NOT_SIMPLE
if (m_fEXE)
{
if (TYMED_NULL==m_stm.tymed && 0!=m_cfFormat)
{
SETDefFormatEtc(fe, m_cfFormat, TYMED_HGLOBAL
| TYMED_MFPICT | TYMED_GDI);
if (NULL!=m_pIDataObject)
m_pIDataObject->GetData(&fe, &m_stm);
}
}
#endif /* NOT_SIMPLE */
switch (m_cfFormat)
{
case CF_TEXT:
psz=(LPTSTR)GlobalLock(m_stm.hGlobal);
if (NULL==psz)
break;
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
pm_DrawText(hDC, psz, &rc, DT_LEFT | DT_WORDBREAK);
GlobalUnlock(m_stm.hGlobal);
break;
#ifdef NOT_SIMPLE
case CF_BITMAP:
hMemDC=CreateCompatibleDC(hDC);
if (NULL!=SelectObject(hMemDC, (HGDIOBJ)m_stm.hGlobal))
{
BitBlt(hDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top
, hMemDC, 0, 0, SRCCOPY);
}
DeleteDC(hMemDC);
break;
case CF_METAFILEPICT:
pMF=(LPMETAFILEPICT)GlobalLock(m_stm.hGlobal);
if (NULL==pMF)
break;
SetMapMode(hDC, pMF->mm);
SetWindowOrgEx(hDC, 0, 0, NULL);
SetWindowExtEx(hDC, pMF->xExt, pMF->yExt, NULL);
SetViewportExtEx(hDC, rc.right-rc.left
, rc.bottom-rc.top, NULL);
PlayMetaFile(hDC, pMF->hMF);
GlobalUnlock(m_stm.hGlobal);
break;
#else /* IS SIMPLE */
case CF_BITMAP:
case CF_METAFILEPICT:
DebugBreak();
break;
#endif /* NOT_SIMPLE */
default:
break;
}
EndPaint(m_hWnd, &ps);
return;
}
void
CAppVars::pm_DrawText(
HDC hDC,
LPTSTR psz,
RECT* prc,
UINT flags)
{
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
// If we are WIN32 and the server is 16 bits this must be ASCII.
#ifdef WIN32
if(m_f16Bit)
DrawTextA(hDC, (char*)psz, -1, prc, flags);
else
#endif
DrawText(hDC, psz, -1, prc, flags);
}