Hello,
How can I change the colour (foreground or background) of one single field in a CListCtrl?
Thank you for answers.
Printable View
Hello,
How can I change the colour (foreground or background) of one single field in a CListCtrl?
Thank you for answers.
Only by drawing every item for yourself. Set the LVS_OWNERDRAWFIXED-style and override DrawItem.
You do NOT need to use owner draw for what you want to do. Use Custom Draw. See the Custom Draw Reference in the Platform SDK docs for specifics.
You create a class that is derived form CListCtrl, handle the NM_CUSTOMDRAW message in that class, and declare your list control member variable to be of that class.
For example, here is a class that uses custom draw to paint a numeric value in red foreground if the value is negative and if it is in a certain column of the list control.
The member variable of the dialog that uses this list control would be declared like CHedgeFeeListCtrl m_listctrlFees;
header file
Implementation file:Code:#if !defined(AFX_HEDGEFEELISTCTRL_H__636791CC_008B_403D_A30B_91B92D91597D__INCLUDED_)
#define AFX_HEDGEFEELISTCTRL_H__636791CC_008B_403D_A30B_91B92D91597D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CHedgeFeeListCtrl : public CListCtrl
{
// Construction
public:
CHedgeFeeListCtrl();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHedgeFeeListCtrl)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CHedgeFeeListCtrl();
// Generated message map functions
protected:
//{{AFX_MSG(CHedgeFeeListCtrl)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_HEDGEFEELISTCTRL_H__636791CC_008B_403D_A30B_91B92D91597D__INCLUDED_)
Code:#include "stdafx.h"
#include "billmain.h"
#include "HedgeFeeListCtrl.h"
#include "APLHedgeListDlg.h"
#include "..\Common\HedgeFeeListInfo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CHedgeFeeListCtrl::CHedgeFeeListCtrl()
{
}
CHedgeFeeListCtrl::~CHedgeFeeListCtrl()
{
}
BEGIN_MESSAGE_MAP(CHedgeFeeListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CHedgeFeeListCtrl)
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()
///////////////////////////////////////
/*
Purpose: Change fonts, etc. for drawing list control items and subitems
Input: None
*/
///////////////////
void CHedgeFeeListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
// for this notification, the structure is actually a
// NMLVCUSTOMDRAW that tells you what's going on with the custom
// draw action. So, we'll need to cast the generic pNMHDR pointer.
NMLVCUSTOMDRAW* pCD = (NMLVCUSTOMDRAW*)pNMHDR;
int row = pCD->nmcd.dwItemSpec;
if(row < 0 || row > GetItemCount() - 1)
{
if(pCD->nmcd.dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYSUBITEMDRAW;
}
else
{
*pResult = CDRF_DODEFAULT;
}
return;
}
int pos = (int)GetItemData(row);
CHedgeFeeListInfo hfli = CAPLHedgeListDlg::m_vHedgeInfo[pos];
bool bNegative = false;
if(hfli.m_Amount.int64 < 0)
{
bNegative = true;
}
switch(pCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.
break;
case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW;
break;
case CDDS_ITEMPREPAINT|CDDS_SUBITEM:
{
if(pCD->iSubItem == 9)
{
pCD->clrText = BILLING_BLACK;
*pResult = CDRF_NEWFONT;
}
else if(pCD->iSubItem == 8 && bNegative)
{
pCD->clrText = BILLING_RED;
*pResult = CDRF_NEWFONT;
}
else
{
*pResult = CDRF_DODEFAULT;
}
break;
}
default:// it wasn't a notification that was interesting to us.
*pResult = CDRF_DODEFAULT;
}
}
I want to move the part of the logic which decides whether we need to draw it in Red ForeGround or not from void CHedgeFeeListCtrl::OnCustomDraw() method to the CAPLHedgeListDlg itself. I guess this can be done by handling the NM_CUSTOMDRAW notification in the CAPLHedgeListDlg itself. But I need to do something in the CHedgeFeeListCtrl::OnCustomDraw() method first, then in the CAPLHedgeListDlg::OnCustomDraw() method I need to do some more thing. How to achieve this?
No, it cannot, unless you do some fancy message rerouting. Windows sends the draw command to the list control, not to the owner of the list control, and it is sent for every item in every row of the list control.Quote:
I guess this can be done by handling the NM_CUSTOMDRAW notification in the CAPLHedgeListDlg itself.
You are probably better off puting info that determines how to draw an item in the item's data (using SetItemData). That's the usual way, and it is straight-forward. In many list controls for which I use custom draw, SetItemData is passed a pointer to a structure that contains whatever I need, if a simple data type is insufficient.
this is jsut an idea but try selchage...adn basicly overdite it , amke another funciotn that dose the same nad then make that be set in onINitDialog on some line and changed the color of the selchage....i donno but it might work if ,,,,,,
Thanks for the reply. I solved this by using the message reflection. I added ON_NOTIFY_REFLECT_EX() in the list ctrl and ON_NOTIFY in the dialog. In the listctrl handler after doing the required stuff I return FALSE to notify the parent i.e dialog.