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 General Discussion » Problem removing hidden rows in CExtReportGridWnd. Collapse All
Subject Author Date
Eric Houvenaghel Jul 25, 2008 - 8:26 AM

Hello.


My application crashes when I attempt to remove hidden rows.


Here is the scenario:


I have a tree control that loads information into the CExtReportGridWnd grid when the user selects one of the tree nodes.


The user then performs a filter which hides rows.


Then the user deselects the a node.


The grid performs a removal of the grid rows that are hidden and I get a crash.


The crash occurs on line 2278 in ExtTreeGridWnd.cpp:


        nRowNo -= nReservedRowCount;

        ASSERT( nRowNo < ULONG(m_arrGridVis.GetSize()) );

        CExtTreeGridCellNode * pNode = m_arrGridVis.GetAt( nRowNo );

        ASSERT_VALID( pNode );

        nOffset = pNode->TreeNodeCalcOffset( false, true ); // CRASH!!!!!!

        nOffset += nReservedRowCount;


The crash seems to occur in some cases and not others.


Hope you can help.


Thanks.

Technical Support Jul 25, 2008 - 11:54 AM

We used v.2.83 for checking the problem described in your message. We checked the item removing code in the CExtTreeGridWnd class and it works OK:

test_tree_grid_idea(with-hiding).zip

We used the FilteredGrids sample application to check hidden item deletion in the CExtReportGridWnd class and it works OK. We modified the ChildView.cpp file in this sample application for testing. We have added the following line at the top of this file:

CExtReportGridItem * g_SavedReportGridItem = NULL;
Then we modified the CFilteredReportGridWnd::Init() method
CTypedPtrArray < CPtrArray, CExtReportGridItem * > _arrItems;
      _arrItems.InsertAt( 0, NULL, nRowCount );
      ReportItemRegister( _arrItems, false, false );
      g_SavedReportGridItem = _arrItems[ 0 ]; /// THIS LINE WAS ADDED
      for( LONG nRowNo = 0L; nRowNo < nRowCount; nRowNo++ )
And then we modified the following method:
void CFilteredReportGridWnd::OnClearAllFilters()
{
      ASSERT_VALID( this );
//    FilterStateClearAll();

      if( g_SavedReportGridItem == NULL )
            return;
      ::AfxMessageBox( _T("Click OK to hide first registered report grid row.") );
      ItemHide( (HTREEITEM)g_SavedReportGridItem, true );
      ::AfxMessageBox( _T("Click OK to remove just hidden report grid row.") );
      ItemRemove( (HTREEITEM)g_SavedReportGridItem );
      g_SavedReportGridItem = NULL;
}
This modified version of the FilteredGrids sample remembers the first registered report grid row at startup. So, if we run this sample application, select the tab page with report grid control and click on the Clear All Filters button at the top of report grid, then the CFilteredReportGridWnd::OnClearAllFilters() method will be invoked and it will hide the saved at startup report row and then remove it. We didn’t come across any crashes. We tried to re-group the report grid and filter it before clicking the Clear All Filters button, but failed to reproduce the crash. Here is the modified version of the ChildView.cpp file from the FilteredGrids sample application:

FilteredGrids_ChildView_CPP_test_hidden_remove.zip

We suspect the problem with hidden items removing in your application can be related to some older version of Prof-UIS or to some other source code specific to your project only. In any case, we would appreciate if you would help us re-produce this problem with v.2.83.

Eric Houvenaghel Jul 28, 2008 - 10:01 AM

Thanks for the reply.


It’s a strange bug.


I really can’t tell which court the ball is in.


The problem occurs in one of our products but not the others.


So I’m inclined to think that it’s our problem.


However, there is another related crash that I’m getting which points to a problem in hidden row removal.


When I remove a row, hidden or visible,  I perform a deletion on the LParam of the row.


So, in our applications, it is impossible, or should be impossible, to have a valid CExtReportGridItem pointer and have a NULL LParam.


But this is exactly what’s happening with the following code that is called after row removal:


COLORREF GridDerivedFromReportGrid::OnGbwQueryBackColor(

    CDC& dc,

    LONG nVisibleColNo,

    LONG nVisibleRowNo,

    LONG nColNo,

    LONG nRowNo,

    INT nColType,

    INT nRowType,

    DWORD dwAreaFlags,

    DWORD dwHelperPaintFlags) const {


    ...




    // Get the row item.

    const CExtReportGridItem* pRGI = ReportItemFromTreeItem(hTreeItem);

    ASSERT(NULL != pRGI); -- OK



    // Get the row lparam.

    LParamData* pParam = (LParamData*)pRGI->LParamGet();

    ASSERT(NULL != pParam); -- Assertion Fails!!!!!


    ...


}

Technical Support Jul 28, 2008 - 12:29 PM

The OnGbwQueryBackColor() virtual method is invoked during grid painting only when the grid control walks through all its visible cells and paints them. The grid rows and columns must not be added/removed during grid painting and, as result, all the grid data accessing during painting will be valid. We suspect your project remembers some grid rows and then uses remembered grid locations in some delayed processing (for instance, some message posting or timer based). In such situation it’s possible that remembered row locations are invalid or removed when delayed processing code is invoked.

Eric Houvenaghel Jul 29, 2008 - 11:00 AM

    I am not removing or adding rows in OnGbwQueryBackColor().

    I am only using the nRowNo parameter (which should be valid) to retrieve the LParam to know what colour to set the row.

    The removal of the rows was performed earlier by a user event.

    The user clicks a button which will then loop though all the rows (hidden or visible).

    Row that contain a certain tag will be removed.

    When I remove a row that is hidden I get a crash.

    Here is what the code looks like:



void MyClass::OnRemoveTagedRows() {

	// Get the list of all childless rows (hidden or visible) currently in the grid.
	std::list< CExtTreeGridCellNode* > listChildlessRows;
	GetChildlessRows(listChildlessRows);

	// Loop through the list of childless rows (hidden or visible) currently in the grid.
	std::list< CExtTreeGridCellNode* >::iterator itTreeNode = listChildlessRows.begin();
	for(; itTreeNode != listChildlessRows.end(); itTreeNode++) {

		// Get the report item.
		// Will be either hidden or visible.
		CExtReportGridItem* pRGI = ReportItemFromTreeItem((HTREEITEM)(*itTreeNode));
		ASSERT(NULL != pRGI);

		// Get the row lparam.
		LParamData* pParam = (LParamData*)pRGI->LParamGet();
		ASSERT(NULL != pParam);

		// Is this row taged for removal.
		if(pParam->m_DoRemove) {

			// Delete the lparam of the row item (hidden or visible).
			DeleteLParamRowDataViaNode(*itTreeNode);

			// Remove the row (hidden or visible).
			ReportItemUnRegister(pRGI, false, false); // CRASHES if row is hidden (i.e. ItemIsHidden() would return true).
		}
	} 
}

Technical Support Jul 30, 2008 - 4:26 AM

Unfortunately, you showed us only one loop from your source code which affects row deletion but we cannot see all the source code that may case the problem. First of all, please ensure the STL’s list of nodes really contains child-less nodes. Only in this case the STL’s forward iterator will not remove the tree nodes which are parent of tree nodes to remove at next steps. If our guess is correct, the crashes will be gone by simply applying the STL’s backward iterator to the loop in the code snippet in your message. Please note, we have really carefully checked the hidden row deletion in various combinations at different indent levels and we was unable to generate crashes.