Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Bug in CExtPropertyItem::Serialize function Collapse All
Subject Author Date
Lars Mohr Nov 15, 2009 - 5:11 PM

Dear Support Team,


there is a bug in the CExtPropertyItem::Serialize function. If you store the data everything is ok, but if you want to load it then the try/catch block throw an exception. You can try it with the PropertyGrid example. Just uncomment the function call ValueDefaultFromActive.



CStarButtonProperty_Animation::CStarButtonProperty_Animation(
    CStarButton * pStarButton // = NULL
    )
    : CStarPropertyValueBase(
        _T("Animation"),
        pStarButton
        )
{
    DescriptionSet( _T("Specifies the star animation effect.") );
CExtGridCellComboBox * pValue =
        STATIC_DOWNCAST(
            CExtGridCellComboBox,
            ValueActiveGetByRTC( RUNTIME_CLASS(CExtGridCellComboBox) )
            );
    ASSERT_VALID( pValue );
    pValue->InsertString( _T("None"), DWORD(CStarButton::__EAT_NONE) );
    pValue->InsertString( _T("Slow"), DWORD(CStarButton::__EAT_SLOW) );
    pValue->InsertString( _T("Middle"), DWORD(CStarButton::__EAT_MIDDLE) );
    pValue->InsertString( _T("Fast"), DWORD(CStarButton::__EAT_FAST) );
    pValue->SetEnumMode();
    if( m_pStarButton != NULL )
        pValue->SetCurSel(
            (INT)m_pStarButton->AnimationGet()
            );
//    ValueDefaultFromActive();  <- UNCOMMENT

And I think, I have found the problem:



void CExtPropertyItem::Serialize( CArchive & ar )
{
    ASSERT_VALID( this );
    if( ar.IsStoring() )
    {
        ...
        CExtGridCell * pCellDefault = ValueDefaultGet(), * pCellActive = ValueActiveGet();
        if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
        {
            ASSERT_VALID( pCellDefault );
            dwFlags |= 0x00000001;
        } // if( pCellDefault != NULL )
        if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
        {
            ASSERT_VALID( pCellActive );
            dwFlags |= 0x00000002;
        } // if( pCellActive != NULL )
        ...
    } // if( ar.IsStoring() )
    else
    {
       ...
    } // else from if( ar.IsStoring() )

should be replaced with



if( pCellActive != NULL )

Thanks...

Technical Support Nov 20, 2009 - 2:39 PM

There is a typo in the CExtPropertyItem::Serialize() method’s source code. Here is the fixed version:

void CExtPropertyItem::Serialize( CArchive & ar )
{
            ASSERT_VALID( this );
            if( ar.IsStoring() )
            {
                        ar << m_strName;
                        ar << m_strDescription;
                        DWORD dwTmp = DWORD( m_lParam );
                        ar << dwTmp;
                        dwTmp = DWORD(m_nHeightPx);
                        ar << dwTmp;
                        DWORD dwFlags = 0;
                        CExtGridCell * pCellDefault = ValueDefaultGet(), * pCellActive = ValueActiveGet();
                        if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
                        {
                                    ASSERT_VALID( pCellDefault );
                                    dwFlags |= 0x00000001;
                        }
                        if( pCellActive != NULL )
                        {
                                    ASSERT_VALID( pCellActive );
                                    dwFlags |= 0x00000002;
                        }
                        if( ExpandedGet() )
                                    dwFlags |= 0x00000004;
                        if( InputEnabledGet() )
                                    dwFlags |= 0x00000008;
                        ar << dwFlags;
                        if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
                        {
                                    CRuntimeClass * pRTC = pCellDefault->GetRuntimeClass();
                                    ASSERT( pRTC != NULL );
                                    ar.WriteClass( pRTC );
                                    pCellDefault->Serialize( ar );
                        } // if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
                        if( pCellActive != NULL )
                        {
                                    CRuntimeClass * pRTC = pCellActive->GetRuntimeClass();
                                    ASSERT( pRTC != NULL );
                                    ar.WriteClass( pRTC );
                                    pCellActive->Serialize( ar );
                        } // if( pCellActive != NULL )
                        DWORD dwIndex, dwCount = ItemGetCount();
                        ar << dwCount;
                        for( dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
                        {
                                    CExtPropertyItem * pItem =
                                                ItemGetAt( INT(dwIndex) );
                                    ASSERT_VALID( pItem );
                                    ASSERT_KINDOF( CExtPropertyItem, pItem );
                                    CRuntimeClass * pRTC = pItem->GetRuntimeClass();
                                    ASSERT( pRTC != NULL );
                                    ar.WriteClass( pRTC );
                                    pItem->Serialize( ar );
                        } // for( dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
            } // if( ar.IsStoring() )
            else
            {
                        if( ItemGetCount() > 0 )
                                    ItemRemove();
                        ar >> m_strName;
                        ar >> m_strDescription;
                        DWORD dwTmp;
                        ar >> dwTmp;
                        m_lParam = LPARAM(dwTmp);
                        ar >> dwTmp;
                        m_nHeightPx = INT(dwTmp);
                        DWORD dwFlags;
                        ar >> dwFlags;
                        if( (dwFlags&0x00000001) != 0 )
                        {
                                    CRuntimeClass * pRTC = ar.ReadClass();
                                    ASSERT( pRTC != NULL );
                                    CExtGridCell * pCellDefault = (CExtGridCell*)pRTC->CreateObject();
                                    ASSERT_VALID( pCellDefault );
                                    ASSERT_KINDOF( CExtGridCell, pCellDefault );
                                    pCellDefault->Serialize( ar );
                                    ASSERT_VALID( pCellDefault );
                                    VERIFY( ValueDefaultSet( pCellDefault ) );
                        } // if( (dwFlags&0x00000001) != 0 )
                        if( (dwFlags&0x00000002) != 0 )
                        {
                                    CRuntimeClass * pRTC = ar.ReadClass();
                                    ASSERT( pRTC != NULL );
                                    CExtGridCell * pCellActive = (CExtGridCell*)pRTC->CreateObject();
                                    ASSERT_VALID( pCellActive );
                                    ASSERT_KINDOF( CExtGridCell, pCellActive );
                                    pCellActive->Serialize( ar );
                                    ASSERT_VALID( pCellActive );
                                    VERIFY( ValueActiveSet( pCellActive ) );
                        } // if( (dwFlags&0x00000002) != 0 )
                        if( (dwFlags&0x00000004) != 0 )
                                    ExpandedSet( true );
                        else
                                    ExpandedSet( false );
                        if( (dwFlags&0x00000008) != 0 )
                                    InputEnabledSet( true );
                        else
                                    InputEnabledSet( false );
                        DWORD dwIndex, dwCount;
                        ar >> dwCount;
                        for( dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
                        {
                                    CRuntimeClass * pRTC = ar.ReadClass();
                                    ASSERT( pRTC != NULL );
                                    CExtPropertyItem * pItem = (CExtPropertyItem*)pRTC->CreateObject();
                                    ASSERT_VALID( pItem );
                                    ASSERT_KINDOF( CExtPropertyItem, pItem );
                                    pItem->Serialize( ar );
                                    ASSERT_VALID( pItem );
                                    VERIFY( ItemInsert( pItem ) );
                        } // for( dwIndex = 0; dwIndex < dwCount; dwIndex ++ )
            } // else from if( ar.IsStoring() )
}


Technical Support Nov 16, 2009 - 1:32 PM

This is not a bug. The CExtPropertyValue object requires both active and default grid cells instantiated inside it and they should be different grid cells. Only such fully initialized property values should be inserted into the property store before assigning it to the property grid control.

Lars Mohr Nov 17, 2009 - 2:53 AM

So the function call ValueDefaultFromActive is important and necessary!? But if I don’t want to have the default and reset to default feature?

Lars Mohr Nov 17, 2009 - 5:07 AM

Oh I have found it: CExtPropertyValueSingleCell...


sorry for my mistake!

Lars Mohr Nov 19, 2009 - 3:38 PM

sorry but I have stille the problem with the CExtPropertyItem::Serialize methode. Now I use a CExtPropertyValueSingleCell instead of a CExtPropertyValue. But the problem ist still there. If you store a CExtPropertyValueSingleCell or CExtPropertyValue you check if pCellActive != NULL and store the CExtGridCell:       

if( pCellActive != NULL )
        {
            CRuntimeClass * pRTC = pCellActive->GetRuntimeClass();
            ASSERT( pRTC != NULL );
            ar.WriteClass( pRTC );
            pCellActive->Serialize( ar );
        } // if( pCellActive != NULL )

But you don’t set the flag to 0x00000002, because the flag condition is:         
if( pCellDefault != NULL && LPVOID(pCellDefault) != LPVOID(pCellActive) )
        {
            ASSERT_VALID( pCellActive );
            dwFlags |= 0x00000002;
        } // if( pCellActive != NULL )

So if you want to load it again, the app crashed because the flag 0x00000002 is missing.