duilib 自帶樹形控件的認識


CTreeViewUI

1、該控件繼承自CListUI,所以是使用了對應的列表來模擬樹形控件。該控件的容器填裝的是CTreeNodeUI,而CTreeNodeUI也繼承CListContainerElementUI,所以樹形控件剝掉外殼其實就是CListUI,然后子列表是CListContainerElementUI。

2、a.每個屬性控件包含的節點:擴展按鈕點前面的空格、擴展按鈕、checkbox按鈕、空格 再加上 后面的用戶自添元素。所有元素加起來的寬度是250,也就是說如果該樹形控件比較大的話就會出現太窄而無法容下所有元素的現象。所以這里可以根據自身的需要進行相應的調整。如代碼UITreeView.cpp的第32行:this->SetFixedWidth(250);

b.樹形控件的每個節點的擴展按鈕前面的空白如何計算呢?如代碼的UITreeView.cpp的第48行:pDottedLine->SetFixedWidth(_ParentNode->GetDottedLine()->GetFixedWidth()+16); 通過獲取父節點的寬度再加上16。如果父節點是空則使用默認的2.雖然這里有默認的了,但是在添加childnode的時候會更新空白寬度調用CalLocation

3、節點相關屬性的設置則可以看對應的void CTreeNodeUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue )函數的設置。再根據我第二點的描述則可以簡單應用。

 

4、關於樹形控件子樹的打開跟關閉。這里使用的是剛開始的時候默認全部是打開的。是因為每個控件默認是全部打開的。雖然是打開的,但是每個擴展按鈕默認都是check=false,所以在放圖片的時候注意這個foldattr屬性normalimage跟selectedimage。

如果在程序開始運行的時候不想讓每個控件都打開,只想讓部分控件打開則需要修改樹形控件的程序。修改的位置是在bool CTreeNodeUI::Add( CControlUI* _pTreeNodeUI ),該函數是在UIDlgBuilder進行解析xml函數的時候直接調用的函數。這里我嘗試將selected="true" 進行設置發現只是圖標修改了而子樹還顯示着。

所以這里我在Add函數調用的CTreeNodeUI::AddChildNode的第370行添加了

// 這里使用 !this->IsVisible()是如果本父節點是非可見了那么它對應的子樹也應該是不可見的。

if (pFolderButton->IsSelected() || !this->IsVisible())
SetItemExpand(this);

並寫了SetItemExpand函數,該函數我是抄襲對應的CTreeViewUI的SetItemExpand

    void CTreeNodeUI::SetItemExpand( CTreeNodeUI* _TreeNode )
    {
        if(_TreeNode)
        {
            if(_TreeNode->GetCountChild() > 0)
            {
                int nCount = _TreeNode->GetCountChild();
                for(int nIndex = 0;nIndex < nCount;nIndex++)
                {
                    CTreeNodeUI* pItem = _TreeNode->GetChildNode(nIndex);
                    pItem->SetVisible(false);

                    if(pItem->GetCountChild() && !pItem->GetFolderButton()->IsSelected())
                        SetItemExpand(pItem);
                }
            }
        }
    }
View Code

這樣,當設置了selected="true"的時候,則相應的子樹均為不可見狀態。

5、對應的按鈕響應函數:其實在TreeViewUI的Add函數中已經都有對應的顯示了。

bool CTreeViewUI::Add( CTreeNodeUI* pControl )

long CTreeViewUI::AddAt( CTreeNodeUI* pControl, int iIndex )

均已經做了相應的操作。

但是我們經常做這樣子的操作:雙擊樹形控件checkbox右邊的空白區域然后打開的子樹則會相應的關閉,或者關閉的子樹則會相應的打開。(即修改對應的foldattr的selected參數的值)。

在這里我們這樣子卻做不了。即使像

本身add里面那樣子操作

pControl->OnNotify += MakeDelegate(this,&CTreeViewUI::OnDBClickItem);
pControl->GetFolderButton()->OnNotify += MakeDelegate(this,&CTreeViewUI::OnFolderChanged);
pControl->GetCheckBox()->OnNotify += MakeDelegate(this,&CTreeViewUI::OnCheckBoxChanged);

也是沒辦法獲取到。究其原因得看本身的空白處到底是什么: COptionUI();

而看其對應的父控件的CbuttonUI則可以知其一二,里面的onevent對應的

if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK )
        {
            if( ::PtInRect(&m_rcItem, event.ptMouse) && IsEnabled() ) {
                m_uButtonState |= UISTATE_PUSHED | UISTATE_CAPTURED;
                Invalidate();
            }
            return;
        }
View Code

只是做了相應的圖像更新操作,而沒有發送對應的onnotify double click操作。那如果在button里面添加該操作呢?但是事實證明在onevent根本捕捉不到對應的dbclick,因為按鈕是不支持雙擊的。

那到底啥原因呢? 

后來我發現在注冊windowclass的時候

WNDCLASS wc = { 0 };
wc.style = GetClassStyle();

該GetClassStyle是虛函數,可以通過繼承該函數添加相應的style來實現雙擊的效果。

UINT GetClassStyle() const
{
return CS_DBLCLKS;
};

如果需要使用自己量身定制的樹形控件,可以看對應的duilib官方給的demo中的GameDemo。(即自繪樹形控件)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM