当 MFC(功能包)调用 CDockablePane::Serialize() 时?

Posted

技术标签:

【中文标题】当 MFC(功能包)调用 CDockablePane::Serialize() 时?【英文标题】:When MFC (Feature Pack) calling for CDockablePane::Serialize()? 【发布时间】:2015-12-04 10:11:58 【问题描述】:

CDockablePane::Serialize() 方法是否从 MFC 功能包核心调用?

我有继承自 CDockablePane 类的可停靠窗口类。我的类覆盖虚拟Serialize() 方法并声明为串行DECLARE_SERIAL/IMPLEMENT_SERIAL。但是 MFC 不会调用我的Serialize() 方法!为什么 ? MSDN say 认为CDockablePane 类有序列化方法:SaveState()LoadState()Serialize()。前两个(SaveState()LoadState()在内部使用Serialize() 用于“序列化窗格”。但它没有调用!

【问题讨论】:

不,它不是由框架调用的。您通常必须从CDocument::Serialize 手动调用它。 LoadState/SaveState 用于保存/恢复窗格位置和状态。他们确实使用 Registry 作为存储。 @AndrewKomiagin 谢谢。 :( 很伤心,我不明白声明CDockablePane 类为可序列化的含义。 DECLARE_SERIALIMPLEMENT_SERIAL 用于支持 operator>> 和其他 CArchive 特定的东西以及运行时类信息。 【参考方案1】:

不,MFC 框架不会自动调用Serialize() 方法。您通常必须从CDocument::Serialize() 手动调用它。 LoadState()SaveState() 方法用于保存/恢复窗格位置和状态。他们确实使用 Registry 作为存储。

至于DECLARE_SERIALIMPLEMENT_SERIAL,它们用于支持operator>> 和其他CArchive 特定的东西以及运行时类信息。这样你就可以自动使用BOOL IsKindOf(RUNTIME_CLASS(...))了。

【讨论】:

不,IsKinfOf 按 MFC 类信息工作(请参阅 DECLARE_DYNAMIC() 宏)。 DECLARE_SERIAL 实现了DECLARE_DYNAMIC,但主要支持序列化代码!【参考方案2】:

我的回答命题。我的班级CSerializableDockablePane 在框架创建或存储此停靠窗格时调用Serialize 方法(框架调用方法LoadState()SaveState())。

您可以使用CSerializableDockablePane 作为可停靠窗格的基类,并根据需要覆盖虚拟Serialize() 方法。

代码:

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
/////////////////////////////////////////////////////////////////////////////

【讨论】:

以上是关于当 MFC(功能包)调用 CDockablePane::Serialize() 时?的主要内容,如果未能解决你的问题,请参考以下文章

MFC 功能包是不是会支持 Scenic Ribbon?

Mfc 功能包 CMFCOutlookBar 未显示

新的 MFC 功能包控件是不是应该出现在 VS 工具箱中

MFC 功能包 - 可停靠文件资源管理器和可停靠属性窗口

找出在 Office 2007 样式中使用 MFC 功能包时使用的颜色

MFC 功能包 - 关闭后无法显示可停靠窗格