Esempio n. 1
0
//------------------------------------------------------------------------
//! Returns the proper rectangle, which a cell value editor should fit in
//!
//! @param owner The list control for the inplace cell value editor
//! @param nRow The index of the row
//! @param nCol The index of the column
//! @return Rectangle where the inplace cell value editor should be placed.
//------------------------------------------------------------------------
CRect CGridColumnTraitText::GetCellEditRect(CGridListCtrlEx& owner, int nRow, int nCol)
{
	// Get position of the cell to edit
	CRect rectCell;
	VERIFY( owner.GetCellRect(nRow, nCol, LVIR_LABEL, rectCell) );

	// Adjust cell rectangle according to grid-lines
	if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES)
		rectCell.bottom -= ::GetSystemMetrics(SM_CXBORDER);

	if (owner.GetExtendedStyle() & LVS_EX_SUBITEMIMAGES)
	{
		// Add margin to cell image
		if (owner.GetImageList(LVSIL_SMALL)!=NULL && owner.GetCellImage(nRow,nCol)!=I_IMAGECALLBACK)
			rectCell.left += ::GetSystemMetrics(SM_CXBORDER);
	}

	// Check if there is enough room for normal margin
	int requiredHeight = GetCellFontHeight(owner);
	requiredHeight += 2*::GetSystemMetrics(SM_CXEDGE);
	if (requiredHeight > rectCell.Height())
		rectCell.bottom = rectCell.top + requiredHeight;

	return rectCell;
}
//------------------------------------------------------------------------
//! Check if current image index blocks for editing of cell label
//!
//! @param owner The list control starting edit
//! @param nRow The index of the row for the cell
//! @param nCol The index of the column for the cell
//! @param pt The position clicked, in client coordinates.
//! @return Is cell read only ? (true / false)
//------------------------------------------------------------------------
bool CGridColumnTraitImage::IsCellReadOnly(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) const
{
	if (!m_ColumnState.m_Editable)
		return true;

	// Check if current cell image blocks for starting cell editor
	if (m_ImageCellEdit.GetSize() != 0)
	{
		int nCurImageIdx = -1;
		for (int i = 0; i < m_ImageCellEdit.GetSize(); ++i)
		{
			if (!m_ImageCellEdit.GetValueAt(i))
			{
				if (nCurImageIdx == -1)
				{
					if (pt != CPoint(-1, -1))
					{
						CRect rect;
						VERIFY(owner.GetCellRect(nRow, nCol, LVIR_LABEL, rect));
						if (!rect.PtInRect(pt))
							break;
					}

					nCurImageIdx = owner.GetCellImage(nRow, nCol);
					if (nCurImageIdx == -1)
						break;
				}
				if (nCurImageIdx == m_ImageCellEdit.GetKeyAt(i))
					return true;
			}
		}
	}

	return false;	// editable
}
//------------------------------------------------------------------------
//! Returns dimensions of the cell text clicked
//!
//! @param owner The list control being clicked
//! @param nRow The index of the row
//! @param nCol The index of the column
//! @param cellText The contents of the cell clicked
//! @return The dimensions of the cell text
//------------------------------------------------------------------------
CRect CGridColumnTraitHyperLink::GetTextRect(CGridListCtrlEx& owner, int nRow, int nCol, const CString& cellText)
{
	CRect rect;
	ASSERT(nRow != -1);
	CDC* pDC = owner.GetDC();
	CFont* pOldFont = pDC->SelectObject(owner.GetCellFont());
	CSize size = pDC->GetTextExtent(cellText);
	pDC->SelectObject(pOldFont);
	owner.ReleaseDC(pDC);

	owner.GetCellRect(nRow, nCol, LVIR_LABEL, rect);

	HDITEM hditem = { 0 };
	hditem.mask = HDI_FORMAT;
	owner.GetHeaderCtrl()->GetItem(nCol, &hditem);

	// First item (Label) doesn't have a margin (Subitems does)
	if (nCol != 0 && !(hditem.fmt & HDF_CENTER))
	{
		if (hditem.fmt & HDF_RIGHT)
			rect.OffsetRect(-7, 0);
		else
			rect.OffsetRect(4, 0);
	}

	if (hditem.fmt & HDF_CENTER)
		rect.DeflateRect((rect.Width() - size.cx) / 2, 0);
	else if (hditem.fmt & HDF_RIGHT)
		rect.left = rect.right - size.cx;
	else
		rect.right = rect.left + size.cx;
	return rect;
}
Esempio n. 4
0
//------------------------------------------------------------------------
//! Overrides the custom draw handler, to allow custom coloring of cells
//! with this column trait.
//!
//! @param owner The list control drawing
//! @param pLVCD Pointer to NMLVCUSTOMDRAW structure
//! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.)
//------------------------------------------------------------------------
void CGridColumnTraitText::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult)
{
	switch (pLVCD->nmcd.dwDrawStage)
	{
		// Before painting a cell
		case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
		{
			m_OldTextColor = pLVCD->clrText;
			m_OldBackColor = pLVCD->clrTextBk;

			// Only change cell colors when not selected
			if (UpdateTextColor(pLVCD, pLVCD->clrText))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			if (UpdateBackColor(pLVCD, pLVCD->clrTextBk))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			if (owner.OnDisplayCellColor(pLVCD))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			// Changed the colors without asking for restoring the original color
			ASSERT((*pResult & CDRF_NOTIFYPOSTPAINT) || (pLVCD->clrText == m_OldTextColor && pLVCD->clrTextBk == m_OldBackColor));

			LOGFONT newFont = { 0 };
			bool createFont = owner.OnDisplayCellFont(pLVCD, newFont);
			createFont |= UpdateTextFont(pLVCD, newFont);
			if (createFont)
			{
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = new CFont;
				VERIFY(pNewFont->CreateFontIndirect(&newFont));
				m_pOldFont = pDC->SelectObject(pNewFont);
				*pResult |= CDRF_NOTIFYPOSTPAINT;	// We need to restore the original font
				*pResult |= CDRF_NEWFONT;
			}
		} break;

		// After painting a cell
		case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
		{
			if (m_pOldFont != NULL)
			{
				// Restore the original font
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = pDC->SelectObject(m_pOldFont);
				delete pNewFont;
				m_pOldFont = NULL;
			}

			pLVCD->clrText = m_OldTextColor;
			pLVCD->clrTextBk = m_OldBackColor;
			*pResult |= CDRF_NEWFONT;
		} break;
	}
}
Esempio n. 5
0
//------------------------------------------------------------------------
//! Overrides the custom draw handler, to allow custom coloring of cells
//! with this column trait.
//!
//! @param owner The list control drawing
//! @param pLVCD Pointer to NMLVCUSTOMDRAW structure
//! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.)
//------------------------------------------------------------------------
void CGridColumnTraitText::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult)
{
	int nRow = (int)pLVCD->nmcd.dwItemSpec;

	switch (pLVCD->nmcd.dwDrawStage)
	{
		// Before painting a cell
		case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
		{
			int nCol = pLVCD->iSubItem;

			m_OldTextColor = pLVCD->clrText;
			m_OldBackColor = pLVCD->clrTextBk;

			// Only change cell colors when not selected
			if (UpdateTextColor(pLVCD->clrText))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			if (UpdateBackColor(pLVCD->clrTextBk))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			if (owner.OnDisplayCellColor(nRow, nCol, pLVCD->clrText, pLVCD->clrTextBk))
				*pResult |= CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT;

			LOGFONT newFont = {0};
			if (owner.OnDisplayCellFont(nRow, nCol, newFont))
			{
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = new CFont;
				VERIFY( pNewFont->CreateFontIndirect(&newFont) );
				m_pOldFont = pDC->SelectObject(pNewFont);
				*pResult |= CDRF_NOTIFYPOSTPAINT;	// We need to restore the original font
				*pResult |= CDRF_NEWFONT;
			}
		} break;

		// After painting a cell
		case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
		{
			if (m_pOldFont!=NULL)
			{
				// Restore the original font
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = pDC->SelectObject(m_pOldFont);
				delete pNewFont;
			}

			pLVCD->clrText = m_OldTextColor;
			pLVCD->clrTextBk = m_OldBackColor;
			*pResult |= CDRF_NEWFONT;
		} break;
	}
}
//------------------------------------------------------------------------
//! Switch to the next image index
//!
//! @param owner The list control starting edit
//! @param nRow The index of the row for the cell to edit
//! @param nCol The index of the column for the cell to edit
//! @return New image index (-1 if no new image)
//------------------------------------------------------------------------
int CGridColumnTraitImage::FlipImageIndex(CGridListCtrlEx& owner, int nRow, int nCol)
{
	if (m_ImageCellText.GetSize() <= 1)
		return -1;

	int nImageIdx = owner.GetCellImage(nRow, nCol);
	int nOldImagePos = -1;
	for (int i = 0; i < m_ImageCellText.GetSize(); ++i)
	{
		if (m_ImageCellText.GetKeyAt(i) == nImageIdx)
		{
			nOldImagePos = i;
			break;
		}
	}
	if (nOldImagePos == -1)
		return -1;

	int nNewImageIdx = -1;
	if (nOldImagePos + 1 == m_ImageCellText.GetSize())
		nNewImageIdx = m_ImageCellText.GetKeyAt(0);
	else
		nNewImageIdx = m_ImageCellText.GetKeyAt(nOldImagePos + 1);

	return nNewImageIdx;
}
//------------------------------------------------------------------------
//! Checks if the mouse click should start the cell editor (OnEditBegin)
//!	Validates that the click was on the text-link within the label-part
//!
//! @param owner The list control being clicked
//! @param nRow The index of the row
//! @param nCol The index of the column
//! @param pt The position clicked, in client coordinates.
//! @param bDblClick Whether the position was double clicked
//! @return How should the cell editor be started (0 = No editor, 1 = Start Editor, 2 = Start Editor and block click-event)
//------------------------------------------------------------------------
int CGridColumnTraitHyperLink::OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick)
{
	int startEdit = CGridColumnTraitImage::OnClickEditStart(owner, nRow, nCol, pt, bDblClick);
	if (startEdit)
	{
		// Check if mouse click was inside the label-part of the cell
		CRect labelRect;
		if (owner.GetCellRect(nRow, nCol, LVIR_LABEL, labelRect) && labelRect.PtInRect(pt))
		{
			// Check if mouse click was inside the text-link of the cell
			CString cellText = owner.GetItemText(nRow, nCol);
			if (GetTextRect(owner, nRow, nCol, cellText).PtInRect(pt))
				return startEdit;
			else
				return 0;
		}
	}
	return startEdit;
}
Esempio n. 8
0
//------------------------------------------------------------------------
//! Calculates the proper row-height according to font, which a cell value
//! editor should fit in.
//!
//! @param owner The list control for the inplace cell value editor
//! @return Height in pixels of the row.
//------------------------------------------------------------------------
int CGridColumnTraitText::GetCellFontHeight(CGridListCtrlEx& owner)
{
	const CString testText = _T("yjpÍÁ");

	CRect rcRequired = CRect(0, 0, 0, 0);

	CClientDC dc(&owner);
	dc.SelectObject(owner.GetCellFont());
	dc.DrawText(testText, &rcRequired, DT_CALCRECT | DT_SINGLELINE);

	return rcRequired.Height();
}
//------------------------------------------------------------------------
//! Returns the proper rectangle, which an editor should fit in
//------------------------------------------------------------------------
CRect CGridColumnTraitText::GetCellEditRect(CGridListCtrlEx& owner, int nRow, int nCol)
{
	// Find the required height according to font
	int requiredHeight = GetCellFontHeight(owner);

	// Get position of the cell to edit
	CRect rectCell;
	VERIFY( owner.GetCellRect(nRow, nCol, LVIR_LABEL, rectCell) );

	// Adjust position to font height
	if (!owner.UsingVisualStyle())
	{
		if ((requiredHeight + 2*::GetSystemMetrics(SM_CXEDGE)) > rectCell.Height())
		{
			rectCell.top -= ::GetSystemMetrics(SM_CXEDGE);
			rectCell.bottom += ::GetSystemMetrics(SM_CXEDGE);
		}
	}
	if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES)
	{
		if ((requiredHeight + 2*::GetSystemMetrics(SM_CXEDGE) + ::GetSystemMetrics(SM_CXBORDER)) < rectCell.Height())
			rectCell.bottom -= ::GetSystemMetrics(SM_CXBORDER);
	}
	if (owner.GetExtendedStyle() & LVS_EX_SUBITEMIMAGES)
	{
		if (owner.GetImageList(LVSIL_SMALL)!=NULL && owner.GetCellImage(nRow,nCol)>=0)
			rectCell.left += ::GetSystemMetrics(SM_CXBORDER);
	}
	return rectCell;
}
//------------------------------------------------------------------------
//! Check if the cell is editable when clicked
//!
//! @param owner The list control being clicked
//! @param nRow The index of the row
//! @param nCol The index of the column
//! @param pt The position clicked, in client coordinates.
//! @param bDblClick Whether the position was double clicked
//! @return How should the cell editor be started (0 = No editor, 1 = Start Editor, 2 = Start Editor and block click-event)
//------------------------------------------------------------------------
int CGridColumnTraitImage::OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick)
{
	// Begin edit if the cell has focus already
	bool startEdit = nRow!=-1 && nCol!=-1 && owner.GetFocusRow()==nRow && owner.GetFocusCell()==nCol && !bDblClick;

	// Check if the cell can be edited without having focus first
	if (m_ToggleSelection)
	{
		if (nCol==0 && owner.GetExtendedStyle() & LVS_EX_CHECKBOXES)
		{
			CRect iconRect;
			if (!owner.GetCellRect(nRow, nCol, LVIR_ICON, iconRect) || !iconRect.PtInRect(pt))
			{
				CRect labelRect;
				if (owner.GetCellRect(nRow, nCol, LVIR_LABEL, labelRect) && !labelRect.PtInRect(pt))
					return 1;	// Clicked the checkbox for the label-column
			}
		}

		if (m_ImageIndexes.GetSize()<=1)
			return startEdit ? 1 : 0;	// No images to flip between

		CRect iconRect;
		if (!owner.GetCellRect(nRow, nCol, LVIR_ICON, iconRect) || !iconRect.PtInRect(pt))
			return startEdit ? 1 : 0;	// Didn't click the image icon

		return 2;	// Don't change focus or change selection
	}

	return startEdit ? 1 : 0;
}
void CGridColumnTraitText::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult)
{
	int nRow = (int)pLVCD->nmcd.dwItemSpec;

	switch (pLVCD->nmcd.dwDrawStage)
	{
		// Before painting a cell
		case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
		{
			// Remove the selection color for the focus cell, to make it easier to see focus
			int nCol = pLVCD->iSubItem;
			if (pLVCD->nmcd.uItemState & CDIS_SELECTED && owner.GetFocusCell()==nCol && owner.GetFocusRow()==nRow)
			{
				pLVCD->nmcd.uItemState &= ~CDIS_SELECTED;
			}

			if (!owner.IsRowSelected(nRow) && owner.GetHotItem()!=nRow)
			{
				if (UpdateTextColor(pLVCD->clrText))
					*pResult |= CDRF_NEWFONT;

				if (UpdateBackColor(pLVCD->clrTextBk))
					*pResult |= CDRF_NEWFONT;

				// Only change cell colors when not selected / in focus
				if (owner.OnDisplayCellColor(nRow, nCol, pLVCD->clrText, pLVCD->clrTextBk))
					*pResult |= CDRF_NEWFONT;
			}

			LOGFONT newFont = {0};
			if (owner.OnDisplayCellFont(nRow, nCol, newFont))
			{
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = new CFont;
				VERIFY( pNewFont->CreateFontIndirect(&newFont) );
				m_pOldFont = pDC->SelectObject(pNewFont);
				*pResult |= CDRF_NOTIFYPOSTPAINT;	// We need to restore the original font
				*pResult |= CDRF_NEWFONT;
			}
		} break;

		// After painting a cell
		case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
		{
			if (m_pOldFont!=NULL)
			{
				// Restore the original font
				CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
				CFont* pNewFont = pDC->SelectObject(m_pOldFont);
				delete pNewFont;
			}
		} break;
	}
}
//------------------------------------------------------------------------
//! Checks if the mouse click should start the cell editor (OnEditBegin)
//! Normally the cell needs to have focus first before cell editor can be started
//! - Except when using ToggleSelection, and have clicked a checkbox (image)
//! - Except when using SingleClickEdit, which makes it impossible to do double click
//!
//! @param owner The list control being clicked
//! @param nRow The index of the row
//! @param nCol The index of the column
//! @param pt The position clicked, in client coordinates.
//! @param bDblClick Whether the position was double clicked
//! @return How should the cell editor be started (0 = No editor, 1 = Start Editor, 2 = Start Editor and block click-event)
//------------------------------------------------------------------------
int CGridColumnTraitImage::OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick)
{
	// Begin edit if the cell has focus already
	bool startEdit = false;
	if (nRow != -1 && nCol != -1 && !bDblClick)
	{
		if (m_SingleClickEdit)
			startEdit = true;
		else
			if (owner.GetFocusRow() == nRow && owner.GetFocusCell() == nCol)
				startEdit = true;
	}

	// Check if the cell-image / cell-checkbox can be edited without having focus first
	if (m_ToggleSelection)
	{
		if (nCol == 0 && owner.GetExtendedStyle() & LVS_EX_CHECKBOXES)
		{
			CRect iconRect;
			if (!owner.GetCellRect(nRow, nCol, LVIR_ICON, iconRect) || !iconRect.PtInRect(pt))
			{
				CRect labelRect;
				if (owner.GetCellRect(nRow, nCol, LVIR_LABEL, labelRect) && !labelRect.PtInRect(pt))
					return 1;	// Clicked the checkbox for the label-column
			}
		}

		if (m_ImageCellEdit.GetSize()>1)
		{
			CRect iconRect;
			if (owner.GetCellRect(nRow, nCol, LVIR_ICON, iconRect) && iconRect.PtInRect(pt))
				return 2;	// Clicked the image-icon (Don't change focus or change selection)
		}
	}

	return startEdit ? 1 : 0;
}
Esempio n. 13
0
//------------------------------------------------------------------------
//! Overrides the custom draw handler, to allow custom coloring of rows.
//!		- Fix white background for icon images
//!		- Fix white background between icon and cell text
//!
//! @param owner The list control drawing
//! @param pLVCD Pointer to NMLVCUSTOMDRAW structure
//! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.)
//------------------------------------------------------------------------
void CGridRowTraitXP::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult)
{
	if (owner.UsingVisualStyle())
	{
		// Perform standard drawing
		CGridRowTraitText::OnCustomDraw(owner, pLVCD, pResult);
		return;
	}
	
	// We are using classic- or XP-style
	int nRow = (int)pLVCD->nmcd.dwItemSpec;

	// Repair the standard drawing
	switch (pLVCD->nmcd.dwDrawStage)
	{
		case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
		{
			// We want to fix cell images
			*pResult |= CDRF_NOTIFYPOSTPAINT;
		} break;

		case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
		{
			// Fix CListCtrl selection drawing bug with white background for icon image
			// Fix CListCtrl selection drawing bug with white margin between icon and text
			int nCol = pLVCD->iSubItem;

			if (CRect(pLVCD->nmcd.rc)==CRect(0,0,0,0))
				break;

			int nImage = owner.GetCellImage(nRow, nCol);
			if (nImage == I_IMAGECALLBACK)
				break;
				
			CImageList* pImageList = owner.GetImageList(LVSIL_SMALL);
			if (pImageList==NULL)
				break;

			COLORREF backColor = COLORREF(-1);
			if (owner.GetExtendedStyle() & LVS_EX_TRACKSELECT && owner.GetHotItem()==nRow)
			{
#if(WINVER >= 0x0500)
				backColor = ::GetSysColor(COLOR_HOTLIGHT);
#else
				if (owner.IsRowSelected(nRow))
					backColor = ::GetSysColor(COLOR_HIGHLIGHT);
				else
					break;
#endif
			}
			else
			if (owner.IsRowSelected(nRow))
			{
				if (!(owner.GetExtendedStyle() & LVS_EX_FULLROWSELECT))
					break;	// No drawing of selection color without full-row-select

				if (m_InvertCellSelection && owner.GetFocusRow()==nRow && owner.GetFocusCell()==nCol)
				{
					// No drawing of selection color for focus cell
					if (pLVCD->clrTextBk > RGB(255,255,255))
						break;

					backColor = pLVCD->clrTextBk;
				}
				else
				{
					if (owner.GetFocus()!=&owner && !owner.IsCellEditorOpen())
					{
						// Selection color is different when not having focus
						if (owner.GetStyle() & LVS_SHOWSELALWAYS)
							backColor = ::GetSysColor(COLOR_BTNFACE);
						else
							break;	// no drawing of selection color when not in focus
					}
					else
					{
						backColor = ::GetSysColor(COLOR_HIGHLIGHT);
					}
				}
			}
			else
			{
				// Redraw with the given background color
				if (pLVCD->clrTextBk > RGB(255,255,255))
					break;	// If a color is more than white, then it is invalid

				backColor = pLVCD->clrTextBk;
			}

			CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);

			CRect rcIcon, rcCell;
			VERIFY( owner.GetCellRect(nRow, nCol, LVIR_ICON, rcIcon) );
			VERIFY( owner.GetCellRect(nRow, nCol, LVIR_BOUNDS, rcCell) );
			// When the label column is placed first it has a left-margin 
			if (nCol==0 && nCol==owner.GetFirstVisibleColumn())
			{
				int cxborder = ::GetSystemMetrics(SM_CXBORDER);
				rcCell.left += cxborder*2;
			}

			// Remove white margin between cell-image and cell-text
			rcCell.right = rcIcon.right + 2;
			CBrush brush(backColor);
			pDC->FillRect(&rcCell, &brush);

			// Draw icon
			COLORREF oldBkColor = pImageList->SetBkColor(backColor);
			pImageList->Draw (	pDC,  
								nImage,  
								rcIcon.TopLeft(),
								ILD_NORMAL );
			pImageList->SetBkColor(oldBkColor);

			if (nCol==0 && owner.GetExtendedStyle() & LVS_EX_CHECKBOXES)
			{
				CImageList* pStateImageList = owner.GetImageList(LVSIL_STATE);
				if (pImageList==NULL)
					break;

				int checkState = owner.GetCheck(nRow);
				COLORREF oldStateBkColor = pStateImageList->SetBkColor(backColor);
				pStateImageList->Draw (	pDC,  
									checkState,  
									rcCell.TopLeft(),
									ILD_NORMAL );
				pStateImageList->SetBkColor(oldStateBkColor);
			}

		} break;
	}

	// Perform standard drawing
	CGridRowTraitText::OnCustomDraw(owner, pLVCD, pResult);
}
//------------------------------------------------------------------------
//! Appends the checkbox state images to the list control image list
//!
//! @param owner The list control adding column
//! @param imagelist The image list assigned to the list control
//! @return Image index where the two state images (unchecked/checked) was inserted
//------------------------------------------------------------------------
int CGridColumnTraitImage::AppendStateImages(CGridListCtrlEx& owner, CImageList& imagelist)
{
	if (!(owner.GetExtendedStyle() & LVS_EX_SUBITEMIMAGES))
		owner.SetExtendedStyle(owner.GetExtendedStyle() | LVS_EX_SUBITEMIMAGES);

	if (!imagelist)
		imagelist.Create(16, 16, ILC_COLOR16 | ILC_MASK, 1, 0);

	if (!owner.GetImageList(LVSIL_SMALL))
		owner.SetImageList(&imagelist, LVSIL_SMALL);

	VERIFY(owner.GetImageList(LVSIL_SMALL) == &imagelist);

	bool createdStateImages = false;
	CImageList* pStateList = owner.GetImageList(LVSIL_STATE);
	if (pStateList == NULL)
	{
		if (!(owner.GetExtendedStyle() & LVS_EX_CHECKBOXES))
		{
			createdStateImages = true;
			owner.SetExtendedStyle(owner.GetExtendedStyle() | LVS_EX_CHECKBOXES);
			pStateList = owner.GetImageList(LVSIL_STATE);
		}
	}
	int imageCount = -1;
	ASSERT(pStateList != NULL);
	if (pStateList != NULL && pStateList->GetImageCount() >= 2)
	{
		imageCount = imagelist.GetImageCount();

		// Get the icon size of current imagelist
		CSize iconSize(16, 16);
		if (imageCount > 0)
		{
			IMAGEINFO iconSizeInfo = { 0 };
			VERIFY(imagelist.GetImageInfo(0, &iconSizeInfo));
			iconSize =
				CSize(iconSizeInfo.rcImage.right - iconSizeInfo.rcImage.left,
					iconSizeInfo.rcImage.bottom - iconSizeInfo.rcImage.top);
		}

		// Scale the icon-position if necessary
		CPoint iconPos(1, 0); // +1 pixel to avoid overlap with left-grid-line
		{
			IMAGEINFO stateSizeInfo = { 0 };
			VERIFY(pStateList->GetImageInfo(0, &stateSizeInfo));
			int stateIconHeight = stateSizeInfo.rcImage.bottom - stateSizeInfo.rcImage.top;
			if (iconSize.cy > stateIconHeight)
				iconPos.y = (iconSize.cy - stateIconHeight) / 2;
		}

		// Redraw the state-icon to match the icon size of the current imagelist (without scaling image)
		CClientDC clienDC(&owner);
		CDC memDC;
		VERIFY(memDC.CreateCompatibleDC(&clienDC));
		CBitmap dstBmp;
		VERIFY(dstBmp.CreateCompatibleBitmap(&clienDC, iconSize.cx, iconSize.cy));

		CBitmap* pBmpOld = memDC.SelectObject(&dstBmp);
		COLORREF oldBkColor = pStateList->SetBkColor(imagelist.GetBkColor());
		CBrush brush(imagelist.GetBkColor());
		memDC.FillRect(CRect(0, 0, iconSize.cx, iconSize.cy), &brush);
		VERIFY(pStateList->Draw(&memDC, 0, iconPos, ILD_NORMAL));
		memDC.SelectObject(pBmpOld);
		VERIFY(imagelist.Add(&dstBmp, oldBkColor) != -1);
		pBmpOld = memDC.SelectObject(&dstBmp);
		memDC.FillRect(CRect(0, 0, iconSize.cx, iconSize.cy), &brush);
		VERIFY(pStateList->Draw(&memDC, 1, iconPos, ILD_NORMAL));
		memDC.SelectObject(pBmpOld);
		VERIFY(imagelist.Add(&dstBmp, oldBkColor) != -1);
		pStateList->SetBkColor(oldBkColor);
	}
	if (createdStateImages)
		owner.SetExtendedStyle(owner.GetExtendedStyle() & ~LVS_EX_CHECKBOXES);

	return imageCount;
}
Esempio n. 15
0
//------------------------------------------------------------------------
//! Overrides the custom draw handler, to allow custom coloring of rows.
//!		- Focus rectangle display
//!		- Use font size to increase row-height, but keep cell font-size
//!		- Alternate row coloring
//!
//! @param owner The list control drawing
//! @param pLVCD Pointer to NMLVCUSTOMDRAW structure
//! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.)
//------------------------------------------------------------------------
void CGridRowTraitText::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult)
{
    int nRow = (int)pLVCD->nmcd.dwItemSpec;

    switch (pLVCD->nmcd.dwDrawStage)
    {
    case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
    {
        // Remove the selection color for the focus cell, to make it easier to see focus
        if (m_InvertCellSelection)
        {
            int nCol = pLVCD->iSubItem;
            if (pLVCD->nmcd.uItemState & CDIS_SELECTED)
            {
                if (owner.GetFocusCell()==nCol && owner.GetFocusRow()==nRow)
                {
                    pLVCD->nmcd.uItemState &= ~CDIS_SELECTED;
                }
            }
        }

        // Bug in Vista causes the cell color from previous cell to be used in the next
        // even if having reverted the cell coloring in subitem-post-paint
        if (pLVCD->clrText <= RGB(255,255,255) || pLVCD->clrTextBk <= RGB(255,255,255))
        {
            pLVCD->clrText = CLR_DEFAULT;
            pLVCD->clrTextBk = CLR_DEFAULT;

            if (UpdateTextColor(nRow, pLVCD->clrText))
                *pResult |= CDRF_NEWFONT;

            if (UpdateBackColor(nRow, pLVCD->clrTextBk))
                *pResult |= CDRF_NEWFONT;

            if (owner.OnDisplayRowColor(nRow, pLVCD->clrText, pLVCD->clrTextBk))
                *pResult |= CDRF_NEWFONT;
        }
    }
    break;

    // Before painting a row
    case CDDS_ITEMPREPAINT:
    {
        if (UpdateTextColor(nRow, pLVCD->clrText))
            *pResult |= CDRF_NEWFONT;

        if (UpdateBackColor(nRow, pLVCD->clrTextBk))
            *pResult |= CDRF_NEWFONT;

        if (owner.OnDisplayRowColor(nRow, pLVCD->clrText, pLVCD->clrTextBk))
            *pResult |= CDRF_NEWFONT;

        LOGFONT newFont = {0};
        if (owner.OnDisplayRowFont(nRow, newFont))
        {
            // New font provided
            CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
            CFont* pNewFont = new CFont;
            VERIFY( pNewFont->CreateFontIndirect(&newFont) );
            m_pOldFont = pDC->SelectObject(pNewFont);
            m_FontAllocated = true;
            *pResult |= CDRF_NOTIFYPOSTPAINT;	// We need to restore the original font
            *pResult |= CDRF_NEWFONT;
        }
        else
        {
            if (owner.GetFont()!=owner.GetCellFont())
            {
                // Using special cell font because of SetMargin()
                CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
                m_pOldFont = pDC->SelectObject(owner.GetCellFont());
                *pResult |= CDRF_NOTIFYPOSTPAINT;	// We need to restore the original font
                *pResult |= CDRF_NEWFONT;
            }
        }

        if (pLVCD->nmcd.uItemState & CDIS_FOCUS)
        {
            if (owner.GetFocus() != &owner)
                break;

            // If drawing focus row, then remove focus state and request to draw it later
            //	- Row paint request can come twice, with and without focus flag
            //	- Only respond to the one with focus flag, else DrawFocusRect XOR will cause solid or blank focus-rectangle
            if (owner.GetFocusRow() == nRow)
            {
                if (owner.GetFocusCell() >= 0)
                {
                    // We want to draw a cell-focus-rectangle instead of row-focus-rectangle
                    pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
                    *pResult |= CDRF_NOTIFYPOSTPAINT;
                }
                else if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES)
                {
                    // Avoid bug where bottom of focus rectangle is missing when using grid-lines
                    //	- Draw the focus-rectangle for the entire row (explicit)
                    pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
                    *pResult |= CDRF_NOTIFYPOSTPAINT;
                }
            }
        }
    }
    break;

    // After painting a row
    case CDDS_ITEMPOSTPAINT:
    {
        if (m_pOldFont!=NULL)
        {
            // Restore the original font
            CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
            CFont* pNewFont = pDC->SelectObject(m_pOldFont);
            if (m_FontAllocated)
            {
                m_FontAllocated = false;
                delete pNewFont;
            }
            m_pOldFont = NULL;
        }

        if (CRect(pLVCD->nmcd.rc)==CRect(0,0,0,0))
            break;

        if (owner.GetFocusRow()!=nRow)
            break;

        if (owner.GetFocus() != &owner)
            break;

        // Perform the drawing of the focus rectangle
        if (owner.GetFocusCell() >= 0)
        {
            // Draw the focus-rectangle for a single-cell
            CRect rcHighlight;
            CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);

            VERIFY( owner.GetCellRect(nRow, owner.GetFocusCell(), LVIR_BOUNDS, rcHighlight) );

            int cxborder = ::GetSystemMetrics(SM_CXBORDER);

            // When the label column is placed first it has a left-margin
            if (owner.GetFocusCell()==0 && owner.GetFocusCell()==owner.GetFirstVisibleColumn())
            {
                rcHighlight.left += cxborder*2;
            }
            else
                // Prevent focus rectangle to overlap with cell-image (Only room for this when not first column)
                if (owner.GetFirstVisibleColumn()!=owner.GetFocusCell())
                {
                    rcHighlight.left -= cxborder;
                }

            // Adjust rectangle according to grid-lines
            if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES)
            {
                rcHighlight.bottom -= cxborder;
            }

            pDC->DrawFocusRect(rcHighlight);
        }
        else if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES)
        {
            // Avoid bug where bottom of focus rectangle is missing when using grid-lines
            //	- Draw the focus-rectangle for the entire row (explicit)
            CRect rcHighlight;
            CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
            // Using LVIR_BOUNDS to get the entire row-rectangle
            VERIFY( owner.GetItemRect(nRow, rcHighlight, LVIR_BOUNDS) );

            // Adjust rectangle according to grid-lines
            int cxborder = ::GetSystemMetrics(SM_CXBORDER);
            rcHighlight.bottom -= cxborder;
            pDC->DrawFocusRect(rcHighlight);
        }
    }
    break;
    }
}
//------------------------------------------------------------------------
//! Appends the checkbox state images to the list control image list
//!
//! @param owner The list control adding column
//! @param imagelist The image list assigned to the list control
//! @return Image index where the two state images (unchecked/checked) was inserted
//------------------------------------------------------------------------
int CGridColumnTraitImage::AppendStateImages(CGridListCtrlEx& owner, CImageList& imagelist)
{
	if (!(owner.GetExtendedStyle() & LVS_EX_SUBITEMIMAGES))
		owner.SetExtendedStyle(owner.GetExtendedStyle() | LVS_EX_SUBITEMIMAGES);

	if (!imagelist)
		imagelist.Create(16, 16, ILC_COLOR16 | ILC_MASK, 1, 0);

	if (!owner.GetImageList(LVSIL_SMALL))
		owner.SetImageList(&imagelist, LVSIL_SMALL);

	VERIFY( owner.GetImageList(LVSIL_SMALL)==&imagelist );

	bool createdStateImages = false;
	CImageList* pStateList = owner.GetImageList(LVSIL_STATE);
	if (pStateList==NULL)
	{
		if (!(owner.GetExtendedStyle() & LVS_EX_CHECKBOXES))
		{
			createdStateImages = true;
			owner.SetExtendedStyle(owner.GetExtendedStyle() | LVS_EX_CHECKBOXES);
			pStateList = owner.GetImageList(LVSIL_STATE);
		}
	}
	int imageCount = -1;
	ASSERT(pStateList!=NULL);
	if (pStateList!=NULL)
	{
		imageCount = imagelist.GetImageCount();
		HICON uncheckedIcon = pStateList->ExtractIcon(0);
		imagelist.Add(uncheckedIcon);
		DestroyIcon(uncheckedIcon);
		HICON checkedIcon = pStateList->ExtractIcon(1);
		imagelist.Add(checkedIcon);
		DestroyIcon(checkedIcon);
	}
	if (createdStateImages)
		owner.SetExtendedStyle(owner.GetExtendedStyle() & ~LVS_EX_CHECKBOXES);

	return imageCount;
}