CEDataBase.h文件
#pragma once
//數據庫類型的枚舉值
//可以對此枚舉進行拓展,但是在響應使用的函數裏都要進行拓展
enum
{
PRO_STRING = 0x00000001, //字符串類型 TCHAR
PRO_TIME, //日期型 systime
PRO_NUMBER //整型 int
};
//////////////////////////////////////////////////////////////////
//說明 Begin:每次使用該數據庫類,只需要修改此處的數據結構
//***定義傳遞記錄的結構體***
typedef struct
{
TCHAR LinkmanName[20];
TCHAR MobilePhone1[21];
TCHAR MobilePhone2[21];
TCHAR OfficePhone[21];
TCHAR HomePhone[21];
TCHAR Company[40];
TCHAR QQ[15];
//char name[20];
}DATA_RECORD,*DATA_pRECORD;
//***數據庫屬性的總個數***
#define PROPERTY_NUM 7
//屬性類型數組
extern DWORD PROPERTY_TYPE_ID[PROPERTY_NUM];
//自定義屬性類型數組
extern DWORD PROPERTY_TYPE[PROPERTY_NUM];
//數據對象在結構體中的位置
extern int PROPERTY_POSITION[PROPERTY_NUM];
//定義數據庫文件名
#define DBFILENAME L"\\My Documents\\contact.vol"
//定義數據庫名
#define DBTABLENAME L"\\contact"
//定義聯繫人姓名字段標識,聯繫人姓名在數據庫中將是唯一型字段
#define PID_NAME MAKELONG(CEVT_LPWSTR,0)
//定義聯繫人手機號碼1字段標識
#define PID_NUMBER1 MAKELONG(CEVT_LPWSTR,1)
//定義聯繫人手機號碼2字段標識
#define PID_NUMBER2 MAKELONG(CEVT_LPWSTR,2)
//定義聯繫人辦公室電話號碼標識
#define PID_NUMBER3 MAKELONG(CEVT_LPWSTR,3)
//定義聯繫人家庭電話號碼標識
#define PID_NUMBER4 MAKELONG(CEVT_LPWSTR,4)
//定義聯繫人單位名稱標識
#define PID_COMPANYNAME MAKELONG(CEVT_LPWSTR,5)
//定義聯繫人QQ標識
#define PID_QQ MAKELONG(CEVT_LPWSTR,6)
//說明 End:每次使用該數據庫類,只需要修改此處的數據結構
//////////////////////////////////////////////////////////////////
class CEDataBase
{
//屬性
private:
CEGUID m_ceGuid; //存儲數據庫文件卷標識(GUID)PCEGUID m_pCeGuid;
CEOID m_ceOid; //DWORD型 存儲數據庫對象標識和記錄對象標識,惟一標識數據庫的ID,CeCreateDatabaseEx()返回
HANDLE m_hDB; //存儲數據庫句柄,CeOpenDatabaseEx()返回
HANDLE m_hSession; //會話句柄
public:
CString m_DataBase; //數據庫路徑及卷文件名稱
CString m_TableName; //操作的數據表名稱
//操作
public:
CEDataBase(void);
~CEDataBase(void);
public:
BOOL Open(void); //打開數據庫
BOOL Create(DWORD dwIndex); //創建數據庫
BOOL Close(void); //關閉數據庫
BOOL UnmountDBVol(void); //卸載數據庫卷,僅在打開數據庫完全失敗時使用
DWORD Seek(DWORD dwID); //移動記錄指針
int GetRecordCount(); //返回表內的記錄總數
BOOL GetRecord(DWORD dwID,DATA_RECORD *pRecord); //返回指定ID的記錄結構體指針
BOOL Add(DATA_RECORD *pRecord); //添加一條記錄
BOOL Delete(DWORD dwIndex); //刪除某條記錄
BOOL Modify(DWORD dwID,DATA_RECORD * pRecord); //修改某條記錄
};
CEDataBase.cpp文件
#include "StdAfx.h"
#include "CEDataBase.h"
//////////////////////////////////////////////////////////////////
//說明 Begin:每次使用該數據庫類,只需要修改此處的數據結構
//***屬性類型數組***
//按照結構體個數依次排列
//MAKELONG第一個參數爲其數據庫中的數據類型
// 第二個參數爲其ID,遞增即可
DWORD PROPERTY_TYPE_ID[PROPERTY_NUM] = {
MAKELONG(CEVT_LPWSTR,1),
MAKELONG(CEVT_LPWSTR,2),
MAKELONG(CEVT_LPWSTR,3),
MAKELONG(CEVT_LPWSTR,4),
MAKELONG(CEVT_LPWSTR,5),
MAKELONG(CEVT_LPWSTR,6),
MAKELONG(CEVT_LPWSTR,7)
};
//***自定義屬性類型數組***
//按照結構體個數依次排列
DWORD PROPERTY_TYPE[PROPERTY_NUM] = {
PRO_STRING,
PRO_STRING,
PRO_STRING,
PRO_STRING,
PRO_STRING,
PRO_STRING,
PRO_STRING
};
//***數據對象在結構體中的位置***
int PROPERTY_POSITION[PROPERTY_NUM] = {
0,
20,
20+20
};
//說明 End:每次使用該數據庫類,只需要修改此處的數據結構
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------
//【函數介紹】: 構造和析構函數
//
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】:
//---------------------------------------------------------------------
CEDataBase::CEDataBase(void)
{
//初始化數據庫句柄
m_hDB = 0;
//將數據庫對象標識設置0
m_ceOid = 0;
m_DataBase=_T("\\My Documents\\contact.vol"); //數據庫路徑及卷文件名稱
m_TableName=_T("\\contact"); //操作的數據表名稱
}
CEDataBase::~CEDataBase(void)
{
}
//--------------------------------------------------------------------
//【函數介紹】: UINT CEDataBase::Open(void)
// 打開數據庫,如果返回 ERROR_FILE_NOT_FOUND 表明數據庫不存在,需要Create函數
// 打開成功返回 0
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 0 爲成功,否則失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Open(void)
{
//掛載數據庫卷,如果存在則打開,不存在,就新建一個
if (!CeMountDBVol(&m_ceGuid,m_DataBase.GetBuffer(),OPEN_ALWAYS))
{
TRACE(_T("CEDataBase001:打開或新建數據卷失敗\n"));
return FALSE;
}
//接着打開數據庫
m_hDB = CeOpenDatabaseEx(&m_ceGuid,&m_ceOid,m_TableName.GetBuffer(),NULL,CEDB_AUTOINCREMENT,NULL);
if (m_hDB == INVALID_HANDLE_VALUE)
{
//如果數據庫不存在,就新建之
Create(PID_NAME);
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL CEDataBase::Create(DWORD dwIndex)
// 創建數據庫,如果打開沒有成功,則判斷返回值是否爲,是 ERROR_FILE_NOT_FOUND 則創建數據庫
//【入口參數】: dwIndex 爲Define的MAKELONG宏定義的某個屬性的DWORD值
//
//【出口參數】: (無)
//【返回 值】: TRUE爲創建成功,FALSE爲創建失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Create(DWORD dwIndex)
{
CEDBASEINFO ceDbInfo;
ceDbInfo.dwFlags = CEDB_VALIDNAME | CEDB_VALIDTYPE | CEDB_VALIDSORTSPEC;
wcscpy(ceDbInfo.szDbaseName , m_TableName.GetBuffer());
ceDbInfo.dwDbaseType = 0;
ceDbInfo.wNumSortOrder = 1; //排序索引字段數目,此處暫定爲1個索引
ceDbInfo.rgSortSpecs[0].propid = dwIndex;
ceDbInfo.rgSortSpecs[0].dwFlags = CEDB_SORT_CASEINSENSITIVE; //升序,且大小寫無關
//此處只要參數允許,最多可以設置4個索引,此處暫定爲1個索引
//ceDbInfo.rgSortSpecs[1].propid = PID_TEL;
//ceDbInfo.rgSortSpecs[1].dwFlags = CEDB_SORT_CASEINSENSITIVE; //升序,且大小寫無關
m_ceOid = CeCreateDatabaseEx(&m_ceGuid,&ceDbInfo);
if (m_ceOid == 0)
{
TRACE(_T("CEDataBase005:創建數據庫失敗\n"));
//此處得卸載數據庫卷
if (!CeUnmountDBVol(&m_ceGuid))
{
TRACE(_T("CEDataBase006:卸載數據庫文件卷失敗\n"));
return FALSE;
}
return FALSE;
}
//創建數據庫後,應緊接着打開數據庫
m_hDB = CeOpenDatabaseEx(&m_ceGuid,&m_ceOid,m_TableName.GetBuffer(),NULL,CEDB_AUTOINCREMENT,NULL);
if (m_hDB == INVALID_HANDLE_VALUE)
{
TRACE(_T("CEDataBase007:打開數據庫失敗\n"));
//此處得卸載數據庫卷
if (!CeUnmountDBVol(&m_ceGuid))
{
TRACE(_T("CEDataBase008:卸載數據庫文件卷失敗\n"));
return FALSE;
}
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL CEDataBase::Close(void)
// 關閉數據庫
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: TRUE爲創建成功,FALSE爲創建失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Close(void)
{
//1、關閉數據庫
if (!CloseHandle(m_hDB))
{
TRACE(_T("CEDataBase002:關閉數據庫失敗\n"));
return FALSE;
}
//2、將數據庫卷的數據緩衝到永久存儲介質上
if (!CeFlushDBVol(&m_ceGuid))
{
TRACE(_T("CEDataBase003:緩衝介質失敗\n"));
return FALSE;
}
//3、卸載數據庫卷
if (!CeUnmountDBVol(&m_ceGuid))
{
TRACE(_T("CEDataBase004:卸載數據庫文件卷失敗\n"));
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL CEDataBase::UnmountDBVol(void)
// 僅供數據庫文件存在,並且打開錯誤的時候卸載使用
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: TRUE爲卸載成功,FALSE爲卸載失敗
//---------------------------------------------------------------------
BOOL CEDataBase::UnmountDBVol(void)
{
//此處得卸載數據庫卷
if (!CeUnmountDBVol(&m_ceGuid))
{
TRACE(_T("CEDataBase009:卸載數據庫文件卷失敗\n"));
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: DWORD CEDataBase::Seek(DWORD dwID)
// 從開始位置移動dwID個數據指針
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 成功返回不爲零數值
//---------------------------------------------------------------------
DWORD CEDataBase::Seek(DWORD dwID)
{
CEOID ceOid;
DWORD dwIndex;
ceOid = CeSeekDatabase(m_hDB,CEDB_SEEK_BEGINNING,dwID,&dwIndex);
ASSERT(ceOid !=0);
return ceOid;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL GetRecord(DWORD dwID,DATA_RECORD * pRecord);
// 返回指定ID的記錄結構體指針
//
//【入口參數】: DWORD dwID 指定返回內容的ID
//
//【出口參數】: DATA_RECORD * pRecord 返回數據的結構體
//【返回 值】: 返回TRUE爲成功,返回FALSE爲失敗
//---------------------------------------------------------------------
BOOL CEDataBase::GetRecord(DWORD dwID,DATA_RECORD *pRecord)
{
CEOID ceOid;
WORD wProps = 0; //查詢數據庫後返回的指定表的屬性個數
DWORD dwRecSize = 0;
DWORD dwInSize = 0;
PBYTE pBuff;
PCEPROPVAL pRecordVal;
char * pRecNew = (char *)pRecord;
//移動記錄指針
ceOid = CeSeekDatabase(m_hDB,CEDB_SEEK_BEGINNING,dwID,&dwRecSize);
ASSERT(ceOid !=0);
pBuff = 0;
ceOid = CeReadRecordProps(m_hDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwInSize);
ASSERT(ceOid != 0);
pRecordVal = (PCEPROPVAL)pBuff;
for (int i=0; i<wProps; i++)
{
//查找當前屬性與之匹配的MAKELONG值在PROPERTY_TYPE_ID數組中的ID
int iPos = 9999; //默認9999爲錯誤值,即沒有找到匹配值
for(int t=0; t<wProps; t++)
{
iPos = 9999;
if(PROPERTY_TYPE_ID[t] == pRecordVal->propid)
{
iPos = t;
break;
}
}
if((iPos == 9999) || (iPos > PROPERTY_NUM) || (iPos < 0))
{
TRACE(_T("CEDataBase010:沒有找到匹配的屬性\n"));
//return FALSE;
}
else
{
//找到了匹配的屬性,並賦值給結構體
switch(PROPERTY_TYPE[iPos])
{
case PRO_STRING:
{
wcscpy((LPWSTR)(pRecNew+PROPERTY_POSITION[i]),pRecordVal->val.lpwstr);
break;
}
case PRO_TIME:
{
memcpy((void *)(pRecNew+PROPERTY_POSITION[i]),(void *)&(pRecordVal->val.filetime),sizeof(FILETIME));
//TRACE1("Sizeof DATA_RECORD = %d \n",sizeof(DATA_RECORD));
//TRACE1("Sizeof DATA_RECORD = %d \n",sizeof(pRecord->szName));
//TRACE1("Sizeof FILETIME = %d \n",sizeof(pRecord->ftBirthday));
//TRACE1("Sizeof FILETIME = %d \n",sizeof(pRecord->szTel));
break;
}
//升級備註:其他數據類型的case在此添加
}
}
pRecordVal++;
}
LocalFree(pBuff);
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: int GetRecordCount();
// 返回表內記錄的個數
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 返回表內記錄的個數
//---------------------------------------------------------------------
int CEDataBase::GetRecordCount()
{
int iCount;
CEOIDINFO oidinfo;
if (!CeOidGetInfoEx(&m_ceGuid,m_ceOid,&oidinfo))
{
TRACE(_T("CEDataBase011:獲取信息失敗\n"));
return -1;
}
iCount = oidinfo.infDatabase.wNumRecords;
return iCount;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL CEDataBase::Delete(DWORD dwIndex)
// 刪除指定ID的記錄
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 返回TRUE爲成功,返回FALSE爲失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Delete(DWORD dwIndex)
{
if(dwIndex < 0)
return FALSE;
DWORD dwRet;
CEOID ceOid;
ceOid = CeSeekDatabase(m_hDB,CEDB_SEEK_BEGINNING,dwIndex,&dwRet);
ASSERT(ceOid !=0 );
if (!CeDeleteRecord(m_hDB,ceOid))
{
TRACE(_T("CEDataBase012:數據庫刪除失敗\n"));
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL CEDataBase::Add(DATA_RECORD * pRecord)
// 添加單個聯繫人
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 返回TRUE爲成功,返回FALSE爲失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Add(DATA_RECORD *pRecord)
{
CEOID ceOid = 0;
CEPROPVAL *pRecordVal = new CEPROPVAL[PROPERTY_NUM];
//TRACE1("Sizeof CEPROPVAL = %d \n",sizeof(CEPROPVAL));
char * pRecNew = (char *)pRecord;
for(int i=0; i<PROPERTY_NUM; i++)
{
memset(pRecordVal,0,sizeof(CEPROPVAL));
pRecordVal->propid = PROPERTY_TYPE_ID[i];
switch(PROPERTY_TYPE[i])
{
case PRO_STRING:
{
pRecordVal->val.lpwstr = (wchar_t *)(pRecNew+PROPERTY_POSITION[i]);
break;
}
case PRO_TIME:
{
memcpy((void *)&(pRecordVal->val.filetime),(void *)(pRecNew+PROPERTY_POSITION[i]),sizeof(FILETIME));
break;
}
//升級備註:其他數據類型的case在此添加
}
pRecordVal++;
}
pRecordVal = pRecordVal - PROPERTY_NUM; //(PROPERTY_NUM - 1);
ceOid = CeWriteRecordProps(m_hDB,0,PROPERTY_NUM,pRecordVal);
if (ceOid == 0)
{
TRACE(_T("CEDataBase013:添加數據失敗\n"));
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------
//【函數介紹】: BOOL Modify(DWORD dwID,DATA_RECORD * pRecord)
// 編輯指定ID的數據內容
//【入口參數】: (無)
//
//【出口參數】: (無)
//【返回 值】: 返回TRUE爲成功,返回FALSE爲失敗
//---------------------------------------------------------------------
BOOL CEDataBase::Modify(DWORD dwID,DATA_RECORD * pRecord)
{
CEOID ceOid = 0;
CEPROPVAL *pRecordVal = new CEPROPVAL[PROPERTY_NUM];
WORD wProps = 0;
DWORD dwRecSize = 0;
char * pRecNew = (char *)pRecord;
///////////////////////////////////////////////////////
ceOid = CeSeekDatabase(m_hDB,CEDB_SEEK_BEGINNING,dwID,&dwRecSize);
ASSERT(ceOid !=0);
for(int i=0; i<PROPERTY_NUM; i++)
{
memset(pRecordVal,0,sizeof(CEPROPVAL));
pRecordVal->propid = PROPERTY_TYPE_ID[i];
switch(PROPERTY_TYPE[i])
{
case PRO_STRING:
{
pRecordVal->val.lpwstr = (wchar_t *)(pRecNew+PROPERTY_POSITION[i]);
break;
}
case PRO_TIME:
{
memcpy((void *)&(pRecordVal->val.filetime),(void *)(pRecNew+PROPERTY_POSITION[i]),sizeof(FILETIME));
break;
}
//升級備註:其他數據類型的case在此添加
}
pRecordVal++;
}
pRecordVal = pRecordVal - PROPERTY_NUM;
ceOid = CeWriteRecordProps(m_hDB,ceOid,PROPERTY_NUM,pRecordVal);
if (ceOid == 0)
{
TRACE(_T("CEDataBase014:修改數據失敗\n"));
return FALSE;
}
return TRUE;
}