使用mfc CWnd 自绘实现一个类似于QQ好友的一个控件
使用CWnd自绘控件其实挺简单的,可以从CWnd派生一个自己命名的类,
响应鼠标移动,鼠标按下事件,在这些响应的事件中,使用双缓存的方式重绘控件的DC;
界面就可以根据用户的操作做出对应的修改。基本原理就是如此。点击打开链接
以QQ的好友管理控件为例,源代码下载地址:http://download.csdn.net/download/weiweiloong/4991943
需要绘制的信息保存在一个std::list中,包含要绘制节点的,图片,坐标值,文字信息等;
用户每次操作后,修改list中缓存的节点值,然后根据这些节点值重新计算修改节点信息值。接着通知界面重绘。
具体请参考源码:
#pragma once
#include <map>
#include <list>
#include <string>
#include <atlimage.h>
using namespace std;
// CCatalogCtrl
/*********************** 好友分组管理 *********************/
// 成员节点
typedef struct _MemberNode
{
int iIndex;
int iParentIndex; // 所属目录编号
string strName;
string strDeclaration; // 好友个性宣言
// 好友信息窗口
// 好友聊天窗口
bool bOnline; // 好友是否在线
bool bSelect; // 节点被选中(高亮)
bool bPress; // 节点被按下(是否放大显示)
CImage imgMemberPic; // 成员头像
int iItemHeight;
int iItemWidth;
int iUserState; // 用户状态
CPoint iItemPos; // 元素位置
CPoint iImgPos; // 头像位置
CPoint iNamePos; // 用户名位置
CPoint iDeclarationPos; // 个性宣言位置
}MemberNode;
// 分组节点
typedef struct _GroupNode
{
int iIndex;
int iMemNum; // 好友人数
int iOnlineNum; // 好友在线人数
string strGroupName; // 分组名称
bool bGroupState; // 分组状态(展开/合并)
CPoint iItemPos; // 元素位置
CPoint iImgPos; // 图片位置
CPoint iInfoPos; // 信息位置
list<MemberNode*> lstMember; // 小组成员
~_GroupNode()
{
// 清空成员链表
list<MemberNode*>::iterator iPos, iEnd;
iEnd = lstMember.end();
for( iPos = lstMember.begin(); iPos != iEnd; iPos++)
{
delete(*iPos);
}
lstMember.clear();
}
}GroupNode;
class CScrollHelper;
// 好友列表控件
class CCatalogCtrl : public CWnd
{
DECLARE_DYNAMIC(CCatalogCtrl)
public:
CCatalogCtrl( CWnd *parentWnd);
virtual ~CCatalogCtrl();
protected:
DECLARE_MESSAGE_MAP()
private:
CPen m_PenItemFrame; // 节点框架
CBrush m_BrushItemRect; // 节点被选中填充画刷
CBrush m_BrushItemMove; // 鼠标移动过程元素的颜色
CDC m_TempDC; // 记录要绘图的部分DC内容1
CFont m_TextFont; // 桌面文字字体
CImage m_imgGroupOpen; // 分组展开图标
CImage m_imgGroupClose; // 分组合并图标
int m_iChildHeight; // 分组高度
int m_iChildWidth; // 分组宽度
int m_iCtrlHeight; // 控件高度
int m_iCtrlWidth; // 控件宽度
CPoint m_CtrlPos; // 控件绘制相对位置
int m_iAllItemsNum; // 控件所有节点个数
private:
list<GroupNode*> m_lstGroup; // 分组信息
CScrollHelper *m_pScrollHelper; // 滚动条类
private:
int ClearGroupLst(); // 清空分组链表
int ClearMemberLst(); // 清空成员链表
int CurrPosAttribute( CPoint pos); // 当前点击位置是分组、节点、空白
int InitCtrl(); // 初始化当前控件
int ProcessDrawInfo( CDC &TempDC); // 初始化绘制信息
void DrawScrollInfo( CDC &TempDC); // 绘制滚动条改变后的窗口视图
int ReCaculateItemsPos( CDC &TempDC); // 某个节点元素改变后,重新调整所有节点位置
public:
bool InsertNewGroup( int iIndex, string strName); // 插入一个分组
bool ModifyGroupName( int iIndex, string strName); // 修改一个分组名称
bool DelCurrGroup( int iIndex); // 删除一个分组
bool InsertNewItem( int iGroupIndex, MemberNode *pMemInfo); // 插入一个好友
bool DelCurrItem( int iMumIndex); // 删除一个好友
bool MoveItem( int iItemIndex, int iSrcGroup, int iDeskGroup); // 将一个好友从一个分组移动到另外一个分组
private: