关闭

[置顶] 让你的软件界面更漂亮(六) -----仿QQ 主界面 CMyListCtrl

7727人阅读 评论(18) 收藏 举报

                                        让你的软件界面更漂亮(六) 

                                                                              -----仿QQ 主界面 CMyListCtrl

                                                      深圳软客 (song_0962#sina.com)

        QQ软件主界面的ListCtrl 是可以说非常经典了,一个字漂亮! 这个ListCtrl的所包含的信息之丰富,更是让我们这些软件工程师望Q兴叹今天,我将和大家一起来解决这个难题,写一个属于自已的CMyListCtrl 

                                                     

 

 
一、实现MyListCtrl要完成的任务及实现方法作分析
     
  1. MyListCtrl 显示彩色图片头像(在线用户头)
让CMyListCtrl 显示彩色图片作为头像很容易,用CImageList 加载规格相同的图片到其中,然后让CimageList和CMyListCtrl关联就可能实现。往ImageList 添加图片或图标有三种方法,代码如下
 
CimageList m_imageList;
m_imagelist.Create(40, 40, ILC_MASK|ILC_COLOR32, 1, 1);
//添加ID 为IDI_ICON的图标
m_imageList.Add( AfxGetApp()->LoadIcon(IDI_ICON));
 
//从图标文件中加载并添加
HICON hIcon = (HICON)LoadImage(NULL, ".//image//SQQun.ico", IMAGE_ICON, 0, 0,
                                                            LR_LOADFROMFILE)
m_imagelist.Add(hIcon);
 
 
//从位图文件中加载并添加
CBitmap *pBitmap=new CBitmap;
pbitmap ->m_hObject = (HBITMAP) LoadImage(NULL, "face.bmp", IMAGE_BITMAP, 0, 0,
                                                                                 LR_LOADFROMFILE);
m_imagelist.Add(pBitmap, RGB(255,255, 255)/*mask color*/);
….
Delete pBitmap;
 
 
注意;在加载并添加大量图标或位图时,每完成一个添加都要掉其对象。
 
CMyListCtrl CimageList 关联代码介绍:
     //先创建ListCtrl ( m_MyTalkerListCtrl)
if(m_MyTalkerListCtrl.Create(LVS_SMALLICON | WS_TABSTOP|WS_CHILD,
                                                                                                      CRect(50,100,206,180),
                                                                                          this,IDD_TALKER_LIST/*ID*/))
{
//关联
            m_MyTalkerListCtrl.SetImageList(&m_imagelistBig,LVSIL_SMALL);
 
                  //往ListCtrl 中添加好友,这时采用单
                  for(int i=1; i<10; i++)
                  {
                      m_MyTalkerListCtrl.InsertItem(i,"我的好友", i);//第三个参数表示Image 的Index
                  }
}
 
 
 
 
2.要让CMyListCtrl 显示灰色图片头像(非在线用户)
显灰色图片似乎不好办,是做大量的单色位图文件还是用软件代码实现转换?做文件麻烦,或几经考虑,最好是把ImageList 中彩色图片用代码实现单色位图转换。处理方法是
是获取CMyListCtrl的ImageList 并提ListCtrl的Item 对应的图像,转换成单色位图并在原位置显示。转换单色位图代码如下:
 
/*
HBITMAP BitmapColorToGray(CDC* pDC,HBITMAP hBitmap)
{
            BITMAP bmpInfo;
            ::GetObject(hBitmap,sizeof(BITMAP),&bmpInfo);
            if(pDC)
            {
                        CDC memDC;
                        if( !memDC.CreateCompatibleDC(pDC) )
                        {
                                    return NULL;
                        }
                       
                        HBITMAP oldBitmap = (HBITMAP)memDC.SelectObject(hBitmap);
                        DWORD   r,g,b;  
                        for (int H =0; H <= bmpInfo.bmHeight; H++)  
                        {
                                    for(int W = 0; W <= bmpInfo.bmWidth; W ++)  
                                    {  
                                                r = GetRValue(memDC.GetPixel(W,H));  
                                                g = GetGValue(memDC.GetPixel(W,H));  
                                                b = GetBValue(memDC.GetPixel(W,H));  
                                                r = (r * 3 + g * 6 + g) / 10;  
                                                g   =   r;  
                                                b   =   g;  
                                                memDC.SetPixel(CPoint(W,H),RGB(r,g,b));
                                    }
                        }
                        hBitmap = (HBITMAP)memDC.SelectObject(oldBitmap);
                        memDC.DeleteDC();
            }
    return hBitmap;                    
}
*/
 
 
说细转换过请参考 MyListCtrl.cpp 中的OnPaint()函数
 
 
  1. CMyListCtrl 要包含丰富的用户信息(如 ID,NAME 、IP Address 、视频可用 ,手机短消息可用…)
QQ 的ListCtrl 包含了很多信息,如在线用户和不在用户的头象不同,有视频设备用户会显示标志,开通了手机短消息功能的也会显示标志,还有很多不一一例出。这是如何实现的?去MSDN分析CListCtrl 发现,有两个函数SetItemData(int nItem,DWORD dwData),和GetItemData(int nItem),非常有用,这个32位 data 做几个标志还是不错的,但还是无法表达更多的东东。如果把这32位 data作为外部结构的地址是否可行呢?经实验是可行的,但在要外部处理,封装性能不好! 那自己定一个为用户信息结构吧!
在CMyListCtrl类的头文件中定义用户信息结构
struct LUSERITEM
{
            CString                       szUserID;
            CString                       szUserName;
            CString                       szIPAddress;
            CString                       szServerAddress;
            CString                       szNoticeMsg;
            BOOL                         bOnline;
            int                                nHeadImageIndex;
            //根据需要可增加信息
};
 
再定义一个链表,用来管理用户信息的结构,如查找,增加,删除等操作。
typedef std::deque<LUSERITEM>       DEQUELVITEM;
           
 
            此外还有#include <dequ>
4. 当新消息时动画显示头像和新消息数量(在V1.2版本中实现)
  
 
二、打开Visual Studio C++ (6.0),新建工程。(本文的主要任务是完成一个QQ ListCtrl 的,不在本任务下的其它工作请自己完成,若和ListCtrl使用有关的代码,本文会详细介绍)
 
a.       首先,生成一个新类名为CMyListCtrl. 其基类为CListCtrl. 这部分工作用ClassWizard很容易完成。
b.      添加相关消息及处理函数,OnPaint() ;OnMouseMove();OnHScroll();OnVScroll等,这部工作用ClassWizard同样很容易完成。编译通过后,接着往下看。
c.   在.h文件顶部定义结构体struct LUSERITEM ,可参照下面定义
 
                  d. 在.h文件顶部定义一些常量标志
#define  TVS_VIDEO                         0x00000001
#define  TVS_MOBILEMSG              0x00000002
#define  TVS_NETDISK                    0x00000004
#define  TVS_LEADER                      0x00000008
#define  TVS_VICELEADER 0x00000010
#define  TVS_ONLINEUSER            0x00000020
e.添加成员变量 及函数
     CFont* m_pFont;                     //用于创建选择字体
     BOOL m_bOverImage;           
     BOOL m_bOverVedio;           
     BOOL m_bOverMobile;
     DEQUELVITEM m_DequeList; //用户信息链表
     HICON m_hTailIconA;               //vido flag
     HICON m_hTailIconB;                 //mobil message flag
     HICON m_hTailIconC;                       
     HBITMAP m_hBackBitmap;     //背景
 
f. .添加成员函数
 
                  重载InsertItem函数,用于增加Item同时增加用户信息。
                        InsertItem(int nItem, LPCTSTR szItemText, int nImageIndex, LUSERITEM* UserInfo)
{
                                    DEQUELVITEM* pDeqListItem = &m_DequeList;
                        if(UserInfo)
                                                pDeqListItem ->push_back(*UserInfo);
            nItem = CListCtrl::InsertItem%2
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:70913次
    • 积分:1022
    • 等级:
    • 排名:千里之外
    • 原创:23篇
    • 转载:0篇
    • 译文:0篇
    • 评论:80条
    最新评论