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 » Growing cell in grid while typing Collapse All
Subject Author Date
Rado Manzela Jul 15, 2010 - 6:25 AM

I need to display and edit long text in grid cell. Text does not contain \r\n, but I need to wrap it to keep cell width and expand/shrink grid’s row as necessary. I’ve tried to apply this style:
ModifyStyleEx(
        __EGCS_EX_AUTO_SIZE_INPLACE_CONTROL|
        __EGCS_EX_WRAP_TEXT
        ,0);
But while typing the edit control expands beyond current cell’s width up to width of whole grid. But there is important column next to edited cell which must not be covered by edit box while typing (it shows length of the text, I’ll need to update it while typing). I need the text to be visible all the time without any scrolling, so current row height must be changed dynamically while typing. Is it possible to achieve this?

Technical Support Jul 19, 2010 - 7:40 AM

The CExtGridWnd::BestFitRow() method measures all the grid cells using the CExtGridCell::OnMeasureBestFitExtent() virtual method which is based on the CExtGridCell::MeasureCell() virtual method. The last method handles the grid cells with wrapped texts correctly:

   if( pWndGrid != NULL && (dwCellStyleEx&(__EGCS_EX_WRAP_TEXT|__EGCS_EX_MULTILINE_TEXT)) != 0L )
            {
                        if( ( dwCellStyleEx & __EGCS_EX_WRAP_TEXT ) != 0L )
                                    nDrawTextFlags |= DT_WORDBREAK;
                        INT nWidth = pWndGrid->OnSiwQueryItemExtentH( nColNo );
                        INT nHeight = 0; //pWndGrid->OnSiwQueryItemExtentV( nRowNo );
                        rcCellTextMeasured = CRect(0,0,nWidth,nHeight);
            }
            else
                        nDrawTextFlags |= DT_SINGLELINE;

This can be verified in the ProfUIS_Controls sample application using the grid cell in the second row of the Text grid column of the Grid dialog page. This grid cell is initialized with the __EGCS_EX_WRAP_TEXT extended grid cell style in the CPageGrid::_InitColumnText() method:
   pCellString1->ModifyStyleEx( __EGCS_EX_WRAP_TEXT );

Double clicking the left header cell separators in this grid control makes the rows automatically resized via the CExtGridWnd::BestFitRow() method:

The grid cells with wrapped texts is the supported feature. The row height is adjusted correctly. All the words became displayed. The method you implemented also works on the Grid dialog page in the ProfUIS_Controls sample application. We tried to add the following into the CPageGrid::CMyGridWnd class:
               virtual void OnGbwResizingStateApply( bool bHorz, LONG nItemNo, INT nItemExtent )
                        {
                                    CExtPPVW < CExtGridWnd > :: OnGbwResizingStateApply( bHorz, nItemNo, nItemExtent );
                                    if( bHorz )
                                    {
                                                for( int row = 0; row < RowCountGet(); ++row )
                                                            BestFitRow( row );
                                    }
                        }
This works and resizes grid cells with wrapped text correctly.
So, we came to the following conclusion: there must be something specific in your project what makes the CExtGridWnd::BestFitRow() method incorrectly or there must be some issue in Prof-UIS but it depends on specific initialization of the grid control in your project. We had to ask you to provide us with more details.

Rado Manzela Jul 19, 2010 - 9:12 AM

I’ve tried to modify your sample, but it does not work too good for me. Please try to initialize cell this way:
pCellString1->TextSet( _T("aaa bbb ccc aaa bbb ccc aaa bbb ccc aaa bbb ccc aaa bbb ccc aaa bbb ccc ") );
and resize column slowly. In some width range where you can see "aaa bbb ccc aaa" in first line, cell shows only 4 lines + 1 pixel of 5th line where you can see only top pixel of the ’bbb’ letters. It works like this in unicode static release, windows XP. Maybe the same thing is causing problems in my application.

When I try unicode debug, even with original sample sometimes it makes corrupted stack message box while scrolling the grid. It is impossible to debug modified sample because of taht message when I start resizing the column.

Rado Manzela Jul 19, 2010 - 9:13 AM

PS I’ve disabled center style     //pCellString1->ModifyStyle( __EGCS_TA_HORZ_CENTER );

Technical Support Jul 19, 2010 - 12:15 PM

Thank you very much for the detailed information. We found two issues related to the wrapped text in the CExtGridCell::MeasureCell() method: the grid lines and text area margins were not used in the measuring algorithm. Please update the source code for the following overloaded version of the CExtGridCell::MeasureCell() method:

CSize CExtGridCell::MeasureCell(
            CExtGridWnd * pWndGrid, // can be NULL
            CDC & dcMeasure,
            LONG nVisibleColNo,
            LONG nVisibleRowNo,
            LONG nColNo,
            LONG nRowNo,
            INT nColType,
            INT nRowType,
            DWORD dwHelperPaintFlags
            ) const
{
            __EXT_DEBUG_GRID_ASSERT_VALID( this );
            __EXT_DEBUG_GRID_ASSERT( dcMeasure.GetSafeHdc() != NULL );
            if( pWndGrid->GetSafeHwnd() == NULL )
                        pWndGrid = NULL;

DWORD dwCellStyle = GetStyle();
DWORD dwCellStyleEx = GetStyleEx();

            // MEASURE ICON SIZE
CSize _sizeIcon = IconGetSize();
            if( _sizeIcon.cx > 0 )
                        _sizeIcon.cx += 2;

            // MEASURE EXISTING TEXT SIZE
UINT nDrawTextFlags = DT_LEFT|DT_TOP|DT_CALCRECT;
CRect rcCellTextMeasured( 0, 0, 0, 0 );
            if( pWndGrid != NULL && (dwCellStyleEx&(__EGCS_EX_WRAP_TEXT|__EGCS_EX_MULTILINE_TEXT)) != 0L )
            {
                        if( ( dwCellStyleEx & __EGCS_EX_WRAP_TEXT ) != 0L )
                                    nDrawTextFlags |= DT_WORDBREAK;
                        INT nWidth = pWndGrid->OnSiwQueryItemExtentH( nColNo );
                        if( pWndGrid->GridLinesVertGet() )
                                    nWidth --;
                        DWORD dwAreaFlags = CExtGridHitTestInfo::CellTypesToAreaFlags( nColType, nRowType );
                        CRect rcTextAreaMargins = OnQueryTextAreaMargins( *pWndGrid, dcMeasure, nVisibleColNo, nVisibleRowNo, nColNo, nRowNo, nColType, nRowType, dwAreaFlags, dwHelperPaintFlags );
                        nWidth -= rcTextAreaMargins.left + rcTextAreaMargins.right;
                        INT nHeight = 0; //pWndGrid->OnSiwQueryItemExtentV( nRowNo );
                        rcCellTextMeasured = CRect(0,0,nWidth,nHeight);
            }
            else
                        nDrawTextFlags |= DT_SINGLELINE;
LPCTSTR strTextBuffer = LPCTSTR( GetTextBuffer() );
int nTextBufferLen = 
                        ( strTextBuffer != NULL )
                                    ? int(_tcslen(strTextBuffer))
                                    : int(0);
HGDIOBJ hOldFont = NULL;
HFONT hCellFont = NULL;
bool bFontMustBeDestroyed = false;
            if( pWndGrid != NULL )
            {
                        hCellFont = OnQueryCellFont( *pWndGrid, nVisibleColNo, nVisibleRowNo, nColNo, nRowNo, nColType, nRowType, 0, bFontMustBeDestroyed, 0 );
                        if( hCellFont == NULL )
                        {
                                    bFontMustBeDestroyed = false;
                                    hCellFont = (HFONT)pWndGrid->OnSiwGetDefaultFont().GetSafeHandle();
                        }
                        if( hCellFont != NULL )
                                    hOldFont = ::SelectObject( dcMeasure, (HGDIOBJ)hCellFont );
            }
            OnAdjustMeasureTextFlags( nDrawTextFlags, nVisibleColNo, nVisibleRowNo, nColNo, nRowNo, nColType, nRowType, 0 );
bool bTextIsMeasured = false;
            if( nTextBufferLen > 0 )
            {
                        CExtRichContentLayout::stat_DrawText(
                                    dcMeasure.m_hDC,
                                    strTextBuffer, nTextBufferLen,
                                    (RECT *)&rcCellTextMeasured,
                                    nDrawTextFlags, 0
                                    );
                        bTextIsMeasured = true;
            } // if( nTextBufferLen > 0 )
            else
            {
                        CExtSafeString strCopy;
                        TextGet( strCopy );
                        if( ! strCopy.IsEmpty() )
                        {
                                    CExtRichContentLayout::stat_DrawText(
                                                dcMeasure.m_hDC,
                                                LPCTSTR( strCopy ), strCopy.GetLength(),
                                                (RECT *)&rcCellTextMeasured,
                                                nDrawTextFlags, 0
                                                );
                                    bTextIsMeasured = true;
                        } // if( ! strCopy.IsEmpty() )
            } // else from if( nTextBufferLen > 0 )
            if( !bTextIsMeasured )
                        rcCellTextMeasured = CRect( 0, 0, 0, 0 );
CRect rcCellTextMeasured2( 0, 0, 0, 0 );
static CExtSafeString g_sTestText( _T("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789;[]{}\\/=+-_*&ˆ%$#@!~") );
            CExtRichContentLayout::stat_DrawText(
                        dcMeasure.m_hDC,
                        LPCTSTR( g_sTestText ), g_sTestText.GetLength(),
                        (RECT *)&rcCellTextMeasured2,
                        nDrawTextFlags, 0
                        );
            if( pWndGrid != NULL && hCellFont != NULL )
                        ::SelectObject( dcMeasure, hOldFont );
            if( bFontMustBeDestroyed && hCellFont != NULL )
                        ::DeleteObject( hCellFont );

INT nAlignHeight = rcCellTextMeasured2.Height();
CSize _sizeText = rcCellTextMeasured.Size();
           _sizeText.cy = max( _sizeText.cy, nAlignHeight );

            if( _sizeText.cx > 0 )
                        _sizeText.cx += 4;
            if( _sizeText.cy > 0 )
                        _sizeText.cy += 4;

            if( pWndGrid != NULL )
            {
                        CRect rcTextAreaMargins = OnQueryTextAreaMargins( *pWndGrid, dcMeasure, nVisibleColNo, nVisibleRowNo, nColNo, nRowNo, nColType, nRowType, 0, 0 );
                        _sizeText.cx += rcTextAreaMargins.left + rcTextAreaMargins.right;
                        _sizeText.cy += rcTextAreaMargins.top + rcTextAreaMargins.bottom;
            }
            else
            {
                        if( _sizeIcon.cx > 0 )
                                    _sizeText.cx += 4;
            }
            // MEASURE BUTTONS SIZE
CSize _sizeAllButtons( 0, 0 );
            if(                     (dwCellStyle&(__EGCS_BUTTON_ELLIPSIS|__EGCS_BUTTON_DROPDOWN|__EGCS_BUTTON_UPDOWN)) != 0
                        &&        (           pWndGrid == NULL
                                    ||           (pWndGrid->BseGetStyle()&__EGWS_BSE_BUTTONS_PERSISTENT) != 0
                                    )
                        &&        ( dwHelperPaintFlags & __EGCPF_SIMPLIFIED_RENDERING_TARGET ) == 0
                        )
            {
                        CSize _sizeOneButton(
                                                ::GetSystemMetrics( SM_CXVSCROLL ),
                                                ::GetSystemMetrics( SM_CYHSCROLL )
                                                );
                        if( (dwCellStyle&__EGCS_BUTTON_ELLIPSIS) != 0 )
                        {
                                    _sizeAllButtons.cx += _sizeOneButton.cx;
                                    _sizeAllButtons.cy = max( _sizeAllButtons.cy, _sizeOneButton.cx );
                        }
                        if( (dwCellStyle&__EGCS_BUTTON_DROPDOWN) != 0 )
                        {
                                    _sizeAllButtons.cx += _sizeOneButton.cx;
                                    _sizeAllButtons.cy = max( _sizeAllButtons.cy, _sizeOneButton.cx );
                        }
                        if( (dwCellStyle&__EGCS_BUTTON_UPDOWN) != 0 )
                        {
                                    _sizeAllButtons.cx += _sizeOneButton.cx;
                                    _sizeAllButtons.cy = max( _sizeAllButtons.cy, _sizeOneButton.cx );
                        }
            }

            // MEASURE CHECK/RADIO SIZE
CSize _sizeCheck( 0, 0 );
            if( (dwCellStyle&__EGCS_CHK_MASK) != 0 )
            {
                        if( pWndGrid != NULL )
                                    _sizeCheck =
                                                OnCalcCheckSize(
                                                            false, false, ( (dwCellStyle&__EGCS_READ_ONLY) == 0 ) ? true : false, *pWndGrid, dcMeasure,
                                                            nVisibleColNo, nVisibleRowNo, nColNo, nRowNo, nColType, nRowType, 0, 0
                                                            );
                        else
                        {
                                    _sizeCheck.cx = 13;
                                    _sizeCheck.cy = 13;
                        }
            }
            
            // MEASURE SORT ARROW SIZE
CSize _sizeSortArrow( 0, 0 );
            if( (dwCellStyle&__EGCS_SORT_ARROW) != 0 )
            {
                        _sizeSortArrow.cx = __EXT_SORT_ARROW_GLYPH_EXTENT_HORZ;
                        _sizeSortArrow.cy = __EXT_SORT_ARROW_GLYPH_EXTENT_VERT;
            }

            // MEASURE FOCUS ARROW SIZE
CSize _sizeFocusArrow( 0, 0 );
            if( (dwCellStyle&(__EGCS_HDR_FOCUS_ARROW_RESERVE_SPACE|__EGCS_HDR_FOCUS_ARROW_DISPLAY)) != 0 )
            {
                        _sizeFocusArrow.cx = __EXT_FOCUS_ARROW_GLYPH_EXTENT_HORZ;
                        _sizeFocusArrow.cy = __EXT_FOCUS_ARROW_GLYPH_EXTENT_VERT;
            }

            // MEASURE ENTIRE SIZE
CSize _sizeMeasured = _sizeIcon;

            _sizeMeasured.cx += _sizeText.cx;
            _sizeMeasured.cx += _sizeAllButtons.cx;
            _sizeMeasured.cx += _sizeCheck.cx;
            _sizeMeasured.cx += _sizeSortArrow.cx;
            _sizeMeasured.cx += _sizeFocusArrow.cx;

            _sizeMeasured.cy = max( _sizeMeasured.cy, _sizeText.cy );
            _sizeMeasured.cy = max( _sizeMeasured.cy, _sizeAllButtons.cy );
            _sizeMeasured.cy = max( _sizeMeasured.cy, _sizeCheck.cy );
            _sizeMeasured.cy = max( _sizeMeasured.cy, _sizeSortArrow.cy );
            _sizeMeasured.cy = max( _sizeMeasured.cy, _sizeFocusArrow.cy );

            return _sizeMeasured;
}

Rado Manzela Jul 20, 2010 - 2:38 AM

Thank you. Next problem is that when cell contains for example 2 lines (resized by BestFitRow()) and width of the column is set as low as possible to keep 2 lines, when you start editing of the cell, only 1 line edit box is created. I guess there will be still some problem with margins. Can you check it please?

I also need the cell to be edited after single click (selections are disabled). I’ve tried to use grid.BseModifyStyle(__EGWS_BSE_EDIT_SINGLE_LCLICK,0); but it seems it is ignored, I still have to use double click

Technical Support Jul 20, 2010 - 9:50 AM

Could you please provide us a screen shot of the grid cell with 2 lines of text and the width of the column is set as low as possible to keep 2 lines? We tried to reproduce this in the ProfUIS_Controls but the editor window always covering entire grid cell. The screen shot will allow us to know the font setting on your computer and exact column width in pixels.

The __EGWS_BSE_EDIT_SINGLE_LCLICK style does not work if the grid control does not use any selection model. Please override CExtGridWnd::OnGbwAnalyzeCellMouseClickEvent() virtual method, hit test the clicked location and start the cell editor. Here is the sample of hit testing and editing code:

CExtGridHitTestInfo htInfo( point );
            HitTest( htInfo, false, true );
            if( htInfo.IsHoverEmpty() || ( ! htInfo.IsValidRect() ) )
                        return . . . // clicked location is nowhere
INT nColType = htInfo.GetInnerOuterTypeOfColumn(), nRowType = htInfo.GetInnerOuterTypeOfRow();
            if( nColType != 0 || nRowType != 0 )
                        return . . . // clicked location is outer header area
            return
                        OnGbwBeginEdit(
                                    htInfo.m_nVisibleColNo, htInfo.m_nVisibleRowNo, htInfo.m_nColNo, htInfo.m_nRowNo, nColType,
                                    nRowType, htInfo.m_rcExtra, htInfo.m_rcItem, CRect(0,0,0,0), true, NULL, GetSafeHwnd()
                                    ); 




Technical Support Jul 15, 2010 - 12:35 PM

The __EGCS_EX_AUTO_SIZE_INPLACE_CONTROL extended grid cell style expands the editor window only horizontally and never vertically. You don’t need it.
The __EGCS_EX_WRAP_TEXT extended grid cell style makes the long single line text wrapped into multiple lines both in the cells area inside grid control and in the in-place activated cell editor control. But it does not change the row height and in-place editor height while typing. Besides, the cell’s text is not changed until you finished typing. This means the row height cannot be re-measured. So, you should override the CExtGridCell::OnInplaceControlTextInputVerify or CExtGridWnd::OnGridCellInplaceControlTextInputVerify() virtual method, re-measure the editor’s text, move the editor window and change the row height. The row height can be changed automatically if you assign the typed text to grid cell and use the CExtGridWnd::BestFitRow() method.

Rado Manzela Jul 19, 2010 - 2:48 AM

Ive tried this but it seems CExtGridWnd::BestFitRow() with __EGCS_EX_WRAP_TEXT is buggy. Just when I set some string to cell - for example "aaa bbb ccc", use this override:

void CDescGrid::OnGbwResizingStateApply(
    bool bHorz,
        LONG nItemNo,
        INT nItemExtent
        )
{
    __super::OnGbwResizingStateApply(bHorz,nItemNo,nItemExtent);
    for (int row=0; row<RowCountGet(); ++row)
    {
        BestFitRow(row);
    }
}

when I resize the column width to be maybe 1 pixel narrower than required, it does not draw the last word and keeps it 1 line high. I think it should resize the row to 2 lines and draw last word to second line.