F-Binding

还好多不完善的地方啊。好累,连写带超。明天好好分析

函数DispalyRow();

#include <tchar.h>
#include <windows.h>
#include <strsafe.h>

#define COM_NO_WINDOWS_H    //如果已经包含了Windows.h或不使用其他Windows库函数时
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0260		//为了ICommandStream接口定义为2.6版
#include <oledb.h>
#include <oledberr.h>
#include <msdasc.h>

#define GRS_ALLOC(sz)		HeapAlloc(GetProcessHeap(),0,sz)
#define GRS_CALLOC(sz)		HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz)
#define GRS_SAFEFREE(p)		if(NULL != p){HeapFree(GetProcessHeap(),0,p);p=NULL;}

#define GRS_USEPRINTF() TCHAR pBuf[1024] = {}
#define GRS_PRINTF(...) \
	StringCchPrintf(pBuf,1024,__VA_ARGS__);\
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),pBuf,lstrlen(pBuf),NULL,NULL);

#define GRS_SAFERELEASE(I) if(NULL != I){I->Release();I=NULL;}
#define GRS_COM_CHECK(hr,...) if(FAILED(hr)){GRS_PRINTF(__VA_ARGS__);goto CLEAR_UP;}


#define GRS_DEF_INTERFACE(i) i* p##i = NULL;
#define GRS_QUERYINTERFACE(i,iid) \
	if(FAILED(hr = i->QueryInterface(IID_##iid, (void **)&p##iid)) )\
	{\
	GRS_PRINTF(_T("不支持'%s'接口\n"),_T(#iid));\
	}\
	else\
	{\
	GRS_PRINTF(_T("支持'%s'接口\n"),_T(#iid));\
	}\
	GRS_SAFERELEASE(p##iid);

#define GRS_ROUNDUP_AMOUNT 8 
#define GRS_ROUNDUP_(size,amount) (((ULONG)(size)+((amount)-1))&~((amount)-1)) 
#define GRS_ROUNDUP(size) GRS_ROUNDUP_(size, GRS_ROUNDUP_AMOUNT) 

#define MAX_DISPLAY_SIZE	30
#define MIN_DISPLAY_SIZE    3


BOOL CreateDBSession(IOpenRowset*&pIOpenRowset);

VOID UpdateDisplaySize (DBCOUNTITEM   cBindings,
	DBBINDING *   rgBindings,
	void *        pData,
	ULONG *       rgDispSize );

VOID DisplayColumnNames(DBORDINAL        cColumns,
	DBCOLUMNINFO*   rgColumnInfo,
	ULONG*          rgDispSize );

HRESULT DisplayRow(DBCOUNTITEM iRow,
	DBCOUNTITEM cBindings,
	DBBINDING * rgBindings,
	void * pData,
	ULONG * rgDispSize );



int _tmain()
{
	GRS_USEPRINTF();
	CoInitialize(NULL);
	HRESULT hr=S_OK;
	IOpenRowset* pIOpenRowset=NULL;
	IDBCreateCommand* pIDBCreateCommand=NULL;

	ICommand* pICommand=NULL;
	ICommandText* pICommandText=NULL;
	ICommandProperties* pICommandProperties=NULL;
	GRS_DEF_INTERFACE(IAccessor);//相当于定义了指针pIAccessor 即:QueryInterface(IID_IAccessor, (void **)&pIAccessor)) )
	GRS_DEF_INTERFACE(IColumnsInfo);//定义:pIColumnsInfo
	GRS_DEF_INTERFACE(IRowset);//定义:pIRowset
	GRS_DEF_INTERFACE(IRowsetChange);//定义 pIRowsetChange

	TCHAR* pSQL=_T("select * from student");
	DBPROPSET ps[1]={};
	DBPROP prop[2]={};

	ULONG cColumns;
	DBCOLUMNINFO* rgColumnInfo=NULL;
	LPWSTR pStringBuffer=NULL;
	ULONG iCol=0;
	ULONG dwOffset=0;
	DBBINDING* rgBindings=NULL;
	HACCESSOR hAccessor=NULL;
	void* pData=NULL;
	ULONG  cRowsObtained=0;
	HROW* rghRows=NULL;
	ULONG iRow=0;
	ULONG lAllRows=0;
	LONG cRows=10;
	void* pCurData=NULL;

	ULONG* plDisplayLen=NULL;
	BOOL bShowColumnName=FALSE;

	if (!CreateDBSession(pIOpenRowset))
	{
		_tsystem(_T("PAUSE"));
		return -1;
	}

	hr=pIOpenRowset->QueryInterface(IID_IDBCreateCommand,(void**)&pIDBCreateCommand);
	GRS_COM_CHECK(hr,_T("获取IDBCreateCommand接口失败。"));
	hr=pIDBCreateCommand->CreateCommand(NULL,IID_ICommand,(IUnknown**)&pICommand);
	GRS_COM_CHECK(hr,_T("创建ICommand接口失败。"));

	//执行一个命令
	hr=pICommand->QueryInterface(IID_ICommandText,(void**)&pICommandText);
	GRS_COM_CHECK(hr,_T("获取ICommandText接口失败."));
	hr=pICommandText->SetCommandText(DBGUID_DEFAULT,pSQL);
	GRS_COM_CHECK(hr,_T("设置SQL语句失败。"));

	//设置属性
	prop[0].dwPropertyID=DBPROP_UPDATABILITY;
	prop[0].vValue.vt=VT_I4;
	//设置执行后的结果集可以进行增删改操作
	prop[0].vValue.lVal=DBPROPVAL_UP_CHANGE//打开Update属性
		|DBPROPVAL_UP_DELETE
		|DBPROPVAL_UP_INSERT;
	prop[0].dwOptions=DBPROPOPTIONS_REQUIRED;
	prop[0].colid=DB_NULLID;

	ps[0].guidPropertySet=DBPROPSET_ROWSET;
	ps[0].cProperties=1;
	ps[0].rgProperties=prop;


	//设置属性  执行语句 获得行集 
	hr=pICommandText->QueryInterface(IID_ICommandProperties,(void**)&pICommandProperties);
	GRS_COM_CHECK(hr,_T("获得ICommandProperties接口失败。"));
	hr=pICommandProperties->SetProperties(1,ps);
	GRS_COM_CHECK(hr,_T("设置Command对象属性失败"));
	hr=pICommandText->Execute(NULL,IID_IRowsetChange,NULL,NULL,(IUnknown**)&pIRowsetChange);
	GRS_COM_CHECK(hr,_T("执行SQL语句失败"));

	//准备绑定信息
	hr=pIRowsetChange->QueryInterface(IID_IColumnsInfo,(void**)&pIColumnsInfo);
	GRS_COM_CHECK(hr,_T("获得IColumnsInfo接口失败"));
	hr=pIColumnsInfo->GetColumnInfo(&cColumns,&rgColumnInfo,&pStringBuffer);
	GRS_COM_CHECK(hr,_T("获得列信息失败"));

	//分配绑定结构数组的内存
	rgBindings=(DBBINDING*)GRS_CALLOC(cColumns*sizeof(DBBINDING));
	//根据列信息 填充绑定结构信息数组 注意行大小进行8字节边界对齐排列
	for (iCol=0;iCol<cColumns;iCol++)
	{
		rgBindings[iCol].iOrdinal=rgColumnInfo[iCol].iOrdinal;
		rgBindings[iCol].dwPart=DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;
		rgBindings[iCol].obStatus=dwOffset;
		rgBindings[iCol].obLength=dwOffset+sizeof(DBSTATUS);
		rgBindings[iCol].obValue=dwOffset+sizeof(DBSTATUS)+sizeof(ULONG);
		rgBindings[iCol].dwMemOwner=DBMEMOWNER_CLIENTOWNED;
		rgBindings[iCol].eParamIO=DBPARAMIO_NOTPARAM;
		rgBindings[iCol].bPrecision=rgColumnInfo[iCol].bPrecision;
		rgBindings[iCol].bScale=rgColumnInfo[iCol].bScale;
		rgBindings[iCol].wType=DBTYPE_WSTR;
		rgBindings[iCol].cbMaxLen=rgColumnInfo[iCol].ulColumnSize*sizeof(WCHAR);

		dwOffset=rgBindings[iCol].cbMaxLen+rgBindings[iCol].obValue;
		dwOffset=GRS_ROUNDUP(dwOffset);
	}
	plDisplayLen=(ULONG*)GRS_CALLOC(cColumns*sizeof(ULONG));
	//创建行访问器
	hr=pIRowsetChange->QueryInterface(IID_IAccessor,(void**)&pIAccessor);
	GRS_COM_CHECK(hr,_T("获得IAccessor接口失败"));
	hr=pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,cColumns,rgBindings,0,&hAccessor,NULL);
	GRS_COM_CHECK(hr,_T("创建行访问器失败"));

	//获取数据
	hr=pIRowsetChange->QueryInterface(IID_IRowset,(void**)&pIRowset);
	GRS_COM_CHECK(hr,_T("获得IRowset接口失败"));
	//分配cRows行数据的缓冲,然后反复读取cRows行到这里,然后逐行处理
	pData=GRS_CALLOC(dwOffset* cRows);
	lAllRows=0;
	while (S_OK==pIRowset->GetNextRows(DB_NULL_HCHAPTER,0,cRows,&cRowsObtained,&rghRows) )
	{
		//循环读取数据,每次循环默认读取cRows行,实际读取到cRowsObtained行
		//每次新现实一批数据时都要先清0一下宽度数组
		ZeroMemory(plDisplayLen,cColumns*sizeof(ULONG));
		for (iRow=0;iRow<cRowsObtained;iRow++)
		{
			//计算每列最大的显示宽度
			pCurData=(BYTE*)pData+(dwOffset*iRow);
			pIRowset->GetData(rghRows[iRow],hAccessor,pCurData);
			UpdateDisplaySize(cColumns,rgBindings,pCurData,plDisplayLen);
		}
		if (!bShowColumnName)
		{//显示字段信息
			DisplayColumnNames(cColumns,rgColumnInfo,plDisplayLen);
			bShowColumnName=TRUE;
		}

		for (iRow=0;iRow<cRowsObtained;iRow++)
		{//显示数据
			pCurData=(BYTE*)pData+(dwOffset*iRow);
			DisplayRow(++lAllRows,cColumns,rgBindings,pCurData,plDisplayLen);
		}

		if (cRowsObtained)
		{
			//释放行句柄数组
			pIRowset->ReleaseRows(cRowsObtained,rghRows,NULL,NULL,NULL);
		}
		bShowColumnName=FALSE;
		CoTaskMemFree(rghRows);
		rghRows=NULL;
	}



CLEAR_UP:
	;

}

BOOL CreateDBSession(IOpenRowset* &pIOpenRowset)
{
	GRS_USEPRINTF();
	GRS_SAFERELEASE(pIOpenRowset);

	IDBPromptInitialize* pIDBPromtInitialize=NULL;
	IDBInitialize* pDBConnet=NULL;
	IDBCreateSession* pIDBCreateSession=NULL;


	HWND hWndParent=GetDesktopWindow();
	CLSID clsid={};
	//使用oledb 数据库连接对话框链接到数据源
	HRESULT hr=CoCreateInstance(CLSID_DataLinks,NULL,CLSCTX_INPROC_SERVER,
		IID_IDBPromptInitialize,(void**)&pIDBPromtInitialize);
	if (FAILED(hr))
	{
		GRS_PRINTF(_T("无法创建IDBPromptInitialize接口"),hr);
		GRS_SAFERELEASE(pDBConnet);
		GRS_SAFERELEASE(pIDBPromtInitialize);
		return FALSE;
	}

	//下面的将弹出数据库连接对话框
	hr=pIDBPromtInitialize->PromptDataSource(
		NULL,
		hWndParent,
		DBPROMPTOPTIONS_PROPERTYSHEET,
		0,
		NULL,
		NULL,
		IID_IDBInitialize,
		(IUnknown**)&pDBConnet);
	if (FAILED(hr))
	{
		GRS_PRINTF(_T("无法创建IDBPromptInitialize接口"),hr);
		GRS_SAFERELEASE(pDBConnet);
		GRS_SAFERELEASE(pIDBPromtInitialize);
		return FALSE;
	}
	GRS_SAFERELEASE(pIDBPromtInitialize);


	hr=pDBConnet->Initialize();//根据对话框采集到的参数链接到指定的数据库
	if (FAILED(hr))
	{
		GRS_PRINTF(_T("初始化数据源连接错误"));
		GRS_SAFERELEASE(pDBConnet);
		return FALSE;
	}

	if (FAILED(hr=pDBConnet->QueryInterface(IID_IDBCreateSession,(void**)&pIDBCreateSession)))
	{
		GRS_PRINTF(_T("获取IDBCreateSession接口失败"));
		GRS_SAFERELEASE(pIDBCreateSession);
		GRS_SAFERELEASE(pDBConnet);
		return FALSE;
	}
	GRS_SAFERELEASE(pDBConnet);

	hr=pIDBCreateSession->CreateSession(
		NULL,
		IID_IOpenRowset,
		(IUnknown**)&pIOpenRowset);
	if (FAILED(hr))
	{
		GRS_PRINTF(_T("创建Session对象获取IOpenRowset接口失败"));
		GRS_SAFERELEASE(pIDBCreateSession);
		GRS_SAFERELEASE(pIOpenRowset);
		return FALSE;
	}
	GRS_SAFERELEASE(pIDBCreateSession);
	GRS_SAFERELEASE(pDBConnet);
	return TRUE;
}

VOID UpdateDisplaySize(DBCOUNTITEM cBindings, 
	DBBINDING * rgBindings,
	void * pData, 
	ULONG * rgDispSize )
{

	DBSTATUS dwStatus;
	ULONG cchLength;
	DBCOUNTITEM iCol;

	for (iCol=0;iCol<cBindings;iCol++)
	{
		dwStatus=*(DBSTATUS*)((BYTE*)pData+rgBindings[iCol].obStatus);
		cchLength=((*(ULONG*)((BYTE*)pData+rgBindings[iCol].obLength))/sizeof(WCHAR));
		switch (dwStatus)
		{
		case DBSTATUS_S_ISNULL:
				cchLength=6;
				break;
		case DBSTATUS_S_TRUNCATED:
		case DBSTATUS_S_OK:
		case DBSTATUS_S_DEFAULT:
			if (rgBindings[iCol].wType==DBTYPE_IUNKNOWN)
				cchLength=2+8;
			cchLength=max(cchLength,MIN_DISPLAY_SIZE);
			break;
		default:
			cchLength=14;
			break;
		}

		if(rgDispSize[iCol]<cchLength)
			rgDispSize[iCol]=cchLength;
	}
}

VOID DisplayColumnNames(DBORDINAL cColumns, 
	DBCOLUMNINFO* rgColumnInfo,
	ULONG* rgDispSize )
{
	GRS_USEPRINTF();
	WCHAR wszColumn[MAX_DISPLAY_SIZE+1];
	LPWSTR pwszColName;
	DBORDINAL iCol;
	ULONG cSpaces;
	ULONG iSpace;
	size_t  szlen;
	//display the title of the row index column
	//显示行索引列的标题
	GRS_PRINTF(_T("Row        |"));
	for (iCol=0;iCol<cColumns;iCol++)
	{
		pwszColName=rgColumnInfo[iCol].pwszName;
		if (!pwszColName)
		{
			if (!rgColumnInfo[iCol].iOrdinal)
			{
				pwszColName=_T("Bmk");
			}
			else
				pwszColName=_T("(null)");
		}

		StringCchCopy(wszColumn,MAX_DISPLAY_SIZE+1,pwszColName);
		StringCchLength(wszColumn,MAX_DISPLAY_SIZE+1,&szlen);
		rgDispSize[iCol]=max(min(rgDispSize[iCol],MAX_DISPLAY_SIZE+1),szlen);
		cSpaces=rgDispSize[iCol]-szlen;

		GRS_PRINTF(_T("%s"),wszColumn);
		for (iSpace=0;iSpace<cSpaces;iSpace++)
		{
			GRS_PRINTF(_T("  "));
		}
		if (iCol<cColumns-1)
		{
			GRS_PRINTF(_T("     |       "));
		}
	}

	GRS_PRINTF(_T("\n"));
}

HRESULT DisplayRow(DBCOUNTITEM iRow,
	DBCOUNTITEM cBindings,
	DBBINDING * rgBindings,
	void * pData,
	ULONG * rgDispSize )
{
	GRS_USEPRINTF();
	HRESULT   hr=S_OK;
	WCHAR  wszColumn[MAX_DISPLAY_SIZE+1];
	DBSTATUS dwStatus;
	DBLENGTH ulLength;
	void* pvValue;
	DBCOUNTITEM iCol;
	ULONG cbRead;
	ISequentialStream* pIseqStream=NULL;
	ULONG cSpaces;
	ULONG iSapce;
	size_t szLen;

	GRS_PRINTF(_T("[%8d]|"),iRow);
	for (iCol=0;iCol<cBindings;iCol++)
	{
		dwStatus=*(DBSTATUS*)((BYTE*)pData+rgBindings[iCol].obStatus);
		ulLength=*(DBLENGTH*)((BYTE*)pData+rgBindings[iCol].obLength);
		pvValue=(BYTE*)pData+rgBindings[iCol].obValue;

		switch (dwStatus)
		{
		case DBSTATUS_S_ISNULL:
			StringCchCopy(wszColumn,MAX_DISPLAY_SIZE+1,L"(null)");
			break;
		case DBSTATUS_S_TRUNCATED:
		case DBSTATUS_S_OK:
		case DBSTATUS_S_DEFAULT:
			{
				switch(rgBindings[iCol].wType)
				{
				case DBTYPE_WSTR:
					{
						StringCchCopy(wszColumn,MAX_DISPLAY_SIZE+1,(WCHAR*)pvValue);
						break;
					}
				case DBTYPE_IUNKNOWN:
					{
						pIseqStream=*(ISequentialStream**)pvValue;
						hr=pIseqStream->Read(
							wszColumn,
							MAX_DISPLAY_SIZE,
							&cbRead);
						wszColumn[cbRead/sizeof(WCHAR)]=L'\0';
						pIseqStream->Release();
						pIseqStream=NULL;
						break;
					}
				}

				break;

			}
		default:
			StringCchCopy(wszColumn,MAX_DISPLAY_SIZE+1,_T("(error status)"));
			break;
		}
		StringCchLength(wszColumn,MAX_DISPLAY_SIZE+1,&szLen);
		cSpaces=min(rgDispSize[iCol],MAX_DISPLAY_SIZE+1)-szLen;

		GRS_PRINTF(_T("%s"),wszColumn);
	}

	GRS_SAFERELEASE(pIseqStream);
	GRS_PRINTF(_T("\n"));
	return hr;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值