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

本文介绍如何使用MFC中的CWnd类自定义控件,通过响应鼠标事件和双缓存技术,实现类似QQ好友管理的界面效果。包括分组和好友节点的绘制、头像、状态信息等,以及对节点的操作如插入、删除和移动。源代码可供下载参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

使用CWnd自绘控件其实挺简单的,可以从CWnd派生一个自己命名的类,

响应鼠标移动,鼠标按下事件,在这些响应的事件中,使用双缓存的方式重绘控件的DC;

界面就可以根据用户的操作做出对应的修改。基本原理就是如此。点击打开链接

以QQ的好友管理控件为例,源代码下载地址:http://download.youkuaiyun.com/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( CD

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值