0

Does CDockablePane::Serialize() method is calling from MFC Feature Pack core?

I have dockable window class that inherited from CDockablePane class. My class override virtual Serialize() method and declared as serial DECLARE_SERIAL/IMPLEMENT_SERIAL. But MFC does not call my Serialize() method! Why ? MSDN say that CDockablePane class have serialization methods: SaveState(), LoadState() and Serialize(). First two (SaveState(), LoadState()) are used internally and Serialize() used for "serializes the pane". But it is not calling!

23W
  • 1,413
  • 18
  • 37
  • 1
    No it is not called by framework. You have to call it manually usually from `CDocument::Serialize`. `LoadState`/`SaveState` are used to save/restore pane position and state. They do use **Registry** as storage. – Andrew Komiagin Dec 04 '15 at 10:28
  • @AndrewKomiagin thank you. :( It's very sad, I do not understand the meaning declare `CDockablePane` class as serializable. – 23W Dec 04 '15 at 10:58
  • `DECLARE_SERIAL` and `IMPLEMENT_SERIAL` are used to support `operator>>` and other `CArchive`-specific stuff plus runtime class info. – Andrew Komiagin Dec 04 '15 at 11:54

2 Answers2

3

No, the Serialize() method is not called by MFC framework automatically. You have to call it manually usually from CDocument::Serialize(). LoadState() and SaveState() methods are used to save/restore pane position and state. They do use Registry as storage.

As for DECLARE_SERIAL and IMPLEMENT_SERIAL they are used to support operator>> and other CArchive-specific things plus runtime class information. So you'll be able to use BOOL IsKindOf(RUNTIME_CLASS(...)) automagically.

Andrew Komiagin
  • 6,446
  • 1
  • 13
  • 23
  • No, `IsKinfOf` works by MFC class information ( see `DECLARE_DYNAMIC()` macro ). `DECLARE_SERIAL` implements `DECLARE_DYNAMIC` but main its code for serialization support! – 23W Dec 04 '15 at 13:16
0

My answer proposition. My class CSerializableDockablePane performs call for Serialize method when this docked pane is created or stored by framework (framework calls methods LoadState() and SaveState()).

You can use CSerializableDockablePane as base class for your dockable pane and overwrite virtual Serialize() method for your need.

Code:

class CSerializableDockablePane
    : public CDockablePane
{
    DECLARE_SERIAL(CSerializableDockablePane)

public:
    typedef CDockablePane TBase;

public:
    CSerializableDockablePane();
    virtual ~CSerializableDockablePane();

    virtual BOOL            LoadState(LPCTSTR lpszProfileName = NULL, int nIndex = -1, UINT uiID = (UINT)-1);
    virtual BOOL            SaveState(LPCTSTR lpszProfileName = NULL, int nIndex = -1, UINT uiID = (UINT)-1);
    virtual void            Serialize(CArchive& ar);
};



/////////////////////////////////////////////////////////////////////////////
// CSerializableDockablePane

#define _MFC_DOCVIEW_PROFILE _T("DockableViews")
#define _REG_UI_DOCVIEWSECTION_FMT _T("%TsSerializableDockablePane-%d")
#define _REG_UI_DOCVIEWSECTION_FMT_EX _T("%TsSerializableDockablePane-%d%x")
#define _REG_UI_SETTINGS _T("Settings")

IMPLEMENT_SERIAL(CSerializableDockablePane, CSerializableDockablePane::TBase, VERSIONABLE_SCHEMA | 2)

CSerializableDockablePane::CSerializableDockablePane()
{
}

CSerializableDockablePane::~CSerializableDockablePane()
{
}

BOOL CSerializableDockablePane::LoadState(LPCTSTR lpszProfileName /*= NULL*/, int nIndex /*= -1*/, UINT uiID /*= (UINT)-1*/)
{
    BOOL bRes = TBase::LoadState(lpszProfileName, nIndex, uiID);
    if (bRes) {

        const CString strProfileName = ::AFXGetRegPath(_MFC_DOCVIEW_PROFILE, lpszProfileName);
        if (nIndex == -1) {
            nIndex = GetDlgCtrlID();
        }

        CString strSection;
        if (uiID == (UINT)-1) {
            strSection.Format(_REG_UI_DOCVIEWSECTION_FMT, (LPCTSTR)strProfileName, nIndex);
        }
        else {
            strSection.Format(_REG_UI_DOCVIEWSECTION_FMT_EX, (LPCTSTR)strProfileName, nIndex, uiID);
        }

        LPBYTE lpbData = nullptr;
        UINT uiDataSize = 0;

        CSettingsStoreSP regSP;
        CSettingsStore& reg = regSP.Create(FALSE, TRUE);

        if (!reg.Open(strSection)) {
            return FALSE;
        }

        if (!reg.Read(_REG_UI_SETTINGS, &lpbData, &uiDataSize)) {
            return FALSE;
        }

        try
        {
            CMemFile file(lpbData, uiDataSize);
            CArchive ar(&file, CArchive::load);

            Serialize(ar);
            bRes = TRUE;
        }
        catch (CMemoryException* pEx)
        {
            pEx->Delete();
            TRACE(_T("Memory exception in CSerializableDockablePane::LoadState()!\n"));
        }
        catch (CArchiveException* pEx)
        {
            pEx->Delete();
            TRACE(_T("CArchiveException exception in CSerializableDockablePane::LoadState()!\n"));
        }

        if (lpbData != nullptr) {
            delete[] lpbData;
        }
    }

    return bRes;
}

BOOL CSerializableDockablePane::SaveState(LPCTSTR lpszProfileName /*= NULL*/, int nIndex /*= -1*/, UINT uiID /*= (UINT)-1*/)
{
    BOOL bRes = TBase::SaveState(lpszProfileName, nIndex, uiID);
    if (bRes) {

        const CString strProfileName = ::AFXGetRegPath(_MFC_DOCVIEW_PROFILE, lpszProfileName);
        if (nIndex == -1) {
            nIndex = GetDlgCtrlID();
        }

        CString strSection;
        if (uiID == (UINT)-1) {
            strSection.Format(_REG_UI_DOCVIEWSECTION_FMT, (LPCTSTR)strProfileName, nIndex);
        }
        else {
            strSection.Format(_REG_UI_DOCVIEWSECTION_FMT_EX, (LPCTSTR)strProfileName, nIndex, uiID);
        }

        try
        {
            CMemFile file;

            {
                CArchive ar(&file, CArchive::store);

                Serialize(ar);
                ar.Flush();
            }

            UINT uiDataSize = (UINT)file.GetLength();
            LPBYTE lpbData = file.Detach();

            if (lpbData != NULL)
            {
                CSettingsStoreSP regSP;
                CSettingsStore& reg = regSP.Create(FALSE, FALSE);

                if (reg.CreateKey(strSection)) {
                    bRes = reg.Write(_REG_UI_SETTINGS, lpbData, uiDataSize);
                }

                free(lpbData);
            }
        }
        catch (CMemoryException* pEx)
        {
            pEx->Delete();
            TRACE(_T("Memory exception in CSerializableDockablePane::SaveState()!\n"));
        }
    }

    return bRes;
}

void CSerializableDockablePane::Serialize(CArchive& ar)
{
    TBase::Serialize(ar);
}
// CSerializableDockablePane
/////////////////////////////////////////////////////////////////////////////
23W
  • 1,413
  • 18
  • 37