1261 lines
31 KiB
C++
1261 lines
31 KiB
C++
/*
|
||
* 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 : kraigb@microsoft.com
|
||
* Compuserve: >INTERNET:kraigb@microsoft.com
|
||
*/
|
||
|
||
|
||
#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);
|
||
}
|
||
|