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.
Subject |
Author |
Date |
|
Krister Goodh
|
Mar 29, 2010 - 2:59 AM
|
Hello! When i remove items from a CExtPropertyStore ther’s normally no problem. After removing the items, using m_SomeCategoryPtr->ItemRemove(); I do m_PGC.PropertyStoreSynchronize(); to show the changes. However if I click on a read-oply property (enables user to copy value to clipboard, from a CExtGridCellString ) and then, while cursor is visible, execute the code above the call to m_PGC.PropertyStoreSynchronize() activates code that fails with the message: ASSERT_VALID fails with illegal vtable pointer.
ASSERT_VALID fails with illegal vtable pointer.
Second Chance Assertion Failed: File C:\Program\FOSS Software Inc\Prof-UIS\Src\ExtPropertyGridWnd.cpp, Line 7194 from CExtPropertyGridWnd::PropertyItemFromTreeItem() (the call is passing CExtGridInplaceEdit::DoEndEdit() ). - Am I removing items in the wrong way?
|
|
Krister Goodh
|
Mar 29, 2010 - 9:59 AM
|
A partial workaround is to do: if (may_delete_or_edit) m_PGC.PropertyStoreSet(NULL);
m_Store.DoSomeChanges();
if (may_delete_or_edit) m_PGC.PropertyStoreSet(&m_Store); This does not work for an edit field that is not disabled for editing. Still asserts. It also has the efect that if I drop down a combo box, and while it:s dropped down delete 2 items moving a checklist into the position previously occupied by the combo, the checklist will be repopulated with the entries from the combo box!!!
|
|
Technical Support
|
Mar 29, 2010 - 12:23 PM
|
Thank you for reporting us this issue. To fix it, please update the source code for the following method: void CExtPropertyGridCtrl::PropertyStoreSynchronize()
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
_EnsureInitialized();
CExtPropertyGridWnd * pActivePGW = GetActiveGrid();
if( pActivePGW->GetSafeHwnd() != NULL )
{
HWND hWndInpalaceEditor = pActivePGW->GetSafeInplaceActiveHwnd();
if( hWndInplaceEditor != NULL )
{
::SendMessage( hWndInplaceEditor, WM_CANCELMODE, 0L, 0L );
pActivePGW->SendMessage( WM_CANCELMODE );
}
}
CExtPropertyStore * pCurrentPS = PropertyStoreGet();
CExtPropertyItem * pRestoreFocusPI = NULL;
if( pCurrentPS != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pCurrentPS );
if( pActivePGW->GetSafeHwnd() != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
HTREEITEM htiFocus = pActivePGW->ItemFocusGet();
if( htiFocus != NULL )
// pRestoreFocusPI = pActivePGW->PropertyItemFromTreeItem( htiFocus );
pRestoreFocusPI = pActivePGW->_PropertyItemFromTreeItem_Impl( htiFocus );
}
}
CTypedPtrArray < CPtrArray, CExtPropertyGridWnd * > arrGrids;
OnPgcQueryGrids( arrGrids );
INT nGridIdx = 0;
for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
{
CExtPropertyGridWnd * pGrid = arrGrids[ nGridIdx ];
__EXT_DEBUG_GRID_ASSERT_VALID( pGrid );
pGrid->PropertyStoreSynchronizeAll();
} // for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
if( pRestoreFocusPI != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
__EXT_DEBUG_GRID_ASSERT( pActivePGW->GetSafeHwnd() != NULL );
// HTREEITEM htiSetFocus = pActivePGW->PropertyItemToTreeItem( pRestoreFocusPI );
HTREEITEM htiSetFocus = pActivePGW->_PropertyItemToTreeItem_Impl( pRestoreFocusPI );
if( htiSetFocus != NULL )
pActivePGW->ItemFocusSet( htiSetFocus );
}
}
|
|
Krister Goodh
|
Mar 30, 2010 - 3:11 AM
|
Great, this solved the first issue described, which was the most serious. It however does not solve the issue with destroyed value lists. How to reproduce: - Have property tree with two categories, the upper category has two entries, the lower has five entries, the first is a combo box and the 4:th is a drop down check list
- Populate combo with some strings and check list with some strings, make all visible in a
CExtPPVW < CExtPropertyGridCtrlMeterInfo > . - Drop down the combo box and move the mouse over a value
- While the combo is open, let the program remove the upper category and it:s 2 values
- Click on a line in the combo
- Now the values from the combo box will repopulate the drop down check list 3 lines below ??!?
|
|
Technical Support
|
Mar 30, 2010 - 5:54 AM
|
Here is the next improved version of the CExtPropertyGridCtrl::PropertyStoreSynchronize() method which closes any popup windows opened by any property grid cells before updating the property grid control:
void CExtPropertyGridCtrl::PropertyStoreSynchronize()
{
__EXT_DEBUG_GRID_ASSERT_VALID( this );
_EnsureInitialized();
CExtPropertyGridWnd * pActivePGW = GetActiveGrid();
if( pActivePGW->GetSafeHwnd() != NULL )
{
HWND hWndInplaceEditor = pActivePGW->GetSafeInplaceActiveHwnd();
if( hWndInplaceEditor != NULL )
{
::SendMessage( hWndInplaceEditor, WM_CANCELMODE, 0L, 0L );
pActivePGW->SendMessage( WM_CANCELMODE );
}
}
if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL && pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) )
{
CExtPropertyGridWnd * pActiveGrid = GetActiveGrid();
if( pActiveGrid != NULL )
{
CExtGridDataProvider & _ActiveDP = pActiveGrid->OnGridQueryDataProvider();
if( LPVOID(&_ActiveDP) == LPVOID(pDP) )
CExtPopupMenuWnd::CancelMenuTracking();
}
}
}
CExtPropertyStore * pCurrentPS = PropertyStoreGet();
CExtPropertyItem * pRestoreFocusPI = NULL;
if( pCurrentPS != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pCurrentPS );
if( pActivePGW->GetSafeHwnd() != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
HTREEITEM htiFocus = pActivePGW->ItemFocusGet();
if( htiFocus != NULL )
// pRestoreFocusPI = pActivePGW->PropertyItemFromTreeItem( htiFocus );
pRestoreFocusPI = pActivePGW->_PropertyItemFromTreeItem_Impl( htiFocus );
}
}
CTypedPtrArray < CPtrArray, CExtPropertyGridWnd * > arrGrids;
OnPgcQueryGrids( arrGrids );
INT nGridIdx = 0;
for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
{
CExtPropertyGridWnd * pGrid = arrGrids[ nGridIdx ];
__EXT_DEBUG_GRID_ASSERT_VALID( pGrid );
pGrid->PropertyStoreSynchronizeAll();
} // for( ; nGridIdx < arrGrids.GetSize(); nGridIdx ++ )
if( pRestoreFocusPI != NULL )
{
__EXT_DEBUG_GRID_ASSERT_VALID( pActivePGW );
__EXT_DEBUG_GRID_ASSERT( pActivePGW->GetSafeHwnd() != NULL );
// HTREEITEM htiSetFocus = pActivePGW->PropertyItemToTreeItem( pRestoreFocusPI );
HTREEITEM htiSetFocus = pActivePGW->_PropertyItemToTreeItem_Impl( pRestoreFocusPI );
if( htiSetFocus != NULL )
pActivePGW->ItemFocusSet( htiSetFocus );
}
}
Please also make the CExtGridCell::g_pCellMenuTracking static property public .
|
|
Krister Goodh
|
Mar 30, 2010 - 6:25 AM
|
When I reach this code provided by you: if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL && pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) ) the variable pDP points to a CExtGridDataProviderMemory and the last if clause in my snip above is not taken -> problem can still be reproduced.
|
|
Technical Support
|
Mar 31, 2010 - 6:41 AM
|
Yes, you are right. The pDP->IsKindOf( RUNTIME_CLASS(CExtTreeGridDataProvider) ) condition is not needed.
|
|
Krister Goodh
|
Apr 12, 2010 - 1:00 AM
|
// Ups’ didn’t see your answer since it was above my question... Well it’s not the runtime class test that is false, but rather _ActiveDP == pDP . That’s why I experimentally replaced the test by the test _ActiveDP = pDP->m_pOuterDataProvider . Could you please verify that this is correct? (See the code posted (i think) below at "Mar 30, 2010 - 6:54 AM".)
|
|
Krister Goodh
|
Apr 28, 2010 - 7:13 AM
|
Have you had time to look at this? The code in profuis289(2010-04-22) seems to be the same (-> i guess not working according to description above). /J
|
|
Krister Goodh
|
Mar 30, 2010 - 6:54 AM
|
Would this work???? (In CExtPropertyGridCtrl::PropertyStoreSynchronize() , slight patch on the code provided by you.) if( CExtGridCell::g_pCellMenuTracking != NULL )
{
CExtGridDataProvider * pDP = CExtGridCell::g_pCellMenuTracking->DataProviderGet();
if( pDP != NULL
&& pDP->IsKindOf( RUNTIME_CLASS(CExtGridDataProviderMemory) )
&& pDP->m_pOuterDataProvider != NULL )
{
CExtPropertyGridWnd * pActiveGrid = GetActiveGrid();
if( pActiveGrid != NULL )
{
CExtGridDataProvider& _ActiveDP = pActiveGrid->OnGridQueryDataProvider(); CExtTreeGridDataProvider * pTreeDP =
DYNAMIC_DOWNCAST( CExtTreeGridDataProvider, pDP->m_pOuterDataProvider ); if( LPVOID(&_ActiveDP) == LPVOID(pTreeDP) )
CExtPopupMenuWnd::CancelMenuTracking();
}
}
}
|
|
Krister Goodh
|
Mar 30, 2010 - 3:30 AM
|
I have a screen shot of the event, and will send this by mail.
|
|
Krister Goodh
|
Mar 29, 2010 - 3:15 AM
|
How to reproduce (using "Win32 Static MBCS Debug", ProfUIS289smd.lib in project "Property Grid Sample": - In
BOOL CMainDlg::OnInitDialog() , add to the end the line SetTimer(134,3000,NULL); - Add function
void CMainDlg::OnTimer(UINT nIDEvent)
{
CExtResizableDialog ::OnTimer(nIDEvent);
if (nIDEvent == 134)
{
m_Btn1.SelectedStateSet( false );
CheckMarkOnButtonChanged();
}
} - Start aplication and quickly click on a property value so that the edit cursor is visible (ex: "RadiusInner")
- Wait for the timer to expire, this will reproduce my problem.
|
|