Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537311
  • 博文数量: 576
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5020
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(576)

文章存档

2011年(1)

2008年(575)

我的朋友

分类:

2008-10-14 14:51:33

修改一个完全颜色的CListCtrl类

作者:



  在使用CListCtrl控件的过程中,我们会发现使用及其不方便,特别是在使用“report"显示模式时, 想给指定条目添加背景颜色,CListCtrl控件所提供的设置颜色函数只能使得控件的界面变得好看一些,根本不能满足我们的要求,我们无法把特定的一项或几项添加上不同的颜色以示区别。 幸运的是很多VC的使用者在改造CListCtrl类,使之更加功能强大上做了很多工作,开发出了各种各样的继承类来实现这个功能,Sven Freitag 就是其中的一员。他开发出了CListCtrl的继承类CColorListCtrl来实现给指定的条目加背景色的功能,并无偿的在网上公布给VC的使用者,我在源代码中收集了他的源程序,各位读者可以先阅读学习一下。

CColorListCtrl类示例代码运行效果如下图所示:




怎样使用CColorListCtrl类:
1、把下面的文件加入你的工程中去:

color.h
color.cpp
ColorListCtrl.h
ColorListCtrl.cpp

2、在对话框头文件中加入ColorListCtrl.h的说明,然后用CColorListCtrl代替CListCtrl声明成员变量。
3、具体的使用方法,请看示例代码中的ColoredListCtrlDlg.cpp文件。

CColorListCtrl类存在的不足:

  在使用CColorListCtrl类的过程中,我体会到了随意添加条目颜色的乐趣,但同时也发现它存在的一些不足之处。下面我列出color.h和color.cpp文件代码来进行分析。color.h源代码如下所示:

// Author: SFr frydaysoft@gmx.de

#ifndef AFX_COLOR_H__9FC7D36B_FC88_42FD_8DAA_2F70016038BA__INCLUDED_
#define AFX_COLOR_H__9FC7D36B_FC88_42FD_8DAA_2F70016038BA__INCLUDED_

#include "windows.h"

typedef enum 
{
	DEF_BACKGROUND=0, DEF_TEXT, DEF_SELBACKGROUND, DEF_SELTEXT, DEF_DESELBACKGROUND, DEF_DESELTEXT,
		BLACK,BLUE,GREEN,CYAN,RED,
		MANGENTA,YELLOW,WHITE,DARKBLUE,DARKGREEN,
		BLUEGREEN,BROWN,PURPUR,OLIV,DARKGRAY,
		LIGHTGRAY,LIGHTBLUE,DARKWHITE,MIDDLEGRAY
}
ITEM_COLOR;

typedef struct 
{
	char str[50];
	ITEM_COLOR col;
}ColorList;

#define COLLIST_MAX 25

extern ColorList colList[COLLIST_MAX];

COLORREF GetColorRef(ITEM_COLOR lParam);

#endif


color.cpp源代码如下所示:

// Author: SFr frydaysoft@gmx.de

#include "stdafx.h"
#include "color.h"

ColorList colList[COLLIST_MAX]=
{
	{"DEF_BACKGROUND",DEF_BACKGROUND},
	{"DEF_TEXT",DEF_TEXT},
	{"DEF_SELBACKGROUND",DEF_SELBACKGROUND},
	{"DEF_SELTEXT",DEF_SELTEXT},
	{"DEF_DESELBACKGROUND",DEF_DESELBACKGROUND},
	{"DEF_DESELTEXT",DEF_DESELTEXT},
	{"BLACK",BLACK},
	{"BLUE",BLUE},
	{"GREEN",GREEN},
	{"CYAN",CYAN},
	{"RED",RED},
	{"MANGENTA",MANGENTA},
	{"YELLOW",YELLOW},
	{"WHITE",WHITE},
	{"DARKBLUE",DARKBLUE},
	{"DARKGREEN",DARKGREEN},
	{"BLUEGREEN",BLUEGREEN},
	{"BROWN",BROWN},
	{"PURPUR",PURPUR},
	{"OLIV",OLIV},
	{"DARKGRAY",DARKGRAY},
	{"LIGHTGRAY",LIGHTGRAY},
	{"LIGHTBLUE",LIGHTBLUE},
	{"DARKWHITE",DARKWHITE},
	{"MIDDLEGRAY",MIDDLEGRAY}
};

COLORREF GetColorRef(ITEM_COLOR lParam) 
{
	switch (lParam)
	{
	case DEF_BACKGROUND: return ::GetSysColor(COLOR_WINDOW); break;
	case DEF_TEXT: return ::GetSysColor(COLOR_WINDOWTEXT); break;
	case DEF_SELBACKGROUND: return ::GetSysColor(COLOR_ACTIVECAPTION); break;
	case DEF_SELTEXT: return ::GetSysColor(COLOR_HIGHLIGHTTEXT); break;
	case DEF_DESELBACKGROUND: return ::GetSysColor(COLOR_INACTIVECAPTION); break;
	case DEF_DESELTEXT: return ::GetSysColor(COLOR_INACTIVECAPTIONTEXT ); break;
	case BLACK: return RGB(0,0,0); break; //black
	case BLUE: return RGB(0,0,255); break; //blue
	case GREEN: return RGB(0,255,0); break; //green
	case CYAN: return RGB(0,255,255); break; //cyan
	case RED: return RGB(255,0,0); break; //red
	case MANGENTA: return RGB(255,0,255); break; //mangenta
	case YELLOW: return RGB(255,255,0); break; //yellow
	case WHITE: return RGB(255,255,255);break; //white
	case DARKBLUE: return RGB(0,0,128); break; //dark-blue
	case DARKGREEN: return RGB(0,128,0); break; //dark-green
	case BLUEGREEN: return RGB(0,128,128); break; //blue-green
	case BROWN: return RGB(128,0,0); break; //brown
	case PURPUR: return RGB(128,0,128); break; //purpur
	case OLIV: return RGB(128,128,0); break; //oliv
	case DARKGRAY: return RGB(128,128,128);break; //dark-gray
	case LIGHTGRAY: return RGB(192,192,192);break; //light-gray
	case LIGHTBLUE: return RGB(166,202,240);break; //light-blue
	case DARKWHITE: return RGB(255,251,240);break; //dark-white
	case MIDDLEGRAY: return RGB(160,160,164);break; //middle-gray
	default: return RGB(0,128,0); break; //dark-green
	}
}		
  由上述源代码可以看出,CColorListCtrl类给我们提供的可供填充的颜色数量十分有限,只有BLACK,BLUE,GREEN,CYAN,RED,MANGENTA,YELLOW,WHITE,DARKBLUE,DARKGREEN,BLUEGREEN,BROWN,PURPUR,
OLIV,DARKGRAY,LIGHTGRAY,LIGHTBLUE,DARKWHITE,MIDDLEGRAY等几种,完全不能满足我们随时定制自己所需颜色的要求,因此我对这个类进行了一些修改,以使得能随心所欲的填充任何颜色。

对CColorListCtrl类修改的地方如下所示:
1、完全去掉color.h和color.cpp源文件,只把ColorListCtrl.h和ColorListCtrl.cpp源文件导入自己的工程中;
2、把ColorListCtrl.h头文件中的#include"color.h"去掉;
3、在类CMyLParam的定义和函数说明中进行如下修改:
源代码:
  ITEM_COLOR	*m_pBackColor;
  ITEM_COLOR	*m_pTextColor;  
	
  m_pBackColor=new ITEM_COLOR[column_count];
  m_pTextColor=new ITEM_COLOR[column_count];

  BOOL SetBackColor(ITEM_COLOR color, int iSub) 
  { 
       if (iSub修改后的代码: 
		
  COLORREF	*m_pBackColor;
  COLORREF	*m_pTextColor;
	
  m_pBackColor=new COLORREF[column_count];
  m_pTextColor=new COLORREF[column_count];  

  BOOL SetBackColor(COLORREF color, int iSub) {
      if (iSub
4、在类CColorListCtrl的定义和函数说明中进行如下修改:
  源代码: 
  
  BOOL SetItemTextColor(ITEM_COLOR color, int Index, int iSub);
  BOOL SetItemBackgndColor(ITEM_COLOR color, int Index, int iSub);
  BOOL CColorListCtrl::SetItemBackgndColor(ITEM_COLOR color, int Index, int iSub)	
  BOOL CColorListCtrl::SetItemTextColor(ITEM_COLOR color, int Index, int iSub)	  
修改后的代码:
  BOOL SetItemTextColor(COLORREF color, int Index, int iSub);
  BOOL SetItemBackgndColor(COLORREF color, int Index, int iSub);
  BOOL CColorListCtrl::SetItemBackgndColor(COLORREF color, int Index, int iSub)
  BOOL CColorListCtrl::SetItemTextColor(COLORREF color, int Index, int iSub)	  
删除的源代码:
            // only for TEST
            if (ret_index<3)
            {
                p->SetBackColor(ITEM_COLOR(ret_index+BLUE),0);
                p->SetTextColor(ITEM_COLOR(ret_index+RED ),0);
            }
            else
            if (ret_index<=6)
            {
                p->SetBackColor(ITEM_COLOR(ret_index+BLUE),1);
                p->SetTextColor(ITEM_COLOR(ret_index+RED ),1);
            }
            else
            {
                p->SetBackColor(ITEM_COLOR((ret_index+BLUE)&0xF),2);
                p->SetTextColor(ITEM_COLOR((ret_index+RED )&0xF),2);
            }
            // end: only for TEST
  
5、替换如下所示的代码:
  DEF_BACKGROUND替换成::GetSysColor(COLOR_WINDOW);
  DEF_TEXT替换成::GetSysColor(COLOR_WINDOWTEXT);
  GetColorRef(DEF_DESELTEXT)替换成::GetSysColor(COLOR_HIGHLIGHTTEXT);
  GetColorRef(DEF_SELBACKGROUND)替换成::GetSysColor(COLOR_ACTIVECAPTION);
  GetColorRef(DEF_SELTEXT)替换成::GetSysColor(COLOR_HIGHLIGHTTEXT);
  GetColorRef(DEF_DESELBACKGROUND)替换成::GetSysColor(COLOR_INACTIVECAPTION);
  pDC->SetTextColor(pMyLParam->GetTextColor(DEF_DESELTEXT))替换成pDC->SetTextColor(pMyLParam->GetTextColor(5));  
  修改后的示例程序如下图所示,基本功能与原来的程序一样。



  本来我还计划把对CListCtrl类的排序功能加入其中,可是到实现的时候才发现异常复杂,因为在CListCtrl控件的“More Style”属性中已选中“Owner draw fixed”选项,对CListCtrl控件颜色的修改实际上是通过自画来实现的,导致了CListCtrl控件某些函数的不可使用,例如InsertItem()等等,我尝试做了一下排序,总是会出现一些无法理解的错误,照我的理解只能把项全部存进列表中,然后对列表进行排序,再清空CListCtrl控件的所有项罗列出已排序的项。如果哪位高手有独到的解决方法,请不吝指教!


--------------------next---------------------

没解决标头拖动后的问题 ( T爱佳T 发表于 2007-11-26 9:02:00)
 
排序问题其实比较容易,只需要使用CListCtrl::SortItems就可以很好的实现,不过lParam必须预先定义好与排序相关的数据结构指针 ( jetricy 发表于 2006-9-7 10:36:00)
 
使用Custom Draw技术而已 ( zyl910 发表于 2005-7-10 17:24:00)
 
感觉ListCtrl怎么改,用起来都不太顺手 ( tmman 发表于 2005-6-9 22:34:00)
 
总要写出原文的出处吧!


这个东东,不错,我刚参加工作就是用了这个东东!
很怀念! ( bm1408 发表于 2005-6-9 15:53:00)
 
你可以参考一下知识库中关于CListCtrl的文章,已经有人做过类似您的工作,也实现了排序功能。 ( sflash2000 发表于 2005-6-8 8:56:00)
 
.......................................................

--------------------next---------------------

阅读(384) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~