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 » ItemFocusSet crashes after CExtTreeGridWnd is re-populated Collapse All
Subject Author Date
Bart Kampers Feb 4, 2008 - 4:30 AM

Hello,

I found that CExtTreeGridWnd::ItemFocusSet crashes when I remove all children from a tree, then re-populate it and set the focus to the first child.

The code below only works the first time I invoke it. The second time it chrashes except when the user does not change the focus manualy.




ItemRemove(ItemGetRoot(), false, false);

Populate(); // Populates the CExtTreeGridWnd and ensures that the root has one child

HTREEITEM focused = ItemGetFirstChild(ItemGetRoot());
ItemFocusSet(focused, NAME_COLUMN, false);



Does someone have some clue?


Kind regards.

Technical Support Feb 6, 2008 - 11:16 AM

Could you e-mail us this project to the support mail box at this web site?

Bart Kampers Feb 6, 2008 - 1:20 AM

I remove rows by "ItemRemove(ItemGetRoot(), false, false)" just before populating the tree (see first posting).

I made a small project that illustrates this problem. Here is the cpp file where the tree is (re)built. I can send you the project in a zip file if you tell me where to send it to.

Thanks in advance.

// test_profuis_treegridDlg.cpp : implementation file
//

#include "stdafx.h"
#include "test_profuis_treegrid.h"
#include "test_profuis_treegridDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Ctest_profuis_treegridDlg dialog


void CTestGrid::Init()
{
SiwModifyStyle(
__ESIS_STH_PIXEL | __ESIS_STV_ITEM | __EGBS_SFM_FULL_ROWS |
__EGBS_RESIZING_CELLS_OUTER_H | __EGBS_RESIZING_CELLS_INNER_H | __EGBS_DYNAMIC_RESIZING_H |
__EGBS_MULTI_AREA_SELECTION | __EGBS_NO_HIDE_SELECTION |
__EGBS_GRIDLINES | __EGBS_LBEXT_SELECTION,
0,
false);
HoverEventsSet(true, true);
    OuterRowCountTopSet(1, false);
    ColumnAdd(1, false);

CRect rect;
GetClientRect(rect);
    CExtGridCellHeader * headerCell =    STATIC_DOWNCAST(CExtGridCellHeader, GridCellGetOuterAtTop(0, 0, RUNTIME_CLASS(CExtGridCellHeader)));
headerCell->ExtentSet(rect.Width());
headerCell->TextSet(_T("Name"));

Fill(10);
}

void CTestGrid::Fill(int pNrRows)
{
for (int i = 0; i < pNrRows; i++)
{
HTREEITEM item = ItemInsert(ItemGetRoot());
CExtGridCellString* cell = (CExtGridCellString*) ItemGetCell(item, 0, 0, RUNTIME_CLASS(CExtGridCellString));
cell->TextSet(_T("Press ’Broken’ to trigger the bug"));
cell->ModifyStyle(__EGCS_NO_INPLACE_CONTROL);
{
HTREEITEM childItem = ItemInsert(item);
CExtGridCellString* cell = (CExtGridCellString*) ItemGetCell(childItem, 0, 0, RUNTIME_CLASS(CExtGridCellString));
cell->TextSet(_T("Press ’Fixed’ to run the *fixed* code"));
cell->ModifyStyle(__EGCS_NO_INPLACE_CONTROL);

if (i == pNrRows-1)
mFocusItem = childItem;
}
}
}

void CTestGrid::Refill(bool pBroken)
{
// remove all
ItemRemove(ItemGetRoot(), false, true);

// make 10 rows
Fill(10);

// and set the focus to the last row
ItemEnsureExpanded(mFocusItem, true);
ItemEnsureVisibleBranch(mFocusItem, true);
ItemFocusSet(mFocusItem, 0, true);

CPoint p = FocusGet();
// p unequal (-1, -1), which is OK.

ItemRemove(ItemGetRoot(), false, true);
// At this point, the grid should be entirely empty and the focus should automatically be lost.

p = FocusGet();
// p should be (-1, -1) as the focused item no longer exists.

if (!pBroken)
{
// FIX: remove focus
CPoint previousFocus = FocusSet(CPoint(-1,-1));
}

// fill with less rows then before
Fill(4);

HTREEITEM focused = ItemGetFirstChild(ItemGetRoot());

// This will assert in prof-uis 2.81:
ItemFocusSet(focused, 0, true); // will try to do something with the old, broken focused item.
}



/////////////////////////////////////////////////////////////////////////////////////////////

Ctest_profuis_treegridDlg::Ctest_profuis_treegridDlg(CWnd* pParent /*=NULL*/)
    : CDialog(Ctest_profuis_treegridDlg::IDD, pParent)
{

}

void Ctest_profuis_treegridDlg::DoDataExchange(CDataExchange* pDX)
{
    __super::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(Ctest_profuis_treegridDlg, CDialog)
ON_BN_CLICKED(IDC_BUTTON_BROKEN, &Ctest_profuis_treegridDlg::OnBnClickedButtonBroken)
ON_BN_CLICKED(IDC_BUTTON_FIXED, &Ctest_profuis_treegridDlg::OnBnClickedButtonFixed)
END_MESSAGE_MAP()


// Ctest_profuis_treegridDlg message handlers

BOOL Ctest_profuis_treegridDlg::OnInitDialog()
{
    __super::OnInitDialog();

CRect rect;
    GetDlgItem(IDC_GRID_PLACEHOLDER)->GetWindowRect(rect);
ScreenToClient(rect);

mGrid.Create(this, rect, 1234);
mGrid.Init();
mGrid.Invalidate();

    return TRUE; // return TRUE unless you set the focus to a control
}



void Ctest_profuis_treegridDlg::OnBnClickedButtonBroken()
{
mGrid.Refill(true);
}

void Ctest_profuis_treegridDlg::OnBnClickedButtonFixed()
{
mGrid.Refill(false);
}

Technical Support Feb 5, 2008 - 12:00 PM

We cannot see anything that would remove tree rows in your code snippets. These code snippets are only initializing grid cells. Please try to use ASSERT_VALID for returned cell pointers after each invocation of the ItemGetCell() method. Please also ensure your code removes tree rows using the CExtTreeGridWnd::ItemRemove() method. To remove all items, you should remove all child items of the root item.

Bart Kampers Feb 5, 2008 - 3:45 AM

This is the code that initializes the TreeGrid. It is execute only once.

SiwModifyStyle(
__ESIS_STH_PIXEL | __ESIS_STV_ITEM |
__EGBS_RESIZING_CELLS_OUTER_H | __EGBS_RESIZING_CELLS_INNER_H | __EGBS_DYNAMIC_RESIZING_H |
__EGBS_SFM_FULL_ROWS | __EGBS_NO_HIDE_SELECTION | __EGBS_GRIDLINES,
0,
false);
OuterRowCountTopSet(1, false);
ColumnAdd(NUMBER_OF_TUPLE_COLUMNS, false);
for (LONG column = 0; column < NUMBER_OF_TUPLE_COLUMNS; column++)
{
CExtGridCellHeader * headerCell = STATIC_DOWNCAST(CExtGridCellHeader, GridCellGetOuterAtTop(column, 0, RUNTIME_CLASS(CExtGridCellHeader)));
headerCell->ExtentSet(COLUMN_WIDTH);
switch (column)
{
case TUPLE_NAME_COLUMN : headerCell->TextSet(_T("Tuple")); break;
case TUPLE_VALUE_COLUMN : headerCell->TextSet(_T("Value")); break;
}
}


Here are methods which Poputalte() calls to insert cells:


to fill the first column
HTREEITEM CTupleTreeGrid::ObjectItemInsert(HTREEITEM pParentItem, const CBlockDataObject* pBlockDataObject, uint32 pIndex, size_t pSize)
{
HTREEITEM childItem = NULL;
if ((pParentItem != NULL) && (pBlockDataObject != NULL))
{
childItem = ItemInsert(pParentItem);
CExtGridCellString* cell = (CExtGridCellString*) ItemGetCell(childItem, TUPLE_NAME_COLUMN, 0, RUNTIME_CLASS(CExtGridCellString));
const std::string* nameStdString = pBlockDataObject->GetNameId();
CString nameCString;
COLORREF color;
if (nameStdString != NULL)
{
nameCString.Format(_T("%s"), CA2T(nameStdString->c_str()));
color = DEFAULT_TEXT_COLORREF;
}
else
{
nameCString = "?";
color = UNKNOWN_NAME_TEXT_COLORREF;
}
if (pSize > 0)
{
CString indexCString;
indexCString.Format(_T("[%d/%d]"), pIndex, pSize);
nameCString += indexCString;
}
cell->TextSet(nameCString);
cell->TextColorSet(CExtGridCell::__ECS_NORMAL, color);
cell->ModifyStyle(__EGCS_NO_INPLACE_CONTROL);
cell->LParamSet((LPARAM) pBlockDataObject);
}
return childItem;
}


To fill the second column:

CString dataCString;
dataCString.Format(_T("%s"), CA2T(dataStdString.c_str()));
CExtGridCellString* cell = (CExtGridCellString*) mTree->ItemGetCell(childItem, TUPLE_VALUE_COLUMN, 0, RUNTIME_CLASS(CExtGridCellString));
cell->TextSet(dataCString);
cell->ModifyStyle(__EGCS_NO_INPLACE_CONTROL);

Technical Support Feb 4, 2008 - 10:12 AM

Could you show the code that removes and re-initializes the tree in your project? We need to know the exact way that would allow us to re-produce this crash.