⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gridbtncellbase.cpp

📁 是一个GridTree的控件
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
}

void CGridBtnCellBase::OnDblClick( CPoint PointCellRelative)
{
    ProcessCtlClick(WM_LBUTTONDBLCLK,   // Command that invoked.  e.g. WM_LBUTTONDOWN
                    PointCellRelative); // point to check for hit
}

BOOL CGridBtnCellBase::GetTextRect( LPRECT pRect)  // i/o:  i=dims of cell rect; o=dims of text rect
{
    CGridCtrl* pGrid = GetGrid();
    ASSERT( pGrid);

    CRect RectCell( *pRect);

    // any button images
    ASSERT( MAX_NBR_CTLS_INCELL > GetDrawCtlNbrMax() ); // whoa!
    CRect RectAry[ MAX_NBR_CTLS_INCELL];

    const int iCtlNbr = GetDrawCtlNbr();
    if( iCtlNbr > 0)
    {
        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
                                *pRect) )   // cell rectangle to work with
        {
            // allowable text area has shrunk up
            *pRect = RectAry[ iCtlNbr];
            pRect->left += GetMargin();
            pRect->right -= GetMargin();
        }

    }


    // I've modified the starting point before passing to base
    return CGridCellBase::GetTextRect( pRect);
}

CSize CGridBtnCellBase::GetCellExtent(CDC* pDC)
{
    CSize sizeBase = CGridCellBase::GetCellExtent(pDC);

    // any button images?
    int iCtlNbr = GetDrawCtlNbr();
    if( iCtlNbr > 0)
    {
        int iDefaultWidth = sizeBase.cy;
        int iWidthTotal = 0;
        int iWidth;
        CSize SizeText;

        LOGFONT lf;
        memcpy(&lf, GetFont(), sizeof(LOGFONT));
        CFont font;
        font.CreateFontIndirect(&lf);

        CFont* pOldFont = pDC->SelectObject(&font);

        CRect rectText;
        for( int i1=0; i1 < iCtlNbr; i1++)
        {
            iWidth = GetDrawCtlWidth( i1);
            if( iWidth <= 0)
            {
                const char* pszBtnText = GetDrawCtlBtnText( i1);
                if( pszBtnText == NULL)
                {
                    iWidth = iDefaultWidth;
                }
                else
                {
                    // use width of text in button as a gauge
                    rectText.SetRectEmpty();
                    pDC->DrawText( pszBtnText, strlen( pszBtnText), &rectText, GetFormat() | DT_CALCRECT);
                    iWidth = rectText.Width();
                }
            }
            iWidthTotal += iWidth;
        }
        pDC->SelectObject(pOldFont);

        sizeBase += CSize( iWidthTotal + 4*GetMargin(), 0);
    }

    return sizeBase;
}

// Simplify by just using drawing logic for printing, too
BOOL CGridBtnCellBase::PrintCell(CDC* pDC, int nRow, int nCol, CRect rect)
{
    return Draw( pDC, nRow, nCol, rect);
}


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

/*****************************************************************************
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;
}

/*****************************************************************************
Processes mouse clicks that potentially hit an embedded cell control

*****************************************************************************/
BOOL CGridBtnCellBase::ProcessCtlClick(UINT uMsg,          // Command that invoked.  e.g. WM_LBUTTONDOWN
                                const CPoint& arPoint)  // point to check for hit
// returns:  T=hit a control / F=no control hit
{
    int iCtlHit = RelPointInCtl( arPoint);  // Relative point coords
    // returns:  Index of control that this point is within bounds of or -1 if no control matches

    if( iCtlHit >= 0)
    {
        ClickedCellCtl( uMsg,   // Command that invoked.  e.g. WM_LBUTTONDOWN
                        iCtlHit);    // zero-based index of image to draw
        return TRUE;
    }
    m_sLastCtlClicked = -1;
    return FALSE;
}

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;
}


/*****************************************************************************
Determines bounding rectangle to draw a button in a cell.   Used to draw cells
and for mouse hit testing.

If a fixed-size control can't fit within the cell, the control will shrink in
the required x and / or y dimension.   I do this because I'm not using a
clipping region when I display the cell -- that would be a better solution.

*****************************************************************************/
BOOL CGridBtnCellBase::CalcDrawCtlRects(CRect* apRect,     // returns:  CRects with coordinates
                                                    //  last entry has optional leftover rect
                                                    //  available for text, etc.
                                int aiNbrRectEntries,   // nbr of Rects in above array
                                const CRect& arRectCell)// cell rectangle to work with
// returns:  success / fail
{
    ASSERT( apRect != NULL);

    if( aiNbrRectEntries < GetDrawCtlNbrMax() )
    {
        ASSERT( FALSE); // need to allow for leftover rect
        return FALSE;
    }

    const int iCtlNbr = GetDrawCtlNbr();
    if( iCtlNbr <= 0)
        return FALSE;

    int i1, i2;
    int iSpinBoxDownIdx = -1;       // can have zero or 1 spin box -- no more
                                    //  identifies placment of down arrow of the spin box
    int iWidth = 0;
    CTL_ALIGN CtlAlign;
    UINT uiType;
    UINT uiState;
    CRect* pRectSav = apRect;

    // calculate the width layout of buttons by examining
    //  all of them and noting important info
    int iFixedSum = 0;
    int iSizeToFitCount = 0;
    for( i1=0; i1 < iCtlNbr; i1++)
    {
        CtlAlign = GetDrawCtlAlign( i1);

        if( CtlAlign == CTL_ALIGN_CENTER)
        {
            // forget all calculations if any are centered, all controls
            //  just overwrite each other and expand to fit cell
            for( i2=0; i2 < iCtlNbr; i2++)
            {
                apRect->operator=( arRectCell); // copy initial rectangle
                apRect++;
            }
            apRect->operator=( CRect(0,0,0,0) );    // no text leftover
            return TRUE;
        }

        iWidth = GetDrawCtlWidth( i1);
        if( iWidth > 0)
            iFixedSum += iWidth;
        else
            iSizeToFitCount++;

        // spin box rectangles are stacked on top of each other
        //  thus, avoid doubling spin box width
        if( iSpinBoxDownIdx < 0)
        {
            uiState = GetDrawCtlState( i1);
            if( GetDrawCtlType( i1) == DFC_SCROLL
                && !( uiState & (DFCS_SCROLLCOMBOBOX
                                | DFCS_SCROLLDOWN
                                | DFCS_SCROLLLEFT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -