Duilib 源码分析之控件 name 篇

今天来介绍一下 Duilib 中控件的 name 的保存及查询方法吧,使用 Duilib 的过程中,大家最常使用的一个功能可能就是 FindControl(LPCTSTR pstrName) 了吧,我们来看一下到底是怎么进行 Find 的。

先上源码:

CControlUI* CPaintManagerUI::FindControl(LPCTSTR pstrName) const
{
    ASSERT(m_pRoot);
    return static_cast<CControlUI*>(m_mNameHash.Find(pstrName));
}
struct TITEM
{
    CDuiString Key;
    LPVOID Data;
    struct TITEM* pPrev;
    struct TITEM* pNext;
};
class DUILIB_API CDuiStringPtrMap
    {
    public:
        CDuiStringPtrMap(int nSize = 83);
        ~CDuiStringPtrMap();

        void Resize(int nSize = 83);
        LPVOID Find(LPCTSTR key, bool optimize = true) const;
        bool Insert(LPCTSTR key, LPVOID pData);
        LPVOID Set(LPCTSTR key, LPVOID pData);
        bool Remove(LPCTSTR key);
        void RemoveAll();
        int GetSize() const;
        LPCTSTR GetAt(int iIndex) const;
        LPCTSTR operator[] (int nIndex) const;

    protected:
        TITEM** m_aT;
        int m_nBuckets;
        int m_nCount;
    };

从以上代码可以看出,最重要的部分在于类 CDuiStringPtrMap,这个类使用的场合很多,例如前面介绍过的字体的存储,此篇控件名称的存储,凡是可以以字符串为 key 值的都可以使用这个类。

  • TITEM** m_aT 数组地址,指向一个数组元素类型为 TITEM* 的数组,同时,每一个元素又是一个链表头
  • int m_nBuckets 数组预设大小
  • int m_nCount 数组中实际存放的元素个数
  • void Resize(int nSize = 83) 清空所有元素,删除数组,并重新创建数组
  • LPVOID Find(LPCTSTR key, bool optimize = true) const 根据 key 值找对应的对象,参数 optimize 代表找到此对象后是否要将此对象放在链表头部
  • bool Insert(LPCTSTR key, LPVOID pData) 插入一条数据,若已存在相同 Key 则跳过
  • LPVOID Set(LPCTSTR key, LPVOID pData) 已存在相同 Key 的场合,覆盖旧值,否则调用 Insert。 所以对于控件的名称尽量不要重复。若重复的话第二个以后的 name 只能通过 FindSubControlByName 找到
  • bool Remove(LPCTSTR key) 删除指定 Key 值数据
  • void RemoveAll() 删除所有已保存元素
  • int GetSize() const 返回已保存元素个数,也就是 m_nCount
  • LPCTSTR GetAt(int iIndex) const 获取第 iIndex 个元素,这个我们得稍微看一下,源码如下:

    int pos = 0;
    int len = m_nBuckets;
    while( len-- )
    {
    for( TITEM* pItem = m_aT[len]; pItem; pItem = pItem->pNext )
    {
      if( pos++ == iIndex )
      {
        return pItem->Key.GetData();
      }
    }
    }

    我们可以看到这个查找顺序是按数组从后往前的顺序查的,并按链表从前向后查,查到第 iIndex 个元素则返回,虽然不知道为什么这么写查询顺序,但是对于遍历来说,顺序从前往后还是从后往前倒是没有区别 (若单纯取第 n 个元素做某操作是有区别的,但目前 duilib 中所有的 CDuiStringPtrMap 类型的对象都只存在从头到尾的遍历,所以遍历顺序就没有关系了)。

  • LPCTSTR operator[] (int nIndex) const 操作符重载函数,作用和 GetAt 一样

这个类本身的使用比较简单,但其中比较重要的一点是存储时所采用的结构,数据结构是一个数组,每个数组的元素又是一个列表的表头。在插入一个元素的时候有一个函数 —— UINT HashKey(LPCTSTR Key), 一个哈希函数,所以这也就是一个以拉链法解决冲突的一个实例。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值