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

📄 gridctrl.cpp

📁 一种简单的股票软件源代码,编译后可以实时显示证券行情
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        bResult = FALSE;
    }
    END_CATCH

    m_nCols = nCols;

//    SetModified();
    ResetScrollBars();//重值滚动条
    Refresh();

    return bResult;
}

BOOL CGridCtrl::SetColumnWidth(int nCol, int width)
{
    ASSERT(nCol >= 0 && nCol < m_nCols && width >= 0);
    if (nCol < 0 || nCol >= m_nCols || width < 0)
        return FALSE;

    m_arColWidths[nCol] = width;
    ResetScrollBars();

    return TRUE;
}

void CGridCtrl::Refresh()
{
    if (GetSafeHwnd() && m_bAllowDraw)
        Invalidate();
}

// Creates a new grid cell and performs any necessary initialisation
/*virtual*/ CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol)
{
//    ASSERT(!GetVirtualMode());

    if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
		//IsDerivedFrom是CRuntimeClass的一个检验函数,
		//判断m_pRtcDefault是否是指定类的派生类.
    {
        ASSERT( FALSE);
        return NULL;
    }
	//这起到类型识别和类型检验的作用

    CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject();
	//m_pRtcDefault在初始化时被RUNTIME_CLASS宏绑定到CGridCell类,
	//所以这实际是用一个基类指针指向一个派生类对象(动态生成)
	//实际使用如下语句似乎也可以:
	//CGridCellBase* pCell = (CGridCellBase*) new CGridCell;

    if (!pCell)
        return NULL;

    pCell->SetGrid(this);
//    pCell->SetCoords(nRow, nCol); 

    if (nCol < m_nFixedCols)//pCell就是固定列
        pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);//是m_nState和GVIS_FIXED | GVIS_FIXEDCOL的运算结果
	                                                                    //所以m_nState是在这里改变的
    if (nRow < m_nFixedRows)//pCell就是固定行
        pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);//是m_nState和GVIS_FIXED | GVIS_FIXEDROW的运算结果
	                                                                    //所以m_nState是在这里改变的
    
//    pCell->SetFormat(pCell->GetDefaultCell()->GetFormat());

    return pCell;//这是非固定的单元格,其m_nState就是0;

}

/*virtual*/ void CGridCtrl::DestroyCell(int nRow, int nCol)
{
    // Should NEVER get here in virtual mode.
//    ASSERT(!GetVirtualMode());

    // Set the cells state to 0. If the cell is selected, this
    // will remove the cell from the selected list.
    SetItemState(nRow, nCol, 0);

    delete GetCell(nRow, nCol);
}

BOOL CGridCtrl::SetItemBkColor(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
{
//    if (GetVirtualMode())
//        return FALSE;

    CGridCellBase* pCell = GetCell(nRow, nCol);
    ASSERT(pCell);
    if (!pCell)
        return FALSE;

    pCell->SetBackClr(cr);
    return TRUE;
}

BOOL CGridCtrl::SetItemFgColor(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
{

    CGridCellBase* pCell = GetCell(nRow, nCol);
//    ASSERT(pCell);
    if (!pCell)
        return FALSE;
    
    pCell->SetTextClr(cr);
    return TRUE;
}

BOOL CGridCtrl::SetItemState(int nRow, int nCol, UINT state)
{
    CGridCellBase* pCell = GetCell(nRow, nCol);
    ASSERT(pCell);
    if (!pCell)
        return FALSE;

    // Set the cell's state
    pCell->SetState(state);

    return TRUE;
}

UINT CGridCtrl::GetItemState(int nRow, int nCol) const
{
    CGridCellBase* pCell = GetCell(nRow, nCol);
    ASSERT(pCell);
    if (!pCell)
        return 0;

    return pCell->GetState();
}


void CGridCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

   if (m_bDoubleBuffer)    // Use a memory DC to remove flicker
	                       // 使用内存DC消除闪烁
    {
        CMemDC MemDC(&dc);
        OnDraw(&MemDC);
    }
    else                    // Draw raw - this helps in debugging vis problems.
        OnDraw(&dc);
	
	// Do not call CWnd::OnPaint() for painting messages
}

void CGridCtrl::OnDraw(CDC* pDC)
{
	if (!m_bAllowDraw)
        return;

    CRect clipRect;
    if (pDC->GetClipBox(&clipRect) == ERROR)
        return;
	GetClientRect(&clipRect);

    EraseBkgnd(pDC);

	CRect rect;
    int row, col;
    CGridCellBase* pCell;

    int nFixedRowHeight = GetFixedRowHeight();
    int nFixedColWidth  = GetFixedColumnWidth();

	CCellID idTopLeft = GetTopleftNonFixedCell();//左上角非固定单元格ID(包含行号和列号)
    int minVisibleRow = idTopLeft.row,//最小可见的行号
        minVisibleCol = idTopLeft.col;//最小可见的列号
	
	CRect VisRect;
    CCellRange VisCellRange = GetVisibleNonFixedCellRange(VisRect);//可见单元格的范围
	                                                               //同时初始化VisRect
    int maxVisibleRow = VisCellRange.GetMaxRow(),//最大可见的行号
        maxVisibleCol = VisCellRange.GetMaxCol();//最大可见的列号

	// draw top-left cells 0..m_nFixedRows-1, 0..m_nFixedCols-1
	// 画左上角单元格(也可能是几行几列)
	//(第一行:一列,一列...,第二行:一列,一列....);
    rect.bottom = -1;
    for (row = 0; row < m_nFixedRows; row++)
    {
        if (GetRowHeight(row) <= 0) continue;//不执行下面语句,直接到下一循环

        rect.top = rect.bottom+1;//有这一行,就不会因下一行的操作
		                         //而使单元格越画越窄了

        rect.bottom = rect.top + GetRowHeight(row)-1;//增加一个行高
        rect.right = -1;

        for (col = 0; col < m_nFixedCols; col++)
        {
            if (GetColumnWidth(col) <= 0) continue;

            rect.left = rect.right+1;//有这一行,就不会因下一行的操作
		                             //而使单元格越画越窄了
            rect.right = rect.left + GetColumnWidth(col)-1;//增加一个列宽

            pCell = GetCell(row, col);
            if (pCell)
			{
			//	pCell->SetCoords(row,col);//这是一个空函数,目前没有用
                pCell->Draw(pDC, row, col, rect, FALSE);
			}
        }
    }
	//////////////////////////////////////////////////////////////////////////////////
	// draw fixed column cells:  m_nFixedRows..n, 0..m_nFixedCols-1
	//画固定的列(行标头):(第一行:一列,一列...,第二行:一列,一列....);
	rect.bottom = nFixedRowHeight-1;
    for (row = minVisibleRow; row <= maxVisibleRow; row++)
    {
        if (GetRowHeight(row) <= 0) continue;

        rect.top = rect.bottom+1;
        rect.bottom = rect.top + GetRowHeight(row)-1;

        // rect.bottom = bottom pixel of previous row
        if (rect.top > clipRect.bottom)
            break;                // Gone past cliprect
        if (rect.bottom < clipRect.top)
            continue;             // Reached cliprect yet?

        rect.right = -1;
        for (col = 0; col < m_nFixedCols; col++)
        {
            if (GetColumnWidth(col) <= 0) continue;

            rect.left = rect.right+1;
            rect.right = rect.left + GetColumnWidth(col)-1;

            if (rect.left > clipRect.right)
                break;            // gone past cliprect
            if (rect.right < clipRect.left)
                continue;         // Reached cliprect yet?

            pCell = GetCell(row, col);
            if (pCell)
			{
				if(col==0)
				{
				  CString str;
				  str.Format("%d",row);
				  pCell->SetText(str);
				}

                pCell->Draw(pDC, row, col, rect, FALSE);
			}
        }
    }
	/////////////////////////////////////////////////////////////
    // draw fixed row cells  0..m_nFixedRows, m_nFixedCols..n
	//画固定的行(列标头):(第一行:一列,一列...,第二行:一列,一列....);
	
    rect.bottom = -1;
    for (row = 0; row < m_nFixedRows; row++)
    {
        if (GetRowHeight(row) <= 0) continue;

        rect.top = rect.bottom+1;
        rect.bottom = rect.top + GetRowHeight(row)-1;

        // rect.bottom = bottom pixel of previous row
        if (rect.top > clipRect.bottom)
            break;                // Gone past cliprect
        if (rect.bottom < clipRect.top)
            continue;             // Reached cliprect yet?

        rect.right = nFixedColWidth-1;
        for (col = minVisibleCol; col <= maxVisibleCol; col++)
        {
            if (GetColumnWidth(col) <= 0) continue;

            rect.left = rect.right+1;
            rect.right = rect.left + GetColumnWidth(col)-1;

            if (rect.left > clipRect.right)
                break;        // gone past cliprect
            if (rect.right < clipRect.left)
                continue;     // Reached cliprect yet?

            pCell = GetCell(row, col);
            if (pCell)
			{
                pCell->Draw(pDC, row, col, rect, FALSE);
			}
        }
    }
///////////////////////////////////////////////////////////////////
	// draw rest of non-fixed cells
	//画剩余的非固定的单元格:(第一行:一列,一列...,第二行:一列,一列....);

	    rect.bottom = nFixedRowHeight-1;
    for (row = minVisibleRow; row <= maxVisibleRow; row++)
    {
        if (GetRowHeight(row) <= 0) continue;

        rect.top = rect.bottom+1;
        rect.bottom = rect.top + GetRowHeight(row)-1;

        // rect.bottom = bottom pixel of previous row
        if (rect.top > clipRect.bottom)
            break;                // Gone past cliprect
        if (rect.bottom < clipRect.top)
            continue;             // Reached cliprect yet?

        rect.right = nFixedColWidth-1;
        for (col = minVisibleCol; col <= maxVisibleCol; col++)
        {
            if (GetColumnWidth(col) <= 0) continue;

            rect.left = rect.right+1;
            rect.right = rect.left + GetColumnWidth(col)-1;

            if (rect.left > clipRect.right)
                break;        // gone past cliprect
            if (rect.right < clipRect.left)
                continue;     // Reached cliprect yet?

            pCell = GetCell(row, col);
            // TRACE(_T("Cell %d,%d type: %s\n"), row, col, pCell->GetRuntimeClass()->m_lpszClassName);
            if (pCell)
			{
                pCell->Draw(pDC, row, col, rect, FALSE);
			}
        }
    }

	CPen pen;
    pen.CreatePen(PS_SOLID, 0, m_crGridLineColour);
    pDC->SelectObject(&pen);

    // draw vertical lines (drawn at ends of cells)
	//画垂直分隔线:
    if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
    {
        int x = nFixedColWidth;
        for (col =minVisibleCol; col <= maxVisibleCol; col++)
        {
            if (GetColumnWidth(col) <= 0) continue;

            x += GetColumnWidth(col);
            pDC->MoveTo(x-1, nFixedRowHeight);
            pDC->LineTo(x-1, rect.bottom);
        }
    }

    // draw horizontal lines (drawn at bottom of each cell)
	//画水平分隔线
    if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
    {
        int y = nFixedRowHeight;
        for (row = minVisibleRow; row <= maxVisibleRow; row++)
        {
            if (GetRowHeight(row) <= 0) continue;

            y += GetRowHeight(row);
            pDC->MoveTo(nFixedColWidth, y-1);
            pDC->LineTo(rect.right,  y-1);
        }
    }

    pDC->SelectStockObject(NULL_PEN);

}

int CGridCtrl::GetFixedRowHeight() const
{
    int nHeight = 0;
    for (int i = 0; i < m_nFixedRows; i++)
        nHeight += GetRowHeight(i);

    return nHeight;
}

int CGridCtrl::GetFixedColumnWidth() const
{
    int nWidth = 0;
    for (int i = 0; i < m_nFixedCols; i++)
        nWidth += GetColumnWidth(i);

    return nWidth;
}

int CGridCtrl::GetRowHeight(int nRow) const
{
    ASSERT(nRow >= 0 && nRow < m_nRows);
    if (nRow < 0 || nRow >= m_nRows)
        return -1;

    return m_arRowHeights[nRow];
}

int CGridCtrl::GetColumnWidth(int nCol) const
{
    ASSERT(nCol >= 0 && nCol < m_nCols);
    if (nCol < 0 || nCol >= m_nCols)
        return -1;

    return m_arColWidths[nCol];
}

// Gets the first non-fixed cell ID
CCellID CGridCtrl::GetTopleftNonFixedCell(BOOL bForceRecalculation /*=FALSE*/)
{
    // Used cached value if possible
	// 如果可能使用保存的值
    if (m_idTopLeftCell.IsValid() && !bForceRecalculation)//因为bForceRecalculation却省为假
		                                                  //所以只要IsValid()返回真就执行
        return m_idTopLeftCell;

    int nVertScroll =GetScrollPos(SB_VERT), //没有滚动条或没有设置初始位置或没有滚动,
        nHorzScroll =GetScrollPos(SB_HORZ); //会返回0值

    m_idTopLeftCell.col = m_nFixedCols;//先赋值(却省情况下这是当然的)
    int nRight = 0;
    //这个循环比较特别,主要目的是要作m_idTopLeftCell.col++的操作,
	//因为各列的宽可能不一样,不能对计数器nRight简单的++,
	//因为nHorzScroll是以屏幕像素为单位的。
	while (nRight < nHorzScroll && m_idTopLeftCell.col < (GetColumnCount()-1))
        nRight += GetColumnWidth(m_idTopLeftCell.col++);//作m_idTopLeftCell.col++操作

⌨️ 快捷键说明

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