前一段时间在做一个图形程序时,需要把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++对象保存到数据库,对以上方法稍做扩展对图象的保存到数据库,甚至多个图象文件保存到数据库和文件。