void CMultilineList::RenderContent(CDC & dc, CRect & r) { dc.FillRect(r,CBrush::FromHandle(GetSysColorBrush(COLOR_WINDOW))); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); CPen * origPen = dc.SelectObject(&m_gridPen); int y1 = 0; int row = 0; // determine top visible row and setup y1 to be the top of its rendering area for (int yPos = 0; row < m_nRows; row++) { int thisRowHeight = m_rowHeights[row]; if ((yPos + thisRowHeight) > m_viewYPos) { y1 = r.top - (m_viewYPos - yPos); break; } else { yPos += thisRowHeight; } } int firstRenderedRow = row; // for each row for (; (row < m_nRows) && (y1 <= r.bottom); row++) { // start with zero height int y2 = y1; // for each column for (int col = 0, x1 = r.left-m_viewXPos; (col < m_nCols); col++) { // get the column object (if it exists) or use defaults Column column; std::map<int,Column>::iterator i = m_columns.find(col); if (i != m_columns.end()) { column = i->second; } // get the cell object (if it exists) or use defaults Cell cell; map<pair<int,int>,Cell>::iterator j = m_cells.find(make_pair(col,row)); if (j != m_cells.end()) { cell = j->second; } // determine the required size of the text, given the column width int x2 = x1 + column.m_width; CRect textRect(x1,y1,x2,y1); textRect.DeflateRect(INNER_PADDING,INNER_PADDING); int origRight = textRect.right; dc.DrawTextEx(cell.m_text,textRect, DT_CALCRECT|DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK, NULL); textRect.right = origRight; // if this row is selected, fill in the background with the selection color and // set the text color if (row == m_curSelRow) { CRect bgRect(textRect); bgRect.InflateRect(INNER_PADDING,INNER_PADDING); bgRect.bottom = bgRect.top + m_rowHeights[row] + GRID_WIDTH; bgRect.top += GRID_WIDTH; dc.FillRect(bgRect,CBrush::FromHandle(GetSysColorBrush(COLOR_HIGHLIGHT))); dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)); } else { // else, ensure text color is set to the non-selected color dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); } textRect.bottom += INNER_PADDING; textRect.bottom += GRID_WIDTH; // ensure tallest cell is stored if (textRect.bottom > y2) { y2 = textRect.bottom; } // render the cell text dc.DrawTextEx(cell.m_text,textRect, DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORDBREAK, NULL); x1 = x2; } // render horizontal grid line below the current row dc.MoveTo(r.left,y2+GRID_WIDTH); dc.LineTo(x1,y2+GRID_WIDTH); // if not the first row, also render the top horizontal line above the current row if (row > firstRenderedRow) { dc.MoveTo(r.left,y1+GRID_WIDTH); dc.LineTo(x1,y1+GRID_WIDTH); } // render the vertical lines between the columns for (int col = 0, x1 = r.left-m_viewXPos; (col < m_nCols) && (x1 <= r.right); col++) { Column column; std::map<int,Column>::iterator i = m_columns.find(col); if (i != m_columns.end()) { column = i->second; } int x2 = x1 + column.m_width; dc.MoveTo(x2,y1+GRID_WIDTH); dc.LineTo(x2,y2+GRID_WIDTH); x1 = x2; } y1 = y2; } dc.SelectObject(origPen); }