我用MFC做了一个画曲线的ACTIVEX控件,在一个控件里最多可以添加四条曲线,其中每天曲线我用一个类来封装,在控件类中定义了一个该曲线类的类模板,添加曲线的功能是在自己定义的属性页中,也就是说我自己定义的控件属性页面不仅仅有曲线的相关属性如颜色名称等,还可以通过属性页面动态的去调用控件的添加属性的方法,可是我把这个控件用到一个DIALOG的MFC程序中在设计这个控件的时候什么属性都设置好了,曲线也出来了,可是运行后设计阶段所设置的曲线都没有了,也就是相关属性没有永久存储住,我想在设计阶段就把控件设计好,运行后不需要干预,如果解决,望高手指点!!!急!!

解决方案 »

  1.   

    要实现Persistence
    查看一下MSDN上的Persistence相关内容
      

  2.   

    这方面的知识我也看了,一般永久存储性存储是在DoPropExchange(CPropExchange* pPX)函数中写
    我要说的是我不仅仅有属性还有方法,我在属性页里有个添加曲线的方法,我怎么去保存我每天曲线的数据呢,即使单条曲线数据保存下来了,后来画的时候怎么区分,因为我的每条曲线是放在曲线类中,而总体的曲线是在曲线类模板中,我画图的时候是读取曲线类模板中所有的曲线类,然后把每个曲线类数据(其中曲线类的成员函数和我控件的属性基本上是对应的)去作图,这个是我作图画曲线的函数,其实如何能保存我的类模板信息就是最好的了,那样的话我初始化的时候只要把当前类模板的信息装载就没有问题了.
      

  3.   

    做图函数:
    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;

    }}
      

  4.   

    其中ANNO是曲线类, CGraphAnnotation 是曲线类摸板,哪位高人给指点一下
      

  5.   

    http://support.microsoft.com/kb/q141274/
    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;
    }
    }
    }
      

  6.   

    谢谢楼上,我看了有关PX_Blob函数的功能,它是用来保存控件的属性的,我这里控件的属性不是单一的一条记录,而是多条,每条曲线对应一组控件的属性,PX_Blob好像保存的是一条曲线的属性,不能够保存我所有曲线的属性,另外保存住了以后画曲线的时候它该怎么区分到底是哪条曲线的属性也是一个问题,因为我画曲线的时候是访问我的模板库看里面有几个ANNO(自己定义的曲线类),因为只是保存了属性,因为如果不触发那个方法我就不会往那个模板类添加曲线类对象,如果能够保存我自己定义的类模板就OK了
      

  7.   

    PX_Blob保存的是一个内存块,什么是内存块,就是可以保存任何的东西,为了给你方便,我特意的用了CObArray作为例子,什么是CObArray,就是可以保存其它的类对象的数组类,和你的CList有什么区别,既然CObArray可以,为什么CObList不可以
    一句话,你可以用文件Serialize的,这里就可以,先Serialize你的List的个数,再Serialize每个曲线,不会要我告诉你Serialize怎么用吧
    什么时候触发添加曲线的方法的,那是你的事,你只要记住随便加一个属性就可以了,这个属性可以是任何类型的,它本身没什么用,只是用来作尸体的,而你的模板库什么的才是魂,用的借尸体还魂的技术就是PX_Blob
      

  8.   

    我添加了一个short的属性Test,关联的成员变量是m_hTest,可是m_hTest = GlobalAlloc(GPTR, cbGuess);报错误,cannot convert from 'void *' to 'short'
      

  9.   

    你留个EMAIL吧,我给你我的测试源码
    关联的成员变量是short m_nTest,至于m_hTest则是自己的变量,类型是HGLOBAL,不是成员变量也没关系
      

  10.   

    我EMAIL:[email protected]
    下面是我按照你得那个写代码,我只想把我得模板类序列化,我想问您一下,如果对模板类进行序列化,是不是这个类模板得所有数据信息就能永久保存住?
    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;
    }  }
    }
    }//用后没有达到我得目的
      

  11.   

    在else后面不要加GlobalAlloc,这是装载数据的时候,你一开始并没有数据,当然load不了东西
    if(hMem){...}里面的代码当然没法执行。
    另外我的cbGuess=5000是因为我的数据只要这么多字节就够了,你最好再弄多一点,可能不够而出错总之,一句话,你就当保存到文件中就行了,事实上,本来也是保存到文件中去的,所以,如果你的模板类能够保存到文件,而且又能正确的从文件中读出,那么,这里也一样可以在你的属性页类中,你就当使用一个普通的属性一样使用Test属性好了,你的曲线是添加到你的m_AnnotationList中,和你的Test属性完全独立