使用mfc CWnd 自绘实现一个类似于QQ好友的一个控件

使用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:

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值