我用MFC做了一个画曲线的ACTIVEX控件,在一个控件里最多可以添加四条曲线,其中每天曲线我用一个类来封装,在控件类中定义了一个该曲线类的类模板,添加曲线的功能是在自己定义的属性页中,也就是说我自己定义的控件属性页面不仅仅有曲线的相关属性如颜色名称等,还可以通过属性页面动态的去调用控件的添加属性的方法,可是我把这个控件用到一个DIALOG的MFC程序中在设计这个控件的时候什么属性都设置好了,曲线也出来了,可是运行后设计阶段所设置的曲线都没有了,也就是相关属性没有永久存储住,我想在设计阶段就把控件设计好,运行后不需要干预,如果解决,望高手指点!!!急!!
查看一下MSDN上的Persistence相关内容
我要说的是我不仅仅有属性还有方法,我在属性页里有个添加曲线的方法,我怎么去保存我每天曲线的数据呢,即使单条曲线数据保存下来了,后来画的时候怎么区分,因为我的每条曲线是放在曲线类中,而总体的曲线是在曲线类模板中,我画图的时候是读取曲线类模板中所有的曲线类,然后把每个曲线类数据(其中曲线类的成员函数和我控件的属性基本上是对应的)去作图,这个是我作图画曲线的函数,其实如何能保存我的类模板信息就是最好的了,那样的话我初始化的时候只要把当前类模板的信息装载就没有问题了.
void CDrawGraphCtrl::Annotate(CDC *pDC, CRect rcy)
{ int i=0;
CRect textRect;
POSITION pos = m_AnnotationList.GetHeadPosition ();
CGraphAnnotation anno=m_AnnotationList.GetHead();
while(pos)
{ if ((i>3)||i>m_nAnnoCount)
break;
anno= m_AnnotationList.GetNext(pos);
if(!anno.m_bVisible)
continue;
pDC->SetBkMode(1);
pDC->SetTextColor (anno.m_BkColor);
pDC->SetTextAlign(TA_LEFT|TA_BOTTOM);
pDC->SetBkMode(TRANSPARENT);
CFont* pOldFont;
CFont* pf;
pf=new CFont;
pf->CreateFont(-15,0,0,0,1000,0,0,0,134,3,2,1,50,_T("宋体"));
pOldFont=pDC->SelectObject(pf);
CSize txtSize = pDC->GetTextExtent(anno.m_Caption);
CRect textRect;
textRect.left=rcy.left;
textRect.top=0+(txtSize.cy+1)*i;
textRect.right=rcy.left+txtSize.cy;
textRect.bottom=txtSize.cy+(txtSize.cy+1)*i;
//RefreshZone(pDC,textRect);
if (m_annoBrush.m_hObject == NULL)
m_annoBrush.CreateSolidBrush (anno.m_BkColor);
CBrush* pBrushSave = pDC->SelectObject(&m_annoBrush);
pDC->FillRect(textRect, &m_annoBrush);
pDC->TextOut(rcy.left+txtSize.cy+4,txtSize.cy+(txtSize.cy+1)*i,anno.m_Caption);
m_annoBrush.DeleteObject();
delete pf;
pDC->SelectObject(pOldFont);
pDC->SelectObject(pBrushSave);
pDC->SetTextAlign(TA_NOUPDATECP);
DrawYTitle(pDC,rcy,anno,i);
Drawcurve(pDC,rcy,anno,i); i=i+1;
}}
http://support.microsoft.com/kb/137333/EN-US/
随便加一个属性Test,将该属性改成用PX_Blob持久化以下是在控件的DoPropExchange中的部分代码,供参考,其中m_arr为CArray派生的集合对象
DWORD cbGuess = 5000;
// TODO: Call PX_ functions for each persistent custom property.
if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor))
{
if(!pPX->IsLoading())
{
m_hTest = GlobalAlloc(GPTR, cbGuess);
if(m_hTest != NULL)
{
BYTE* pMem = (BYTE*)m_hTest;
CSharedFile file;
file.Attach(pMem + sizeof(DWORD), cbGuess - sizeof(DWORD));
CArchive ar(&file, CArchive::store);
m_arr.Serialize(ar);
ar.Close();
int n = file.GetLength();
*(DWORD*)pMem = file.GetLength();
file.Close();
PX_Blob(pPX, _T("Test"), m_hTest);
}
GlobalFree(m_hTest);
m_hTest = NULL;
}
else{
PX_Blob(pPX, _T("Test"), m_hTest);
if(m_hTest){
BYTE* pMem = (BYTE*)GlobalLock(m_hTest);
CSharedFile file;
ULONG u = *(DWORD*)pMem;
ULONG ul = GlobalSize(m_hTest);
file.Attach(pMem + sizeof(DWORD), ul - sizeof(DWORD));
CArchive ar(&file, CArchive::load);
m_arr.Serialize(ar);
ar.Close();
file.Close();
GlobalUnlock(m_hTest);
GlobalFree(m_hTest);
m_hTest = NULL;
}
}
}
一句话,你可以用文件Serialize的,这里就可以,先Serialize你的List的个数,再Serialize每个曲线,不会要我告诉你Serialize怎么用吧
什么时候触发添加曲线的方法的,那是你的事,你只要记住随便加一个属性就可以了,这个属性可以是任何类型的,它本身没什么用,只是用来作尸体的,而你的模板库什么的才是魂,用的借尸体还魂的技术就是PX_Blob
关联的成员变量是short m_nTest,至于m_hTest则是自己的变量,类型是HGLOBAL,不是成员变量也没关系
下面是我按照你得那个写代码,我只想把我得模板类序列化,我想问您一下,如果对模板类进行序列化,是不是这个类模板得所有数据信息就能永久保存住?
void CDrawGraphCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
DWORD cbGuess = 5000;
//HGLOBAL hMem;hMem是控件类得成员变量,不和控件属性关联
if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor))
{ if(!pPX->IsLoading())
{
//m_hTest = GlobalAlloc(GPTR, cbGuess);
hMem = GlobalAlloc(GPTR, cbGuess);
if(hMem != NULL)
{
BYTE* pMem = (BYTE*)hMem;
CSharedFile file;
file.Attach(pMem + sizeof(DWORD), cbGuess - sizeof(DWORD));
CArchive ar(&file, CArchive::store);
m_AnnotationList.Serialize(ar);
ar.Close();
int n = file.GetLength();
*(DWORD*)pMem = file.GetLength();
file.Close();
}
PX_Blob(pPX, _T("Test"), hMem);
GlobalFree(hMem);
hMem = NULL;
}
else{
PX_Blob(pPX, _T("Test"), hMem);
//hMem = GlobalAlloc(GPTR, cbGuess);如果把这个注释掉下面 就不执行了,如果给放开则运行后在控件调试器里运行正常,用到DIALOG里,添加曲线就会报内存错误
if(hMem){
BYTE* pMem = (BYTE*)GlobalLock(hMem);
CSharedFile file;
ULONG u = *(DWORD*)pMem;
ULONG ul = GlobalSize(hMem);
file.Attach(pMem + sizeof(DWORD), ul - sizeof(DWORD));
CArchive ar(&file, CArchive::load);
m_AnnotationList.Serialize(ar);
//file.Attach(
ar.Close();
file.Close();
GlobalUnlock(hMem);
GlobalFree(hMem);
hMem = NULL;
} }
}
}//用后没有达到我得目的
if(hMem){...}里面的代码当然没法执行。
另外我的cbGuess=5000是因为我的数据只要这么多字节就够了,你最好再弄多一点,可能不够而出错总之,一句话,你就当保存到文件中就行了,事实上,本来也是保存到文件中去的,所以,如果你的模板类能够保存到文件,而且又能正确的从文件中读出,那么,这里也一样可以在你的属性页类中,你就当使用一个普通的属性一样使用Test属性好了,你的曲线是添加到你的m_AnnotationList中,和你的Test属性完全独立