// Hack for AutoSizeRowEx()...
CSize CGridCellMultiLine::GetCellExtentEx(int width, CDC*pDC)
{
	CSize ImageSize(0,0);
	
	int nImage = GetImage();
	if (nImage >= 0) 
	{
		CGridCtrl* pGrid = GetGrid();
		ASSERT(pGrid);
		
		if (pGrid->GetImageList()) 
		{
			IMAGEINFO Info;
			if (pGrid->GetImageList()->GetImageInfo(nImage, &Info))
				ImageSize = CSize(Info.rcImage.right-Info.rcImage.left+1, 
				Info.rcImage.bottom-Info.rcImage.top+1);
		}
	}
	
	
	CSize size = GetTextExtentEx(width - ImageSize.cx, GetText(), pDC);

	CSize retSize(size.cx + ImageSize.cx, max(size.cy, ImageSize.cy));

	return retSize;
}
int CGridTreeCellBase::GetTreeIndent()
// returns:  device units to indent within a cell for a tree at this level
{
    ASSERT( m_pTreeColumn != NULL);
    CGridCtrl* pGridCtrl = GetGrid();
    ASSERT( pGridCtrl != NULL);
    unsigned char ucLevel = GetLevel();

    if( ucLevel == 0)
        return 0;

    if( !m_pTreeColumn->GetTreeLines() )
        ucLevel--;

    return (m_pTreeColumn->GetDefTreeIndent() * ucLevel) + (pGridCtrl->GetDefCellMargin() * 2);
}
예제 #3
0
int CGridBtnCellBase::RelPointInCtl(    const CPoint& arPoint)  // Relative point coords
// returns:  Index of control that this point is within bounds of or -1 if no control matches
{
    CGridCtrl* pGrid = GetGrid();
    ASSERT( pGrid);

    CRect RectCell;
    if( pGrid->GetCellRect( m_iRow,
                            m_iCol,
                            &RectCell) )
    {
        ASSERT( MAX_NBR_CTLS_INCELL > GetDrawCtlNbrMax() ); // whoa!
        CRect RectAry[ MAX_NBR_CTLS_INCELL];

        if( CalcDrawCtlRects(   RectAry,    // returns:  CRects with coordinates
                                            //  last entry has optional leftover rect
                                            //  available for text, etc.
                                MAX_NBR_CTLS_INCELL,// nbr of Rects in above array
                                RectCell) ) // cell rectangle to work with
        {
            const int iCtlNbr = GetDrawCtlNbr();

            // make point absolute coord
            CPoint pointAbs;
            pointAbs.x = arPoint.x + RectCell.left;
            pointAbs.y = arPoint.y + RectCell.top;

            for( int i1=0; i1 < iCtlNbr; i1++)
            {
                if( pointAbs.x >= RectAry[i1].left
                    && pointAbs.x <= RectAry[i1].right
                    && pointAbs.y >= RectAry[i1].top
                    && pointAbs.y <= RectAry[i1].bottom)
                {
                    return i1;  // found it
                }

            }
        }
    }
    return -1;
}
예제 #4
0
BOOL CGridBtnCellBase::HasCellText()
// returns:  F=auto-size buttons, only
{
    CGridCtrl* pGrid = GetGrid();
    ASSERT( pGrid);

    CRect RectCell;
    if( !pGrid->GetCellRect(m_iRow,
                            m_iCol,
                            &RectCell) )
        return FALSE;

    // rather than see if there is text assigned, check if any
    //  space allocated for text
    CRect RectText( RectCell);
    if( !GetTextRect( &RectText) ) // i/o:  i=dims of cell rect; o=dims of text rect
        return FALSE;

    if( RectText.Width() > 0 )
        return TRUE;

    return FALSE;
}
예제 #5
0
void CGridBtnCellCombo::OnClick( CPoint PointCellRelative)
{
    // immediately edit if user clicked on scroll down button picture

    int iCtlHit = RelPointInCtl( PointCellRelative);  // Relative point coords
    // returns:  Index of control that this point is within bounds of or -1 if no control matches

    BOOL bHitScrollDown = FALSE;
    if( iCtlHit >= 0)
    {
        // if user clicked on scroll down button picture, then show
        //  the drop-down, too

        UINT uiType = GetDrawCtlType( iCtlHit);
        UINT uiState = GetDrawCtlState( iCtlHit);

        bHitScrollDown =    ( uiType == DFC_SCROLL)
                            && uiState & DFCS_SCROLLDOWN;
    }
    if( bHitScrollDown)
    {
        // invoke the edit, now -- similar to CGridCtl::OnEditCell() logic
        CGridCtrl* pGrid = GetGrid();
        ASSERT( pGrid != NULL);

        CRect rect;
        if (!pGrid->GetCellRect( m_iRow, m_iCol, rect))
            return;

        SendMessageToParent(m_iRow, m_iCol, GVN_BEGINLABELEDIT);

        Edit( m_iRow, m_iCol, rect, PointCellRelative, IDC_INPLACE_CONTROL, VK_LBUTTON);
        return;
    }

    CGridBtnCell::OnClick( PointCellRelative);
}
예제 #6
0
// EFW - Various changes to make it draw cells better when using alternate
// color schemes.  Also removed printing references as that's now done
// by PrintCell() and fixed the sort marker so that it doesn't draw out
// of bounds.
BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect,  BOOL bEraseBkgnd /*=TRUE*/)
{
    // Note - all through this function we totally brutalise 'rect'. Do not
    // depend on it's value being that which was passed in.
//Used for merge cells
	//by Huang Wei
	if(	m_Hide && !IsMerged())
	{
		return TRUE;
	}

    CGridCtrl* pGrid = GetGrid();
    ASSERT(pGrid);

    if (!pGrid || !pDC)
        return FALSE;

    if( rect.Width() <= 0 || rect.Height() <= 0)  // prevents imagelist item from drawing even
        return FALSE;                             //  though cell is hidden

    //TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol);

    int nSavedDC = pDC->SaveDC();
    pDC->SetBkMode(TRANSPARENT);

    // Get the default cell implementation for this kind of cell. We use it if this cell
    // has anything marked as "default"
    CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
    if (!pDefaultCell)
        return FALSE;

    // Set up text and background colours
    COLORREF TextClr, TextBkClr;

    TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr();
    if (GetBackClr() == CLR_DEFAULT)
        TextBkClr = pDefaultCell->GetBackClr();
    else
    {
        bEraseBkgnd = TRUE;
        TextBkClr = GetBackClr();
    }

    // Draw cell background and highlighting (if necessary)
    if ( IsFocused() || IsDropHighlighted() )
    {
        // Always draw even in list mode so that we can tell where the
        // cursor is at.  Use the highlight colors though.
        if(GetState() & GVIS_SELECTED)
        {
            TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT);
            TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
            bEraseBkgnd = TRUE;
        }

        rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
        if (bEraseBkgnd)
        {
            TRY 
            {
                CBrush brush(TextBkClr);
                pDC->FillRect(rect, &brush);
            } 
            CATCH(CResourceException, e)
            {
                //e->ReportError();
            }
            END_CATCH
        }

        // Don't adjust frame rect if no grid lines so that the
        // whole cell is enclosed.
        if(pGrid->GetGridLines() != GVL_NONE)
        {
            rect.right--;
            rect.bottom--;
        }

        if (pGrid->GetFrameFocusCell())
        {
                // Use same color as text to outline the cell so that it shows
                // up if the background is black.
            TRY 
            {
                CBrush brush(TextClr);
                pDC->FrameRect(rect, &brush);
            }
            CATCH(CResourceException, e)
            {
                //e->ReportError();
            }
            END_CATCH
        }
        pDC->SetTextColor(TextClr);

        // Adjust rect after frame draw if no grid lines
        if(pGrid->GetGridLines() == GVL_NONE)
        {
            rect.right--;
            rect.bottom--;
        }

		//rect.DeflateRect(0,1,1,1);  - Removed by Yogurt
    }
예제 #7
0
/*****************************************************************************
Called during all the mouse events associated with clicking a control
embedded within a cell.  Override to have more elaborate handling like
implementing radio button logic.

*****************************************************************************/
BOOL CGridBtnCellBase::ClickedCellCtl(  UINT uMsg,      // Command that invoked.  e.g. WM_LBUTTONDOWN
                                        int aiWhich)    // zero-based index of image to draw
// returns:  T=redraw occurred / F=no redraw
{
    if( aiWhich < 0
        || aiWhich >= GetDrawCtlNbrMax() )
    {
        ASSERT( FALSE);
        return FALSE;
    }

    UINT uiState = GetDrawCtlState( aiWhich);
    if( uiState & DFCS_INACTIVE)
        return FALSE;   // button is inactive -- don't do anything

    m_sLastCtlClicked = (short)aiWhich;
    UINT iType = GetDrawCtlType( aiWhich);

    switch( uMsg)
    {
        case WM_LBUTTONDOWN:
            // appears pushed in
            uiState |= DFCS_PUSHED;
            SetDrawCtlState( aiWhich, uiState);
            break;

        case WM_LBUTTONUP:
        case WM_LBUTTONDBLCLK:
            // appears pushed out
            uiState &= (~DFCS_PUSHED);

            // auto check / uncheck controls, too
            if( iType == DFC_BUTTON )
            {
                BOOL bIsMbrRadioGrp = GetDrawCtlIsMbrRadioGrp( aiWhich);

                if( uiState & DFCS_BUTTONRADIO
                    || bIsMbrRadioGrp )
                {
                    // radio buttons or any button flagged as being part
                    //  of a radio group will be made to look pressed down
                    //  while pushing-up / unchecking all other members
                    //  of the radio group

                    const int iCtlNbr = GetDrawCtlNbr();
                    UINT uiStateRadio;

                    for( int i1=0; i1 < iCtlNbr; i1++)
                    {
                        if( i1 != aiWhich)
                        {
                            uiStateRadio = GetDrawCtlState( i1);
                            bIsMbrRadioGrp = GetDrawCtlIsMbrRadioGrp( i1);

                            if( uiStateRadio & DFCS_BUTTONRADIO
                                || bIsMbrRadioGrp )
                            {
                                uiStateRadio &= (~( DFCS_PUSHED | DFCS_CHECKED)  );
                                                    // push out and uncheck
                                SetDrawCtlState( i1, uiStateRadio);
                            }
                        }
                    }
                    uiState |= DFCS_CHECKED;  // check
                    if( !(uiState & DFCS_BUTTONRADIO) )
                        uiState |= DFCS_PUSHED;  // press in if not real radio button

                }
                else if(  !( uiState & ALL_BUT_BTN_CHK)  )
                {
                    // not a pushbutton -- it's a check box
                    //  (can't check for DFCS_BUTTONCHECK directly since it is bit 0)
                    if( uiState & DFCS_CHECKED)
                        uiState &= (~DFCS_CHECKED); // uncheck
                    else
                        uiState |= DFCS_CHECKED;    // check
                }
            }

            SetDrawCtlState( aiWhich, uiState);
            break;

        default:
            ASSERT( FALSE); // gotta handle new message
            return FALSE;
    }

    CGridCtrl* pGrid = GetGrid();
    ASSERT( pGrid);

    pGrid->RedrawCell( m_iRow, m_iCol);

    return TRUE;
}
// This hack allows you to determine the height that a cell should be in order to display
// stuff properly in the given width.
CSize CGridCellMultiLine::GetTextExtentEx(int width, LPCTSTR szText, CDC* pDC /*= NULL*/)
{
	CGridCtrl* pGrid = GetGrid();
	ASSERT(pGrid);
	
	BOOL bReleaseDC = FALSE;
	if (pDC == NULL)
	{
		pDC = pGrid->GetDC();
		if (!pDC) 
		{
			CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell();
			ASSERT(pDefCell);
			return CSize(pDefCell->GetWidth(), pDefCell->GetHeight());
		}
		bReleaseDC = TRUE;
	}
	
	CFont *pOldFont = NULL,
	*pFont = GetFontObject();
	if (pFont)
		pOldFont = pDC->SelectObject(pFont);
	
	CSize size;
	int nFormat = GetFormat();
	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);

	int textWidth = width - (4*GetMargin ());

	// corrects the bug if resizing column gives a text width smaller than (4*Getmargin())
	if (textWidth <= 0) 
	{
		textWidth = 1;
	}
	
	// If the cell is a multiline cell, then use the width of the cell
	// to get the height
	if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE))
	{
		CRect rect;
		rect.SetRect(0, 0, textWidth, 0);
		pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT);

		size.cx = rect.Width ();
		size.cy = rect.Height ();
	}
	else
		size = pDC->GetTextExtent(szText, _tcslen(szText));
	
	size.cx += (tm.tmOverhang);
	
	if (pOldFont)
		pDC->SelectObject(pOldFont);
	
	size += CSize(4*GetMargin(), 2*GetMargin());
	
	// Kludge for vertical text
	LOGFONT *pLF = GetFont();
	if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900)
	{
		int nTemp = size.cx;
		size.cx = size.cy;
		size.cy = nTemp;
		size += CSize(0, 4*GetMargin());
	}
	
	if (bReleaseDC)
		pGrid->ReleaseDC(pDC);
	
	return size;
}
예제 #9
0
BOOL CSListView::SetAverageItem( CGridCtrl &grid, CStockContainer & container, BOOL bRedraw )
{
	if( grid.GetColumnCount() <= 0 )
		return FALSE;

	container.Lock();

	// Get LPARAM
	CUIntArray	anParams;
	anParams.SetSize( 0, grid.GetColumnCount() );
	for( int nCol=0; nCol < grid.GetColumnCount(); nCol ++ )
	{
		LPARAM	lParam	=	grid.GetItemData( 0, nCol );
		anParams.Add( lParam );
	}

	// Set Average
	CStockInfo & infoAve = container.GetAverage( );
	CStockInfo & infoWAve = container.GetWeightAverage( );
	int	iRowAve=0, iRowWAve=0;

	if( grid.GetRowCount() >= 3
		&& grid.GetItemData(grid.GetRowCount()-2,0) == (LPARAM)ID_STOCKCNTN_AVERAGE
		&& grid.GetItemData(grid.GetRowCount()-1,0) == (LPARAM)ID_STOCKCNTN_WEIGHTAVERAGE )
	{
		// get item id
		iRowAve		=	grid.GetRowCount()-2;
		iRowWAve	=	grid.GetRowCount()-1;
	}
	else
	{
		// Insert item
		iRowAve = grid.InsertRow( infoAve.GetStockName() );
		grid.SetItemData( iRowAve, 0, (LPARAM)ID_STOCKCNTN_AVERAGE );
		iRowWAve = grid.InsertRow( infoWAve.GetStockName() );
		grid.SetItemData( iRowWAve, 0, (LPARAM)ID_STOCKCNTN_WEIGHTAVERAGE );
	}

	// Set Average
	for( nCol=0; nCol<anParams.GetSize(); nCol++ )
	{
		grid.SetItemText( iRowAve, nCol, AfxGetVariantDispString(anParams[nCol], infoAve, NULL) );
		grid.SetItemBkColour( iRowAve, nCol, AfxGetProfile().GetColor(CColorClass::clrSListBK) );
		grid.SetItemFgColour( iRowAve, nCol, AfxGetVariantColor( anParams[nCol], infoAve ) );
	}

	// Set Weight Average
	for( nCol=0; nCol<anParams.GetSize(); nCol++ )
	{
		grid.SetItemText( iRowWAve, nCol, AfxGetVariantDispString(anParams[nCol], infoWAve, NULL) );
		grid.SetItemBkColour( iRowWAve, nCol, AfxGetProfile().GetColor(CColorClass::clrSListBK) );
		grid.SetItemFgColour( iRowWAve, nCol, AfxGetVariantColor( anParams[nCol], infoWAve ) );
	}

	//	Set Param which is
	//	SLH_MARKETVALUE, SLH_MARKETVALUEA, SLH_MARKETVALUEB and etc,  and more than SLH_USERDEFINE_BEGIN
	for( nCol=0; nCol < anParams.GetSize(); nCol ++ )
	{
		UINT	lParam	=	anParams[nCol];
		if( SLH_DIFF == lParam || SLH_DIFFPERCENT == lParam || SLH_SCOPE == lParam
			|| SLH_DIFFPERCENT_MIN5 == lParam || SLH_PE == lParam
			|| SLH_PMAININCOME == lParam || SLH_RATIO_PCASH == lParam
			|| SLH_RATIO_CURRENCY == lParam || SLH_RATIO_CHANGEHAND == lParam
			|| SLH_RATIO_VOLUME == lParam || SLH_RS == lParam
			|| SLH_MARKETVALUE == lParam || SLH_MARKETVALUEA == lParam
			|| SLH_MARKETVALUEB == lParam || lParam >= SLH_USERDEFINE_BEGIN )
		{
			double	dc = 0., average = 0.;
			double	wsum = 0.0001, waverage = 0., w = 0.;
			for( int iRow=1; iRow<grid.GetRowCount(); iRow++ )
			{
				if( iRow == iRowAve || iRow == iRowWAve )
					continue;

				int	id	=	grid.GetItemData(iRow,0);
				if( id < 0 || id > container.GetSize() )
					continue;

				CStockInfo	& info = container.ElementAt(id);
				w	=	info.m_fShare_count_total;
				double	dValue	=	0.;
				if( !AfxGetVariantValue( lParam, info, &dValue, &container ) )
					continue;

				average		=	(average * dc + dValue)/(dc+1);
				waverage	=	(waverage * wsum + dValue * w)/(wsum+w);

				dc		+=	1;
				wsum	+=	w;
			}

			CString	strText;
			if( SLH_MARKETVALUE == lParam || SLH_MARKETVALUEA == lParam || SLH_MARKETVALUEB == lParam )
			{
				strText.Format( "%u", (DWORD)average );
				grid.SetItemText( iRowAve, nCol, strText );
				grid.SetItemText( iRowWAve, nCol, "-" );
			}
			else
			{
				strText.Format( "%.2f", average );
				grid.SetItemText( iRowAve, nCol, strText );
				strText.Format( "%.2f", waverage );
				grid.SetItemText( iRowWAve, nCol, strText );
			}
		}
	}

	container.UnLock();

	if( bRedraw )
	{
		grid.RedrawRow( iRowAve );
		grid.RedrawRow( iRowWAve );
	}
	return TRUE;
}
/*****************************************************************************
Allows Tree + Btn object to call drawing member

*****************************************************************************/
BOOL CGridTreeCellBase::DrawTreeCell(CDC* pDC, int nRow, int nCol, CRect* prect,
    BOOL /* bEraseBkgnd */)
{
    ASSERT( m_pTreeColumn != NULL);

    if( !m_pTreeColumn->GetAllowDraw())
        return FALSE;

    CGridCtrl* pGrid = GetGrid();

    if (!pGrid || !pDC)
        return FALSE;

    if( m_pTreeColumn->GetFixedRowCount() != pGrid->GetFixedRowCount()
        || m_pTreeColumn->GetRowCount() > pGrid->GetRowCount() )
    {
        ASSERT( FALSE); // if ASSERT here, this means that you a tree in a column
                        //  but you called CGridCtrl::SetFixedRowCount() or
                        //  or CGridCtrl::SetRowCount() directly.  You can't do this.
                        //  To change the layout of rows when you are using the tree,
                        //  you must call CTreeColumn::Setup().
        return FALSE;
    }

    if( prect->Width() <= 0
        || prect->Height() <= 0)  // prevents imagelist item from drawing even
        return FALSE;           //  though cell is hidden

    // tree drawing graphic logic begins here

    int nSavedDC = pDC->SaveDC();

    if( nCol == m_pTreeColumn->GetColumnWithTree())
    {
        // this column has a tree

        // move text over to allow for level indentation
        if( IsViewable() )
        {
            // if row is showing, draw the tree graphic
            if( m_pTreeColumn->GetTreeLines())
            {
                TreeDrawGraphic(    pDC,      // current CDC
                                    *prect);    // coordinates of bounding cell rectangle
            }
            else if( m_pTreeColumn->GetTreeUsesImages())
            {
                TREE_IMAGE TreeImage = TREE_IMAGE_DOCUMENT;

                // is it not the very last row?
                if( nRow + m_pTreeColumn->GetFixedRowCount() < m_pTreeColumn->GetRowCount())
                {
                    // is it a plus or minus?
                    BOOL bIsPlus;
                    BOOL bIsMinus;
                    BOOL bIsLastLeaf;

                    if( m_pTreeColumn->TreeCellHasPlusMinus(   nRow,        // row of Cell to check
                                                &bIsPlus,    // returns:  T=Is a plus
                                                &bIsMinus,   // returns:  T=Is a minus
                                                &bIsLastLeaf) )// returns:  T=Is Last Leaf
                    {
                        // returns:  T=cell has a plus or minus;  F=not
                        if( bIsPlus)
                            TreeImage = TREE_IMAGE_FOLDER_CLOSED;
                        else
                            TreeImage = TREE_IMAGE_FOLDER_OPEN;
                    }
                }
                SetImage( TreeImage);
            }
        }

        prect->left += GetTreeIndent();

    }
    pDC->RestoreDC(nSavedDC);
    return TRUE;
}
/*****************************************************************************
Draws "+", "-" and lines that show a tree graphic

*****************************************************************************/
void CGridTreeCellBase::TreeDrawGraphic(CDC* apDC,      // current CDC
                                    CRect aRect)    // coordinates of bounding cell rectangle
{
    ASSERT( apDC != NULL);
    ASSERT( m_pTreeColumn != NULL);
    ASSERT( m_pTreeColumn->GetAllowDraw());

    int iNbrTreeElements = m_pTreeColumn->GetRowCount() - m_pTreeColumn->GetFixedRowCount();

    // get current level
    unsigned char ucLevelCurrent = GetLevel();
    ASSERT( IsViewable() ); // can't deal with hidden rows!
    if( ucLevelCurrent <= 0)
    {
        if( m_pTreeColumn->GetTreeUsesImages())
            SetImage( TREE_IMAGE_DOCUMENT);
        return;     // no + / - box if level 0
    }

    BOOL bIsNextShowing;
    unsigned char ucLevelNext;
    int iLineStop;


    if( m_pTreeColumn->GetDefTreeIndent() < TREE_BOX_MARGIN * 3)
        return; // too small to draw the graphic

    CRect RectRel;
    TreeGetBoxRelCoords( &RectRel);      // returns: relative coordinates
    CRect RectBox( RectRel);
    RectBox.OffsetRect( aRect.left, aRect.top);

    int iXCenter = RectBox.left + ( (RectBox.right - RectBox.left) / 2);
    int iYCenter = RectBox.top + ( (RectBox.bottom - RectBox.top) / 2);

    CPen psPen(PS_SOLID, 1, m_pTreeColumn->GetTreeLineColor() );
    CPen* pOldPen = apDC->SelectObject(&psPen);

    TREE_IMAGE TreeImage = TREE_IMAGE_DOCUMENT;

    // is it the very last row?
    if( !GetForcePlus()  &&  m_iRow >= m_pTreeColumn->GetRowCount() - 1)
    {
        iXCenter -= m_pTreeColumn->GetDefTreeIndent();

        // draw |__ (with long horizontal)
        if( TryMoveTo( aRect, apDC, iXCenter, aRect.top) )
            if( TryLineTo( aRect, apDC, iXCenter, iYCenter) )
                TryLineTo( aRect, apDC, RectBox.right, iYCenter);

        apDC->SelectObject(pOldPen);
        if( m_pTreeColumn->GetTreeUsesImages())
            SetImage( TreeImage);
        return;
    }

    // is it a plus or minus?  Check up to all remaining entries for an answer
    BOOL bIsPlus;
    BOOL bIsMinus;
    BOOL bIsLastLeaf;
    CGridCtrl* pGrid = GetGrid();
    ASSERT( pGrid != NULL);

    int iVertLineBottom = aRect.bottom + 1; // if drawing a horizontal line,
                                            //  overwrite the grid line in case it is
                                            //  not displayed

    BOOL bIsBranch = m_pTreeColumn->TreeCellHasPlusMinus(
                                m_iRow,          // row of Cell to check
                                &bIsPlus,    // returns:  T=Is a plus
                                &bIsMinus,   // returns:  T=Is a minus
                                &bIsLastLeaf);// returns:  T=Is Last Leaf

    if( bIsBranch )
    {
        // returns:  T=cell has a plus or minus;  F=not

        if( bIsPlus)
            TreeImage = TREE_IMAGE_FOLDER_CLOSED;
        else
            TreeImage = TREE_IMAGE_FOLDER_OPEN;

        // draw a square box
        BOOL bCanDrawRectangle =    aRect.PtInRect( CPoint( RectBox.left, RectBox.top ))
                                    && aRect.PtInRect( CPoint( RectBox.right, RectBox.bottom ));

        if( bCanDrawRectangle )
        {
            apDC->Rectangle(    RectBox.left,
                                RectBox.top,
                                RectBox.right,
                                RectBox.bottom);
        }

        // draw a minus sign
        if( TryMoveTo( aRect, apDC, RectBox.left + TREE_BOX_MARGIN, iYCenter) )
            TryLineTo( aRect, apDC, RectBox.right - TREE_BOX_MARGIN, iYCenter);

        // draw small horizontal tick just to the left of the box if not
        //  level 1
        if( ucLevelCurrent > 1)
        {
            // draw -
            if( TryMoveTo( aRect, apDC, iXCenter - m_pTreeColumn->GetDefTreeIndent(), iYCenter) )
                TryLineTo( aRect, apDC, RectBox.left, iYCenter);
        }

        if( bIsPlus)
        {
            // ... make it into a plus sign
            if( TryMoveTo( aRect, apDC, iXCenter, RectBox.top + TREE_BOX_MARGIN) )
                TryLineTo( aRect, apDC, iXCenter, RectBox.bottom - TREE_BOX_MARGIN);
        }
        else
        {
            // it's a minus sign, so draw vertical tick below box center

            // draw |
            if( TryMoveTo( aRect, apDC, iXCenter, RectBox.bottom) )
                TryLineTo( aRect, apDC, iXCenter, iVertLineBottom);
        }

    }
    else if( ucLevelCurrent > 1)
    {
        // it's not a box, it's a leaf of the tree.  Just draw a horizontal line

        CGridTreeCellBase* pGridTreeCellBase = (CGridTreeCellBase*)pGrid->GetCell( m_iRow + 1, m_pTreeColumn->GetColumnWithTree());
        if( pGridTreeCellBase == NULL)
            return;

        bIsNextShowing = pGridTreeCellBase->IsViewable();
        ucLevelNext = pGridTreeCellBase->GetLevel();


        if( ucLevelCurrent > ucLevelNext)
        {
            bIsLastLeaf = TRUE;
        }

        // draw -
        if( TryMoveTo( aRect, apDC, iXCenter - m_pTreeColumn->GetDefTreeIndent(), iYCenter) )
            TryLineTo( aRect, apDC, iXCenter, iYCenter);
    }

    // draw nearest to text vertical lines that appear to the left of the box for all
    //  levels except level 1
    if( ucLevelCurrent > 1)
    {
        iXCenter -= m_pTreeColumn->GetDefTreeIndent();
        if( bIsLastLeaf)
            iLineStop = iYCenter;
        else
            iLineStop = iVertLineBottom;

        // draw |
        if( TryMoveTo( aRect, apDC, iXCenter, aRect.top) )
            TryLineTo( aRect, apDC, iXCenter, iLineStop);
    }

    BOOL bFoundBranch;
    unsigned char ucLevelToCheck = ucLevelCurrent;

    // draw vertical lines that appear to the left of the box for all appropriate
    //  levels except level 1
    for( int i1=ucLevelCurrent - 1; i1 > 1; i1--)
    {
        bFoundBranch = FALSE;

        int iStartPt = m_iRow + 1;

        for( int i2=iStartPt; i2 <= iNbrTreeElements; i2++)
        {
            CGridTreeCellBase* pGridTreeCellBase = (CGridTreeCellBase*)pGrid->GetCell(
                                                i2,
                                                m_pTreeColumn->GetColumnWithTree());
            if( pGridTreeCellBase == NULL)
                return;

            ucLevelNext = pGridTreeCellBase->GetLevel();

            if( ucLevelNext + 1 < ucLevelToCheck)
                break;

            if( ucLevelNext + 1 == ucLevelToCheck)
            {
                bIsNextShowing = pGridTreeCellBase->IsViewable();
                if( bIsNextShowing)
                    bFoundBranch = TRUE;
                break;
            }

        }

        iXCenter -= m_pTreeColumn->GetDefTreeIndent();

        if( bFoundBranch)
        {
            // draw |
            if( TryMoveTo( aRect, apDC, iXCenter, aRect.top) )
                TryLineTo( aRect, apDC, iXCenter, iVertLineBottom);
        }
        ucLevelToCheck--;   // each loop heads to level 1
    }

    // cleanup
    apDC->SelectObject(pOldPen);

    if( m_pTreeColumn->GetTreeUsesImages())
        SetImage( TreeImage);

}