加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

VC可编辑可变颜色的列表控件CListCtrl

(2017-12-22 15:51:50)
标签:

可编辑可变颜色

列表控件clistctrl

分类: 代码天地

列表控件CListCtrl 使用很广泛,但自身无法编辑单元格的内容,无法改变前景和背景颜色。
通过加入相关的函数,借助编辑框输入文本,组合框选择项目等来实现文本编辑
代码大部分来自网络,为了使用灵活使用,加入适当的代码,或者适当的改变。
比如:列的类型数组,列的组合框项目数组等。
修改的部分都使用红色标注。


主要 代码 如下 :


一 类头文件(3个类放到一个头文件内 ) EditListCtrl.h

#if !defined(AFX_EDITLISTCTRL_H__129EB9CC_D1CA_488B_A9E5_44793533DC86__INCLUDED_)
#define AFX_EDITLISTCTRL_H__129EB9CC_D1CA_488B_A9E5_44793533DC86__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EditListCtrl.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// EditListCtrl window

//1 CListCtrlEdit

class CListCtrlEdit : public CEdit
{
DECLARE_DYNAMIC(CListCtrlEdit)

public:
CListCtrlEdit();
virtual ~CListCtrlEdit();

protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnKillFocus(CWnd* pNewWnd);
};



//2 CListCtrlCombo

class CListCtrlCombo : public CComboBox
{
DECLARE_DYNAMIC(CListCtrlCombo)

public:
CListCtrlCombo();
virtual ~CListCtrlCombo();

protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnKillFocus(CWnd* pNewWnd);
};


//3  CEditableListCtrl

class CEditListCtrl : public CListCtrl
{
DECLARE_DYNAMIC(CEditListCtrl)
enum {listCtrl_LABEL=0,listCtrl_EDIT=1,listCtrl_COMBO=2,listCtrl_STATIC=3};

public:
CEditListCtrl();
virtual ~CEditListCtrl();

protected:
DECLARE_MESSAGE_MAP()

public:
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);


void ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl);
void ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl);
afx_msg LRESULT OnEditEnd(WPARAM wParam,LPARAM lParam);
afx_msg LRESULT OnComboEnd(WPARAM wParam,LPARAM lParam);


private:
CListCtrlEdit m_edit;
CListCtrlCombo m_combo;
int nItem;         // 当前点击项
int nSubItem;            // 当前点击子项
bool m_bEditVisible;     // Edit是否可见
bool m_bComboVisible;    // ComboBox是否可见

//-----------------新增部分----------------------
public:
void column_type(int nColumn=0);//初始化各列的类型 
void column_string(int nColumn=0);//初始化各列的选择数目项,主要针对组合框 

void OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult )  ;//1 自绘函数改变颜色声明 

public:
int m_column_num;//列的个数
int *m_column_type;//列的类型, 区分是编辑框,组合框,还是普通的文本框
CString *m_column_string;//各个列的组合框的项目字符数足


};

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

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EDITLISTCTRL_H__129EB9CC_D1CA_488B_A9E5_44793533DC86__INCLUDED_)


二 类 的实现文件(3个类放到一个实现文件内 ) EditListCtrl.cpp

// EditListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "editList.h"
#include "EditListCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//1
//#include "ListCtrlEdit.h"
#define WM_USER_EDIT_END WM_USER+101
// CListCtrlEdit
IMPLEMENT_DYNAMIC(CListCtrlEdit, CEdit)
CListCtrlEdit::CListCtrlEdit()
{
}
CListCtrlEdit::~CListCtrlEdit()
{
}
BEGIN_MESSAGE_MAP(CListCtrlEdit, CEdit)
ON_WM_KILLFOCUS()
END_MESSAGE_MAP()
// CListCtrlEdit message handlers
void CListCtrlEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// TODO: Add your message handler code here
CWnd *pParent = this->GetParent();
::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, 0, 0);
}

//2
//#include "ListCtrlCombo.h"
#define WM_USER_COMBO_END WM_USER+102
// CListCtrlCombo
IMPLEMENT_DYNAMIC(CListCtrlCombo, CComboBox)
CListCtrlCombo::CListCtrlCombo()
{

}
CListCtrlCombo::~CListCtrlCombo()
{
}
BEGIN_MESSAGE_MAP(CListCtrlCombo, CComboBox)
ON_WM_KILLFOCUS()
END_MESSAGE_MAP()
// CListCtrlCombo message handlers
void CListCtrlCombo::OnKillFocus(CWnd* pNewWnd)
{
CComboBox::OnKillFocus(pNewWnd);

// TODO: Add your message handler code here
CWnd *pParent = this->GetParent();
::PostMessage(pParent->GetSafeHwnd(), WM_USER_COMBO_END, 0, 0);
}

//3
//#include "EditableListCtrl.h"

#define WM_USER_EDIT_END  WM_USER+101
#define WM_USER_COMBO_END WM_USER+102

// CEditListCtrl

IMPLEMENT_DYNAMIC(CEditListCtrl, CListCtrl)

CEditListCtrl::CEditListCtrl() 
: m_bEditVisible(false), m_bComboVisible(false), nItem(-1), nSubItem(-1)
{
m_column_string=NULL;
m_column_type=NULL;
}

CEditListCtrl::~CEditListCtrl()
{
if (m_column_type) delete []m_column_type;
for (int i=0;i < m_column_num ;i++)
{
//if (m_column_string[i])
{
m_column_string[i]="";//.ReleaseBuffer();
// delete []m_column_string[i];
// m_column_string[i]=NULL;
}
//delete m_column_string;
}
m_column_string=NULL;

}

void CEditListCtrl::column_type(int nColumn)//
{
if (nColumn==0)
{
nColumn=CEditListCtrl::GetHeaderCtrl()->GetItemCount();
}
m_column_num=nColumn;//列的个数

if (m_column_type) delete []m_column_type;
m_column_type=new int [m_column_num];//列类型数组的声明
for (int i=0;i m_column_num ;i++)
{
m_column_type[i]=0;
}
}
void CEditListCtrl::column_string(int nColumn)//
{
if (nColumn==0)
{
nColumn=CEditListCtrl::GetHeaderCtrl()->GetItemCount();
}
m_column_num=nColumn;//列的个数

if (m_column_string)
{
for (int i=0;i m_column_num ;i++)
{
// if (m_column_string[i])
{
m_column_string[i]="";
// delete []m_column_string[i];
// m_column_string[i]=NULL;
}
}
delete m_column_string;
m_column_string=NULL;
}

m_column_string=new CString [m_column_num];
for (int i=0;i m_column_num ;i++)
{
m_column_string[i]="";
}
}

void CEditListCtrl::ShowEdit(bool bShow, int nItem, int nSubItem, CRect rcCtrl)
{
  m_bEditVisible = bShow;

  if (m_edit.m_hWnd == NULL)
  {
 m_edit.Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN | WS_BORDER,
CRect(0,0,0,0), this, 1001);
      m_edit.ShowWindow(SW_HIDE);
 
      CFont tpFont;
      tpFont.CreateStockObject(DEFAULT_GUI_FONT);
      m_edit.SetFont(&tpFont);
      tpFont.DeleteObject();
  }

  if (bShow == TRUE)
  {
     CString cstrItem = GetItemText(nItem, nSubItem);
     m_edit.MoveWindow(&rcCtrl);
     m_edit.ShowWindow(SW_SHOW);
     m_edit.SetWindowText(cstrItem);
     m_edit.SetFocus();
     m_edit.SetSel(-1); 
  }
  else
      m_edit.ShowWindow(SW_HIDE);
}

void CEditListCtrl::ShowCombo(bool bShow, int nItem, int nSubItem, CRect rcCtrl)
{
m_bComboVisible = bShow;

if (m_combo.m_hWnd == NULL)
{
m_combo.Create(ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_CHILD | ES_LEFT | CBS_DROPDOWNLIST,
CRect(0,0,0,0), this, 1002);
m_combo.ShowWindow(SW_HIDE);

CFont tpFont;
tpFont.CreateStockObject(DEFAULT_GUI_FONT);
m_combo.SetFont(&tpFont);
tpFont.DeleteObject();

// m_combo.AddString(TEXT("Male"));
// m_combo.AddString(TEXT("Female"));

}

if (bShow == TRUE)
{
//1 根据本列实际的项目m_column_string[nSubItem], 来动态填充 组合框
CString str1="",str2="",str3="";
int nPos=0;
str3="\n";//按换行符拆分,这样确保内容可以是各种字符
str1=m_column_string[nSubItem];
str1.TrimLeft();str1.TrimRight();

if (str1!="")//!str1.IsEmpty())
{
nPos=str1.FindOneOf(str3);
while(nPos>=0)
{
str2=str1.Mid(0,nPos);
m_combo.AddString(str2);
str1=str1.Mid(nPos+1);
nPos=str1.FindOneOf(str3);

}
if (str1!="") {str2=str1;m_combo.AddString(str2);}
}

m_combo.SetCurSel(-1);

CString cstrItem = GetItemText(nItem, nSubItem);
//2  根据组合框的(条目数+1),编辑区域占据一个所以+1, 来设置组合框的下拉大小
// m_combo.MoveWindow(&rcCtrl);
CRect rect;
m_combo.GetDroppedControlRect(&rect );
int nn=m_combo.GetCount(),hh=rcCtrl.Height();
rect.SetRect(rcCtrl.left,rcCtrl.top , rcCtrl.right,rcCtrl.top+(nn+1)*hh);
m_combo.MoveWindow(&rect);

m_combo.ShowWindow(SW_SHOW);
m_combo.SetWindowText(cstrItem);
m_combo.SetFocus();
int nItems = m_combo.GetCount();
for (int i=0; i < nItems ; ++i)
{
CString cstrItemText;
m_combo.GetLBText(i, cstrItemText);
if (cstrItem == cstrItemText)
{
m_combo.SetCurSel(i);
break;
}
}
}
else
{//隐含时 清理组合框, 再次显示时, 根据实际的列 ,动态填充
m_combo.ResetContent();//清理
m_combo.ShowWindow(SW_HIDE);
}

}

BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl)
ON_WM_LBUTTONDBLCLK()
ON_NOTIFY(HDN_BEGINTRACKA, 0, CEditListCtrl::OnHdnBegintrack)
ON_NOTIFY(HDN_BEGINTRACKW, 0, CEditListCtrl::OnHdnBegintrack)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_MESSAGE(WM_USER_EDIT_END, OnEditEnd)
ON_MESSAGE(WM_USER_COMBO_END, OnComboEnd)
// ON_NOTIFY ( NM_CUSTOMDRAW,IDC_LIST, OnCustomdrawMyList )  //2 手工加入消息影射
END_MESSAGE_MAP()

// CEditListCtrl message handlers
////3 手工添加本函数,设置ListCtrl某行某列单元格的前景,背景颜色
void CEditListCtrl::OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult )  
    //This code based on Michael Dunn's excellent article on  
    //list control custom draw at http://www.codeproject.com/listctrl/lvcustomdraw.asp  
    NMLVCUSTOMDRAW* pLVCD = reinterpret_cast( pNMHDR );  
    // Take the default processing unless we set this to something else below.  
    *pResult = CDRF_DODEFAULT;  
    // First thing - check the draw stage. If it's the control's prepaint  
    // stage, then tell Windows we want messages for every item.  
    if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )  
    {  
        *pResult = CDRF_NOTIFYITEMDRAW;  
    }  
    else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )  
    {  
        // This is the notification message for an item.  We'll request  
        // notifications before each subitem's prepaint stage.  
        *pResult = CDRF_NOTIFYSUBITEMDRAW;  
    }  
    else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage )  
    {  
COLORREF m_clrText,m_clrTextBk;//前景色,背景色
int nRow,nCol;//行 , 列
nRow = static_cast (pLVCD->nmcd.dwItemSpec);
nCol=pLVCD->iSubItem;
// 获取ListCtrl当前单元格的文本
CString str = GetItemText(nRow ,nCol);//m_list.

m_clrText = pLVCD->clrText ;//设置前景文本色
m_clrTextBk = pLVCD->clrTextBk;//设置背景色
if (m_column_type[nCol]==3)//可变背景列
{
m_clrTextBk=(DWORD)atoi(str);
}
pLVCD->clrText = m_clrText;//设置前景文本色
pLVCD->clrTextBk=m_clrTextBk;//设置背景色

*pResult = CDRF_DODEFAULT;
    }  
}  


LRESULT CEditListCtrl::OnEditEnd(WPARAM wParam, LPARAM lParam)
{
CString strText;
    m_edit.GetWindowText(strText);
    SetItemText(nItem,nSubItem,strText);

ShowEdit(false, -1, -1, CRect());
 
    return 0;
}

LRESULT CEditListCtrl::OnComboEnd(WPARAM wParam, LPARAM lParam)
{
int nSel = m_combo.GetCurSel();
CString cstrTextSel;
m_combo.GetLBText(nSel, cstrTextSel);
    SetItemText(nItem, nSubItem, cstrTextSel);

ShowCombo(false, -1, -1, CRect());
 
    return 0;
}

void CEditListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect rcCtrl;
LVHITTESTINFO lvhti;
lvhti.pt = point;
nItem = SubItemHitTest(&lvhti);
if (nItem == -1) 
return;

nSubItem = lvhti.iSubItem;
GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl);

//查看列的类型
switch( m_column_type[lvhti.iSubItem])
{
case 0://listCtrl_LABEL
break;
case 1://listCtrl_EDIT
ShowEdit(TRUE, nItem, nSubItem, rcCtrl);
break;
case 2://listCtrl_COMBO
ShowCombo(TRUE, nItem, nSubItem, rcCtrl);
break;
case 3://listCtrl_STATIC
{
CString str = GetItemText(nItem ,nSubItem);
COLORREF clr=atol(str);//RGB(255,0,0);
CColorDialog  dlg;
dlg.m_cc.lpCustColors=&clr;//原来颜色
if (IDOK==dlg.DoModal())
{
clr=dlg.GetColor();//新选择的颜色
str.Format("%ld",clr);
SetItemText(nItem ,nSubItem,str);//颜色数值设置为单元格的文本
this->Invalidate();//刷新列表
}
}
break;


default:
break;

}


CListCtrl::OnLButtonDblClk(nFlags, point);
}

void CEditListCtrl::OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER phdr = reinterpret_cast(pNMHDR);
// TODO: Add your control notification handler code here
if (m_edit.m_hWnd != NULL && m_bEditVisible)
OnEditEnd(0, 0);
if (m_combo.m_hWnd != NULL && m_bComboVisible)
OnComboEnd(0, 0);
*pResult = 0;
}

void CEditListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (m_edit.m_hWnd != NULL && m_bEditVisible)
OnEditEnd(0, 0);
if (m_combo.m_hWnd != NULL && m_bComboVisible)
OnComboEnd(0, 0);
CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CEditListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (m_edit.m_hWnd != NULL && m_bEditVisible)
OnEditEnd(0, 0);
if (m_combo.m_hWnd != NULL && m_bComboVisible)
OnComboEnd(0, 0);
CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}



三 对话框头文件中的代码

// editListDlg.h : header file
//

#if !defined(AFX_EDITLISTDLG_H__6617E8B1_8F6A_4959_AAAA_D66822A926A5__INCLUDED_)
#define AFX_EDITLISTDLG_H__6617E8B1_8F6A_4959_AAAA_D66822A926A5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "EditListCtrl.h"

/////////////////////////////////////////////////////////////////////////////
// CEditListDlg dialog

class CEditListDlg : public CDialog
{
// Construction
public:
CEditListDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
//{{AFX_DATA(CEditListDlg)
enum { IDD = IDD_EDITLIST_DIALOG };
CEditListCtrl m_listCtrl;
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEditListDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
void OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult )  ;//1 手工加入自绘函数声明 

// Implementation
protected:
HICON m_hIcon;

// Generated message map functions
//{{AFX_MSG(CEditListDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EDITLISTDLG_H__6617E8B1_8F6A_4959_AAAA_D66822A926A5__INCLUDED_)



四 对话框实现文件的主要代码


void CEditListDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CEditListDlg)
DDX_Control(pDX, IDC_LIST1, m_listCtrl);
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CEditListDlg, CDialog)
//{{AFX_MSG_MAP(CEditListDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_NOTIFY ( NM_CUSTOMDRAW,IDC_LIST1, OnCustomdrawMyList )  //2 手工加入消息影射
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEditListDlg message handlers

BOOL CEditListDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Style
DWORD dwStyle = ::GetWindowLong(m_listCtrl.GetSafeHwnd(), GWL_STYLE); 
dwStyle |= LVS_SINGLESEL;       //只可单行选中
dwStyle |= LVS_SHOWSELALWAYS;   //Always show selection
  dwStyle |=LVS_REPORT ; //报告风格
::SetWindowLong(m_listCtrl.GetSafeHwnd(), GWL_STYLE, dwStyle);

// Extended Style
DWORD dwStyleEx = m_listCtrl.GetExtendedStyle();
dwStyleEx |= LVS_EX_GRIDLINES;        //网格线
dwStyleEx |= LVS_EX_FULLROWSELECT;    //整行高亮
dwStyleEx |= LVS_EX_CHECKBOXES;       //Item前生成check box
m_listCtrl.SetExtendedStyle(dwStyleEx);

// 插入列
m_listCtrl.InsertColumn(0, TEXT("姓名"), LVCFMT_LEFT, 100);
m_listCtrl.InsertColumn(1, TEXT("年龄"), LVCFMT_LEFT, 60);
m_listCtrl.InsertColumn(2, TEXT("性别"), LVCFMT_LEFT, 80);
m_listCtrl.InsertColumn(3, TEXT("上衣颜色"), LVCFMT_LEFT, 80);

//
int nItem = 0;
nItem = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), TEXT("张扬"), 0);
m_listCtrl.SetItemText(nItem, 1, TEXT("26"));   //子项从1开始,0代表主项
m_listCtrl.SetItemText(nItem, 2, TEXT("男"));
m_listCtrl.SetItemText(nItem, 3, TEXT("255"));//255 数值 代表背景的颜色值
nItem = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), TEXT("王艳"), 0);
m_listCtrl.SetItemText(nItem, 1, TEXT("24"));
m_listCtrl.SetItemText(nItem, 2, TEXT("女"));
m_listCtrl.SetItemText(nItem, 3, TEXT("65280"));//255*256 数值 代表背景的颜色值
nItem = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), TEXT("李娜"), 0);
m_listCtrl.SetItemText(nItem, 1, TEXT("24"));
m_listCtrl.SetItemText(nItem, 2, TEXT("女"));
m_listCtrl.SetItemText(nItem, 3, TEXT("65535"));//255+255*256 数值 代表背景的颜色值

//这些语句最好放到初始化的最后,至少要放到插入完列以后,否则需要传递列数
m_listCtrl.column_type();//获得列数,并初始化 各列的默认类型,不同的类型见下面的赋值语句
m_listCtrl.m_column_type[1]=1;//第2列编辑框
m_listCtrl.m_column_type[2]=2;//第3列组合框
m_listCtrl.m_column_type[3]=3;//第4列背景变色框,文本的数值为背景的颜色数值

m_listCtrl.column_string();//初始化各列的项目内容, 组合框列的项目要单独赋值,见下面语句
m_listCtrl.m_column_string[2]="男\n女\n";//第3列为性别,组合框的内容以换行符分割

return TRUE;  // return TRUE  unless you set the focus to a control
}
void CEditListDlg::OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult )  
m_listCtrl.OnCustomdrawMyList (  pNMHDR,  pResult )  ;//调用控件类函数改变颜色
}

五  运行效果

VC可编辑可变颜色的列表控件CListCtrl

0

阅读 收藏 喜欢 打印举报/Report
后一篇:喜迎2018
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有