Duilib 源码分析之控件 name 篇

来源:互联网 发布:js浏览器兼容 编辑:程序博客网 时间:2024/06/07 03:47

今天来介绍一下 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
  • 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 个元素则返回,虽然不知道为什么这么写查询顺序,但是对于遍历来说,顺序从前往后还是从后往前倒是没有区别。

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

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

原创粉丝点击