首页
社区
课程
招聘
[分享]界面-一个列表框
发表于: 2010-10-30 09:11 5582

[分享]界面-一个列表框

2010-10-30 09:11
5582
之前计划写一个界面库,这个列表花了一个星期的空余时间,虽然没像名字那么Super,希望有兴趣的可以继续完善之。
下面是当时设计时的一些思路。
1 ITEM类型
CYasSuperList 中把ITEM分为3类:

#define LISTITEM_NORMAL 0x00
#define LISTITEM_COMBINE 0x01
#define LISTITEM_VIRTUAL 0x02

1)LISTITEM_NORMAL: 是可见的,而且可以拥有 LISTITEM_COMBINE 和 LISTITEM_VIRTUAL类型的ITEM作为子ITEM
LISTITEM_NORMAL一般通过InsertItem来生成。

2)LISTITEM_COMBINE:引入这中ITEM的原因是为了实现列表中不同ITEM可以有不同的高度。LISTITEM_COMBINE类型的ITEM又可以分为

俩类,第一类是主联合ITEM,另外一类是子联合ITEM。一般主联合ITEM就是LISTITEM_COMBINE的第一个LISTITEM_NORMAL类型的ITEM。
主联合ITEM 有数据用于描述该ITEM上控件的分布,而子联合ITEM的作用仅仅是提供空间来给 LISTITEM_COMBINE绘画控件。

3)LISTITEM_VIRTUAL:引入这中ITEM是为了扩展LISTITEM_NORMAL类型ITEM的功能,使其具有下拉的功能
一般LISTITEM_VIRTUAL不可见,也就是一段数据的描述,LISTITEM_NORMAL可以根据时机创建这些ITEM。

三种ITEM的描述的数据结构是:

typedef struct tagClistItemData
{
  //
  //用于标示 Combine Item
  //
  UINT uItemType;
  UINT uItemOsToMainItem; // 如果LISTITEM_COMBINE == uItemType,且 bIsMainItem == 0 
                          // 那这个用于确定主联合ITEM的号是,
                          // 主联合ITEM号 = 本ITEM号 - uItemOsToMainItem; 
  BOOL bIsMainItem; // 如果LISTITEM_COMBINE == uItemType, 那标示这个ITEM是不是主联合ITEM

  BOOL bCanExpand; //是否展开,FOR REAL ITEM ONLY
  //
  //Virtual Item 有效
  //
  
  struct tagClistItemData *pNext;
  struct tagClistItemData* ChildClistItemDataList; //NULL表示没有虚拟ITEM
  int nChildItemNum;

  //
  //COMMOM DATA
  //

  CPictureEx *p_gif;
  POINT gif_pos;
  int gif_nsubItem;

  BOOL bNeedDrawItem; //
  BOOL bNeedItemFill;//选择或者鼠标移过是否允许填充背景色
  pSubItemInfo __pSubItemInfo[10];

  BOOL bItemBottomLine; //是否画底部线
  BOOL bItemCheck; // 一个ITEM只允许以个主要的CHECK BOX
  PVOID pdata;// 文字数据之类,不会被绘画

}ClistItemData, *pClistItemData;
相关接口是
int CListNewItem(int nItem, BOOL bEnableTopLine);
int CListNewItem(int nItem, BOOL bNeedDraw, BOOL bNeedItemFill, BOOL bEnableTopLine);
int CListNewCombineItem(int nItem, BOOL bNeedDraw, BOOL bNeedItemFill, BOOL bEnableTopLine);
BOOL CListNewVirtualItem(int nParentItem, int nChildItem, BOOL bNeedDraw, 
             BOOL bNeedItemFill, BOOL bEnableTopLine);

2 控件分布的管理:
CYasSuperList 的控件是基于SubItem的,也就是每个SubItem都有相关数据来描述控件的信息。相关数据结构为
typedef struct tagSubItemInfo
{
  int iSubItem; //iSubItem号
  COLORREF bkCol; 
  CtrlNodeInfo *pSubItemCtrlList; //本iSubItem的控件描述列表。
  
}SubItemInfo, *pSubItemInfo;

typedef struct tagCtrlNodeInfo
{
  struct tagCtrlNodeInfo *pNext;
  int nCtrlType; //控件的类型,是 按钮,进度条,还是其他...
  RECT hitrc; //控件的坐在位置,这个CYasSuperList用来响应相关的消息,比如是否点中这个控件,或者鼠标移到这控件。
  pLGCallBack pfnCallBack; //控件的响应函数,一般是用于注册的。
  int MouseState; //本控件的鼠标状态,是离开了,还是处于HOVER状态。
  PVOID pData; //详细的描述了控件的信息。
}CtrlNodeInfo, *pCtrlNodeInfo;

因为不同控件需要的描述的信息不一样,所在tagCtrlNodeInfo的字段PVOID pData;的意义就是用于描述具体的控件。
比如它可能指向下面这么一个结构:
typedef struct tagCheckBoxData
{
  POINT pos;
  int nCtrlId;
  RECT hitrc;
  pLGCallBack pfnCallBack;
  HCURSOR hMoveCursor;
  BOOL bCheck;
  int nLen;
  
}CheckBoxData, *pCheckBoxData;

3 控件的添加:
目前CYasSuperList 支持的控件类型有
位图, 按钮, Checkbox, 直线, 文字, 图标, 进度条 和 动态的GIF图片。
相关接口有:
LISTITEM_NORMAL 系列的有:
  int  CListAddCtrl_Button(int iItem, int iSubItem, POINT &pos, int len, 
                         int hei, int iState, COLORREF bkColor, BOOL bFr, 
                 pLGCallBack pfnCallBack);
  int  CListAddCtrl_Button(int iItem, int iSubItem, POINT &pos, int len, 
                         int hei, int iState, COLORREF bkColor, BOOL bFr, 
                         CFont *ptextfont,  LPSTR pszText, COLORREF bkTextColor,
                 pLGCallBack pfnCallBack);

  int CListAddCtrl_CheckBox(int iItem, int iSubItem, POINT &pos,  BOOL bCheck, 
                   int nLen, pLGCallBack pfnCallBack);
  int CListAddCtrl_Progress(int iItem, int iSubItem, POINT &pos, int len, int hei, 
                  int percent, COLORREF col, int index_type, pLGCallBack 

pfnCallBack);
  int CListAddCtrl_Bitmap(int iItem, int iSubItem, POINT &pos, 
              int nBitmapId,pLGCallBack pfnCallBack);
  int CListAddCtrl_Text(int iItem, int iSubItem, POINT &pos, CFont *pfont, 
                  LPSTR psztext, COLORREF TextColor, int 

state, BOOL bxButonText,
                  pLGCallBack pfnCallBack);
  int CListAddCtrl_Icon(int iItem, int iSubItem, POINT &pos,  
                  PVOID pdata, int type_index, pLGCallBack 

pfnCallBack);

LISTITEM_VIRTUAL 系列的有:
  BOOL CListNewVirtualItem(int nParentItem, int nChildItem, BOOL bNeedDraw, 
                         BOOL bNeedItemFill, BOOL bEnableTopLine);

  int CListAddVirtualCtrl_Text(int iParentItem, int iItem, int iSubItem, POINT &pos, 
                             CFont *pfont, LPSTR psztext, COLORREF TextColor, int state, 
                   BOOL bxButonText,pLGCallBack pfnCallBack);
  int CListAddVirtualCtrl_Bitmap(int iParentItem, int nChildItem, int iSubItem, POINT &pos, 
                   int nBitmapId,pLGCallBack pfnCallBack);
  int CListAddVirtualCtrl_CheckBox(int iParentItem, int nChildItem, int iSubItem, POINT &pos, 
                   BOOL bCheck, int nLen, pLGCallBack 

pfnCallBack);
  int CListAddVirtualCtrl_Progress(int iParentItem, int nChildItem, int iSubItem, POINT &pos, int len, int 

hei, 
                                 int percent, COLORREF col, int index_type, pLGCallBack pfnCallBack);
  int CListAddVirtualCtrl_Icon(int iParentItem, int nChildItem, int iSubItem, POINT &pos,  
                 PVOID pdata, int type_index, pLGCallBack 

pfnCallBack);
  int CListAddVirtualCtrl_Button(int iParentItem, int nChildItem, int iSubItem,POINT &pos, 
                               int len, int hei, int iState, COLORREF bkColor, BOOL bFr, 
                               CFont *ptextfont,  LPSTR pszText, COLORREF bkTextColor,
                  pLGCallBack pfnCallBack);
  int CListAddVirtualCtrl_Button(int iParentItem, int nChildItem, int iSubItem, POINT &pos, int len, 
                               int hei, int iState, COLORREF bkColor, BOOL bFr, 
                   pLGCallBack pfnCallBack);

4 控件的绘画:
难于描述,,,直接上图,绘画的代码为了方便扩展和管理,我把他放在一个全局文件里
GDrawManger.cpp,这里提供了各种控件的绘画,控件可以根据自己的需求来画
BOOL  __DrawIcon0( __in CDC *pdc, 
           __in POINT &point, 
           __out RECT &rc, 
           __in int nIconId);
BOOL  __DrawIcon1( __in CDC *pdc, 
           __in POINT &point, 
           __out RECT &rc, 
           __in HICON hIcon );
BOOL  __DrawIcon2( __in CDC *pdc, 
           __in POINT &point, 
           __out RECT &rc, 
           __in LPCTSTR lpIconPath );
BOOL  __DrawIcon3( __in CDC *pdc, 
           __in POINT &point, 
           __out RECT &rc, 
           __in LPCTSTR lpszName );

void  __DrawBmp0(CDC *pdc, POINT &Pos, int nBitmapId, RECT &rc);
void __DrawButton(__in CDC *pdc, __in POINT &point, __in __out RECT &rc, 
          __in int len, __in int hei, __in BOOL bFr, __in COLORREF col, __in int nState);
void __DrawButtonEx(__in CDC *pdc, 
          __in POINT &point, 
          __in __out RECT &rc, 
          __in int len, 
          __in int hei, 
          __in BOOL bFr, 
          __in COLORREF col,
          __in int nState, 
          __in CFont *ptextfont, 
          __in LPSTR pszText, 
          __in COLORREF bkTextColor);

void  __DrawProgress1(__in CDC *pdc, __in POINT &point, 
           __in __out RECT &rc, __in int len, __in int hei, __in COLORREF col);

void  __DrawProgress0(__in CDC *pdc, __in POINT &point, __in __out RECT &rc, 
            __in int len, __in int hei, __in int Pos, __in COLORREF col);

void __DrawText(__in CDC *pdc, __in POINT &point, __in __out RECT &rc, 
        __in CFont *pfont, LPSTR psztext, COLORREF TextColor);
void __DrawCheckBox(__in CDC *pdc, __in POINT &point, __out RECT &rc, __in BOOL bCheck, __in int nLen);

5 消息处理。
对于我们绘画的控件,目前支持的消息类型有
#define MSG_NONE 0x00
#define MSG_LBUTTONDOWN 0x01
#define MSG_RBUTTONDOWN 0x02
#define MSG_MOUSEMOVE 0x03
#define MSG_LBUTTONUP 0x04
#define MSG_RBUTTONUP 0x05
基本都是于鼠标相关的。
处理一般就在控件注册的回调里。比如你收到MSG_LBUTTONDOWN,你可以自己控件这时控件应该怎么画,收到MSG_MOUSEMOVE你就可以绘

画控件的状态了。

5局部绘画
虽然双缓冲避免了闪烁,但频繁的绘画还是会引起一些效率问题,有时候只是点击了一个按钮,整个ITEM不一定都要重新绘画,所以只

需要自己绘按钮就可以,这个可以在回调里完成,在绘画的时候,可以禁止进入DrawItem
  if( bCanbeDraw == FALSE) 
  {
    return;
  }

((CYasListCtrl*)pList)->IsNeedDrawItem(FALSE);就可以了。

6
直接看代码。。也不知道怎么说好。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看起来不错的样子。。。。
2010-10-30 10:48
0
雪    币: 384
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
看起来的确不错
2010-10-30 10:51
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
根本不用搞那么复杂,将 ListView 的 LVIR_LABEL 作为母容器(窗口),在其中可以完全建立各种标准的Win32控件。
上传的附件:
2010-11-3 12:28
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
5
最近界面用的Tk感觉很适合自己
2010-11-3 13:59
0
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
6
不知楼主对Combobox的下拉箭头按钮的重绘有没有研究?比如改变这个按钮的颜色。
2010-11-3 14:24
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
7
用QT吧,想怎么绘就怎么绘,而且是开源的。
2010-11-4 09:07
0
游客
登录 | 注册 方可回帖
返回
//