Ado 实现C++对象的存取
作者:江上飞鸟
其实我最讨厌写东西了,最近忙死了,呵呵,前一段时间在做一个图形程序时,需要把C++对象保存到数据库里,刚开始真让我头疼啊,琢磨了一个下午,终于给做出来了,废话不说了,还是把自己的一些体会与各位同任一起分享!!!!
一、新建一个继承于 CObject 的子类 CLine;
头文件:Line.h
class CLine : public CObject?
{
private :
LOGPEN m_logPen; //画笔
COLORREF m_crBackColor;
CArray<CPoint, CPoint &> m_PointArray; //标记类对应框
public:
int GetSize();
CPoint GetPoint(int pos);
void DrawLine(CDC *pDC,CPoint pt1,CPoint pt2,CRect rc);
void DrawBackGround(CDC *pDC,CRect rect);
void DrawPoint(CDC *pDC, CRect rect);
void SetWidth(int iWidth);
COLORREF GetColor();
void SetColor(COLORREF color);
COLORREF GetBkColor();
void SetBkColor(COLORREF color);
void AddPoint(CPoint point);
void Clear();
CLine();
virtual ~CLine();
virtual void Serialize(CArchive &ar);
CLine& operator=(CLine &src);
DECLARE_SERIAL(CLine)??
};
实现文件:Line.cpp
//////////////////////////////////////////////////////////////////////
// Line.cpp: implementation of the CLine class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TestAdo.h"
#include "Line.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
IMPLEMENT_SERIAL(CLine,CObject,1)
CLine::CLine()
{
Clear();
}
CLine::~CLine()
{
}
//重写 =
CLine& CLine::operator=(CLine &src)
{
if(this!=&src)
{
m_logPen = src.m_logPen;
m_crBackColor = src.m_crBackColor;
}
return *this;?
}
//串行化操作
void CLine::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << DWORD(m_crBackColor);
ar.Write(&m_logPen, sizeof(LOGPEN));
}
else
{
DWORD dw;
ar >> dw; m_crBackColor = COLORREF(dw);
ar.Read(&m_logPen, sizeof(LOGPEN));
}
m_PointArray.Serialize(ar);
}
void CLine::Clear()
{
m_crBackColor = RGB(255,255,255);
m_logPen.lopnStyle = PS_SOLID;
m_logPen.lopnWidth.x = 1;
m_logPen.lopnWidth.y = 1;
m_logPen.lopnColor = RGB(0, 0, 0);
m_PointArray.RemoveAll();
}
void CLine::AddPoint(CPoint point)
{
m_PointArray.Add(point);
}
void CLine::SetColor(COLORREF color)
{
m_logPen.lopnColor = color;
}
COLORREF CLine::GetColor()
{
return m_logPen.lopnColor;
}
void CLine::SetBkColor(COLORREF color)
{
m_crBackColor = color;
}
COLORREF CLine::GetBkColor()
{
return m_crBackColor;
}
void CLine::SetWidth(int iWidth)
{
m_logPen.lopnWidth.x = iWidth;
m_logPen.lopnWidth.y = iWidth;
}
//绘线条
void CLine::DrawPoint(CDC *pDC, CRect rect)
{
int len = m_PointArray.GetSize();
if (len <=0) return;
CPen pen;
pen.CreatePenIndirect(&m_logPen);
CPen *pOldPen = pDC->SelectObject(&pen);
CPoint pt = m_PointArray.GetAt(0);
pDC->MoveTo(pt);
for (int i=1; i< len; i++)
{
pt = m_PointArray.GetAt(i);
pDC->LineTo(pt);
}
pDC->SelectObject(pOldPen);
pOldPen = NULL;
pen.DeleteObject();
}
void CLine::DrawBackGround(CDC *pDC, CRect rect)
{
CBrush brushCtl;
brushCtl.CreateSolidBrush(GetBkColor());
pDC->Rectangle(rect);
pDC->FillRect(rect,&brushCtl) ;
brushCtl.DeleteObject();
}
void CLine::DrawLine(CDC *pDC,CPoint pt1, CPoint pt2, CRect rc)
{
CPen pen;
pen.CreatePenIndirect(&m_logPen);
CPen *pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(pt1);
pDC->LineTo(pt2);
pDC->SelectObject(pOldPen);
pOldPen = NULL;
pen.DeleteObject();
}
CPoint CLine::GetPoint(int pos)
{
if (pos>=0 && pos<m_PointArray.GetSize())?
{
return m_PointArray.GetAt(pos);
}
return CPoint(0,0);
}
int CLine::GetSize()
{
return m_PointArray.GetSize();
}
二、用Ado接口打开数据库
BOOL CTestAdoDlg::OpenDb(CString filename)
{
HRESULT hr=S_OK;
hr=m_pCon.CreateInstance("ADODB.Connection");
if (hr!=S_OK)
{
return FALSE;
}
try
{
_bstr_t sCon;
sCon=_bstr_t(filename); //路径名
sCon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+sCon;
hr=m_pCon->Open(sCon,"","",adModeUnknown);
if (hr!=S_OK)
{
return FALSE;
}
///////////////////////
hr=m_pSet.CreateInstance("ADODB.Recordset");
if (hr!=S_OK)
{
return FALSE;
}
m_pSet->CursorLocation=adUseClient;
hr=m_pSet->Open("SELECT * FROM object_table",_variant_t((IDispatch*)m_pCon,TRUE),
adOpenStatic,adLockOptimistic,adCmdText);
if (hr!=S_OK)
{
return FALSE;
}
return TRUE;
///////////////////////
}
catch(_com_error &e)
{
CString errorMessage;
errorMessage.Format("连接数据库失败!错误信息:%s",e.ErrorMessage());
return FALSE;
}
return FALSE;
}
(注意:在StdAfx.h中要加入:#import "C:\Program Files\Common Files\SYSTEM\ADO\msado15.dll" no_namespace rename("EOF","adoEOF")
来引入ado库,还有在 BOOL CTestAdoApp::InitInstance() 加入 AfxOleInit();///初始化COM库)
三、CLine对象的保存
void CTestAdoDlg::OnButtonSave()
{
//m_List
if (!m_bState) return;
UpdateData();
try
{
m_pSet->AddNew();
m_pSet->PutCollect("name", _variant_t(m_sName));
//保存图形对象
CMemFile memFile;
CArchive ar(&memFile, CArchive::store);
m_Line.Serialize(ar);
ar.Close();
DWORD dwSize = memFile.GetLength();
LPBYTE lpInfo = memFile.Detach();
VARIANT varBLOB;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = dwSize;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < (long)dwSize; i++)
{
SafeArrayPutElement (psa, &i, lpInfo++);
}
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
m_pSet->GetFields()->GetItem("object")->AppendChunk(varBLOB);
m_pSet->Update();
m_List.AddString(m_sName);
}
catch(_com_error &e)
{
CString str=(char *)e.Description();
MessageBox(str+"\r保存数据库出问题!","提示",MB_OK|MB_ICONWARNING);
return ;
}
}
四、CLine对象的读取
void CTestAdoDlg::OnSelchangeListData()
{
int iPos = m_List.GetCurSel();
if (iPos<0) return ;
m_pSet->MoveFirst();
int i=0;
while (i< iPos)
{
m_pSet->MoveNext();
i++;
}
long lDataSize = m_pSet->GetFields()->GetItem(_variant_t("object"))->ActualSize;
if(lDataSize <= 0) return;
_variant_t varBLOB;
VariantInit (&varBLOB);
varBLOB = m_pSet->GetFields()->GetItem(_variant_t("object"))->GetChunk(lDataSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
BYTE *pBuf = new BYTE[lDataSize + 1];
if(pBuf)
{
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
SafeArrayUnaccessData (varBLOB.parray);
CMemFile memfile;
memfile.Attach(pBuf,lDataSize);
memfile.SeekToBegin();
CArchive ar(&memfile, CArchive::load);
m_Line.Serialize(ar);
ar.Close();
memfile.Detach();
CRect rc = GetRect(IDC_STATIC_RECT);
InvalidateRect(rc);
}
}
VariantClear (&varBLOB);
}
五、结束语
以上充分利用了串行化来实现c++对象保存到数据库,对以上方法稍做扩展对图象的保存到数据库,甚至多个图象文件保存到数据库和文件。
(很抱歉:我实在不想写文字说明了,如果有什么问题不清楚,跟我联系好了!!哎)
QQ:36201365
e-mail:ldh5118@sohu.com