三、编写工程代码
10. 编写CMemberSystemView类的处理函数
CMemberSystemView类的处理函数在MemberSystemView.h文件里有如下的声明:
private:
BOOL OpenCurRecordset(CString strTableName);
BOOL RefreshColumn(ULONG *pulColCount);
BOOL RefreshData(ULONG ulColCount);
BOOL GetInfoArray(CString strTableName, CUIntArray
&uaID,CStringArray &saArray);
BOOL InsertRow(CString strTableName, CStringArray
&saValues);
BOOL DeleteRow(CString strTableName, CString strColName,CString
strValue);
CString VariantToCtring(VARIANT var);
BOOL ConstructVar(CString strValue, int type, VARIANT *var);
下面分别介绍这些函数的功能和实现过程。
(1)
函数OpenCurRecordset
函数OpenCurRecordset用于将特定的表打开,结果集存放在_RecordsetPtr对象里,参数strTableName表示表的名称。
函数在打开结果集的时候使用的是m_recordset对象的Open方法,参数表明采用了adOpenDynamic、adLockOptimistic和adCmdText模式。
OpenCurRecordset函数的实现代码如下:
//OpenCurRecordset:特定表的打开,结果集存放在_RecordsetPtr所指的对象里
//参数(Sql):查询语句
//返回值:Bool型,用来表示打开成功与否
BOOL
CMemberSystemView::OpenCurRecordset(CString strTableName)
{
// 有效性检验
if(!m_fConnected)
return FALSE;
if(strTableName.IsEmpty())
return FALSE;
HRESULT hr;
// 构造查询语句(OpenCurRecordset函数也可以直接以sql语句为参数,以支持复杂查询)
CString strQuery;
strQuery.Format("select * from %s", strTableName);
//_bstr_t
query = Sql;
//用户使用的SQL语句(CString参数)
_bstr_t query = strQuery;
_bstr_t source = m_strSource;
try{
//不能打开已打开的记录集,否则报“Unknown Error 0x800A0E79”错误
if(m_recordset->State == adStateOpen)
m_recordset->Close();//adStateClosed
//或者使用 if (m_recordset->State
)
m_recordset->Close();
hr = m_recordset->Open(query, source,
adOpenDynamic,adLockOptimistic, adCmdText);
}
catch (_com_error &e){
CString errormessage;
errormessage.Format("打开记录集失败!\r\n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);//或MessageBox,显示错误信息,测试错误出在那个函数中
return FALSE;
}
return (SUCCEEDED(hr));
}
(2)
函数RefreshColumn
RefreshColumn函数通过m_recordset对象的get_Fields方法取得对象的列集,从该列集里得到结果集的列信息,并插入到界面中列表视图的列里。
RefreshColumn函数的代码如下:
BOOL
CMemberSystemView::RefreshColumn(ULONG *pulColCount)
{
// 有效性检验
if(!m_fConnected)
return FALSE;
HRESULT hr;
CListCtrl &listCtrl = GetListCtrl();
listCtrl.DeleteAllItems();//首先清空列表控件原有的内容
//DWORD exstyle =
listCtrl.GetExtendedStyle();
//listCtrl.SetExtendedStyle(exstyle|LVS_EX_FULLROWSELECT |
LVS_EX_GRIDLINES
| LVS_EX_CHECKBOXES | WS_EX_STATICEDGE);
listCtrl.ModifyStyle(0,LVS_REPORT|LVS_SHOWSELALWAYS);//|LVS_SORTASCENDING使显示不正常
listCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_GRIDLINES
|LVS_EX_FULLROWSELECT);
CString
strColName;//保存列名
Fields* fields = NULL;//保存记录集中的所有Field
try{
// 取结果集的列集
hr =
m_recordset->get_Fields(&fields);
if (SUCCEEDED(hr))
hr = fields->get_Count((long
*)pulColCount);//获取列数
//-把列名在List控件中显示-//
int index;
for(long i=0;i<*pulColCount;i++)
{
BSTR bstrColName;
hr =
fields->Item[i]->get_Name(&bstrColName);
strColName = bstrColName;
// 插入列表视图的列
int nWidth = listCtrl.GetStringWidth(strColName) + 25;
index = listCtrl.InsertColumn(i, strColName, LVCFMT_LEFT,
nWidth);
}
// 释放列集
if (SUCCEEDED(hr))
fields->Release();
}
catch (_com_error &e)
{
MessageBox("RefreshColumn
error");//测试错误出在那个函数中
MessageBox(e.ErrorMessage());
return FALSE;
}
return (SUCCEEDED(hr));
}
(3)
函数RefreshData
RefreshData函数通过调用m_recordset对象的get_adoEOF方法获知当前的结果集光标的位置是否在结果集末尾,使用
get_Item方法取得一个field对象,该对象里存放了列的数据类型和数据,我们可以通过get_Value方法取得它的值,使用
VariantToCtring函数将这个VARIANT类型的值转换成CString类型的值,VariantToCtring函数我们还要在后面介
绍,函数最后调用m_recordset对象的Close方法关闭结果集。
RefreshData函数的实现代码如下:
BOOL
CMemberSystemView::RefreshData(ULONG ulColCount)
{
// 有效性检验
if(!m_fConnected)
return FALSE;
if(0 == ulColCount)
return FALSE;
//- 变量定义 -//
HRESULT hr;
CListCtrl &listCtrl = GetListCtrl();//获取视图控件
CString strValue;
VARIANT var_value;
VARIANT_BOOL ValEof;//是否还有记录
int nRowCount = 0;
Field *field = NULL;
VARIANT varCounter;
varCounter.vt = VT_I4;//有关VARIANT类型的说明请见MSDN的CComVariant
varCounter.lVal = 0;
try{
// 取当前光标位置是否在结果集末尾
ValEof =
m_recordset->get_adoEOF(&ValEof);
//hr =
m_recordset->get_adoEOF(&ValEof);该代码作用与上相同
while(TRUE){
if(ValEof) break;
varCounter.lVal = 0;
// 取一个列对象
m_recordset->Fields->get_Item(varCounter,
&field);
//DataTypeEnum
data_type;
field->get_Value(&var_value);//
取列对象的值
// 转换成字符类型
strValue = VariantToCtring(var_value);
// 插入到界面列表视图里
listCtrl.InsertItem(nRowCount, strValue);
//int
Colcount = (int)ulColCount;
//for (long i = 1; i < Colcount; i++)
for(int i=1;i<ulColCount;i++){
varCounter.lVal = i;
m_recordset->Fields->get_Item(varCounter,
&field);
field->get_Value(&var_value);
strValue = VariantToCtring(var_value);
listCtrl.SetItemText(nRowCount, i, strValue);
}
nRowCount ++;
m_recordset->MoveNext();
m_recordset->get_adoEOF(&ValEof);
}
// 关闭结果集
m_recordset->Close();
}
catch (_com_error &e){
MessageBox("RefreshData
error");//测试错误出在那个函数中
MessageBox(e.ErrorMessage());
return FALSE;
}
return (SUCCEEDED(hr));
}
(4)
函数GetInfoArray
GetInfoArray函数实现了从特定表的特定列里得到需要的信息,参数strTableName为输入的表的名称,参数uaID为输出的关键字列里的ID,参数saArray为输出列的名称。
GetInfoArray函数的实现代码如下:
BOOL
CMemberSystemView::GetInfoArray(CString strTableName,CUIntArray
&uaID,
CStringArray &saArray)
{
// 有效性检验
if(!m_fConnected)
return FALSE;
HRESULT hr;
CString strQuery;
CString strValue;
VARIANT var_value;
VARIANT_BOOL ValEof;
int nRowCount = 0;
Field *field = NULL;
_variant_t var_t;
_bstr_t bst_t;
VARIANT varCounter;
varCounter.vt = VT_I4;
varCounter.lVal = 0;
// 建立查询字符串
strQuery.Format("select * from %s", strTableName);
_bstr_t query = strQuery;
_bstr_t source = m_strSource;
try{
// 打开结果集
hr = m_recordset->Open(query, source,
adOpenDynamic,adLockOptimistic, adCmdText);
ValEof =
m_recordset->get_adoEOF(&ValEof);
while(TRUE){
if(ValEof) break;
varCounter.lVal = 0;
// 读取字段内容,第1个字段为整型的行标识,如社团ID,第2个字段为社团名等字串