DuiLib 之 UIList

来源:互联网 发布:les交友软件 编辑:程序博客网 时间:2024/06/08 01:48
#ifndef __UILIST_H__#define __UILIST_H__#pragma once#include "Layout/UIVerticalLayout.h"#include "Layout/UIHorizontalLayout.h"namespace DuiLib {///////////////////////////////////////////////////////////////////////////////////////class CListHeaderUI;#define UILIST_MAX_COLUMNS 32typedef struct tagTListInfoUI{    int nColumns;    RECT rcColumn[UILIST_MAX_COLUMNS];    int nFont;    UINT uTextStyle;    RECT rcTextPadding;    DWORD dwTextColor;    DWORD dwBkColor;    CDuiString sBkImage;    bool bAlternateBk;    DWORD dwSelectedTextColor;    DWORD dwSelectedBkColor;    CDuiString sSelectedImage;    DWORD dwHotTextColor;    DWORD dwHotBkColor;    CDuiString sHotImage;    DWORD dwDisabledTextColor;    DWORD dwDisabledBkColor;    CDuiString sDisabledImage;    DWORD dwLineColor;    bool bShowHtml;    bool bMultiExpandable;} TListInfoUI;///////////////////////////////////////////////////////////////////////////////////////class IListCallbackUI{public:    virtual LPCTSTR GetItemText(CControlUI* pList, int iItem, int iSubItem) = 0;};class IListOwnerUI{public:    virtual TListInfoUI* GetListInfo() = 0;    virtual int GetCurSel() const = 0;    virtual bool SelectItem(int iIndex, bool bTakeFocus = false) = 0;    virtual void DoEvent(TEventUI& event) = 0;};class IListUI : public IListOwnerUI{public:    virtual CListHeaderUI* GetHeader() const = 0;    virtual CContainerUI* GetList() const = 0;    virtual IListCallbackUI* GetTextCallback() const = 0;    virtual void SetTextCallback(IListCallbackUI* pCallback) = 0;    virtual bool ExpandItem(int iIndex, bool bExpand = true) = 0;    virtual int GetExpandedItem() const = 0;};class IListItemUI{public:    virtual int GetIndex() const = 0;    virtual void SetIndex(int iIndex) = 0;    virtual IListOwnerUI* GetOwner() = 0;    virtual void SetOwner(CControlUI* pOwner) = 0;    virtual bool IsSelected() const = 0;    virtual bool Select(bool bSelect = true) = 0;    virtual bool IsExpanded() const = 0;    virtual bool Expand(bool bExpand = true) = 0;    virtual void DrawItemText(HDC hDC, const RECT& rcItem) = 0;};///////////////////////////////////////////////////////////////////////////////////////class CListBodyUI;class CListHeaderUI;class UILIB_API CListUI : public CVerticalLayoutUI, public IListUI{public:    CListUI();    LPCTSTR GetClass() const;    UINT GetControlFlags() const;    LPVOID GetInterface(LPCTSTR pstrName);    bool GetScrollSelect();    void SetScrollSelect(bool bScrollSelect);    int GetCurSel() const;    bool SelectItem(int iIndex, bool bTakeFocus = false);    CListHeaderUI* GetHeader() const;      CContainerUI* GetList() const;    TListInfoUI* GetListInfo();    CControlUI* GetItemAt(int iIndex) const;    int GetItemIndex(CControlUI* pControl) const;    bool SetItemIndex(CControlUI* pControl, int iIndex);    int GetCount() const;    bool Add(CControlUI* pControl);    bool AddAt(CControlUI* pControl, int iIndex);    bool Remove(CControlUI* pControl);    bool RemoveAt(int iIndex);    void RemoveAll();    void EnsureVisible(int iIndex);    void Scroll(int dx, int dy);    int GetChildPadding() const;    void SetChildPadding(int iPadding);    void SetItemFont(int index);    void SetItemTextStyle(UINT uStyle);    void SetItemTextPadding(RECT rc);    void SetItemTextColor(DWORD dwTextColor);    void SetItemBkColor(DWORD dwBkColor);    void SetItemBkImage(LPCTSTR pStrImage);    void SetAlternateBk(bool bAlternateBk);    void SetSelectedItemTextColor(DWORD dwTextColor);    void SetSelectedItemBkColor(DWORD dwBkColor);    void SetSelectedItemImage(LPCTSTR pStrImage);     void SetHotItemTextColor(DWORD dwTextColor);    void SetHotItemBkColor(DWORD dwBkColor);    void SetHotItemImage(LPCTSTR pStrImage);    void SetDisabledItemTextColor(DWORD dwTextColor);    void SetDisabledItemBkColor(DWORD dwBkColor);    void SetDisabledItemImage(LPCTSTR pStrImage);    void SetItemLineColor(DWORD dwLineColor);    bool IsItemShowHtml();    void SetItemShowHtml(bool bShowHtml = true);RECT GetItemTextPadding() const;DWORD GetItemTextColor() const;DWORD GetItemBkColor() const;LPCTSTR GetItemBkImage() const;    bool IsAlternateBk() const;DWORD GetSelectedItemTextColor() const;DWORD GetSelectedItemBkColor() const;LPCTSTR GetSelectedItemImage() const;DWORD GetHotItemTextColor() const;DWORD GetHotItemBkColor() const;LPCTSTR GetHotItemImage() const;DWORD GetDisabledItemTextColor() const;DWORD GetDisabledItemBkColor() const;LPCTSTR GetDisabledItemImage() const;DWORD GetItemLineColor() const;    void SetMultiExpanding(bool bMultiExpandable);     int GetExpandedItem() const;    bool ExpandItem(int iIndex, bool bExpand = true);    void SetPos(RECT rc);    void DoEvent(TEventUI& event);    void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);    IListCallbackUI* GetTextCallback() const;    void SetTextCallback(IListCallbackUI* pCallback);    SIZE GetScrollPos() const;    SIZE GetScrollRange() const;    void SetScrollPos(SIZE szPos);    void LineUp();    void LineDown();    void PageUp();    void PageDown();    void HomeUp();    void EndDown();    void LineLeft();    void LineRight();    void PageLeft();    void PageRight();    void HomeLeft();    void EndRight();    void EnableScrollBar(bool bEnableVertical = true, bool bEnableHorizontal = false);    virtual CScrollBarUI* GetVerticalScrollBar() const;    virtual CScrollBarUI* GetHorizontalScrollBar() const;protected:    bool m_bScrollSelect;    int m_iCurSel;    int m_iExpandedItem;    IListCallbackUI* m_pCallback;    CListBodyUI* m_pList;    CListHeaderUI* m_pHeader;    TListInfoUI m_ListInfo;};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListBodyUI : public CVerticalLayoutUI{public:    CListBodyUI(CListUI* pOwner);    void SetScrollPos(SIZE szPos);    void SetPos(RECT rc);    void DoEvent(TEventUI& event);protected:    CListUI* m_pOwner;};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListHeaderUI : public CHorizontalLayoutUI{public:    CListHeaderUI();    LPCTSTR GetClass() const;    LPVOID GetInterface(LPCTSTR pstrName);    SIZE EstimateSize(SIZE szAvailable);};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListHeaderItemUI : public CControlUI{public:    CListHeaderItemUI();    LPCTSTR GetClass() const;    LPVOID GetInterface(LPCTSTR pstrName);    UINT GetControlFlags() const;    void SetEnabled(bool bEnable = true);bool IsDragable() const;    void SetDragable(bool bDragable);DWORD GetSepWidth() const;    void SetSepWidth(int iWidth);DWORD GetTextStyle() const;    void SetTextStyle(UINT uStyle);DWORD GetTextColor() const;    void SetTextColor(DWORD dwTextColor);void SetTextPadding(RECT rc);RECT GetTextPadding() const;    void SetFont(int index);    bool IsShowHtml();    void SetShowHtml(bool bShowHtml = true);    LPCTSTR GetNormalImage() const;    void SetNormalImage(LPCTSTR pStrImage);    LPCTSTR GetHotImage() const;    void SetHotImage(LPCTSTR pStrImage);    LPCTSTR GetPushedImage() const;    void SetPushedImage(LPCTSTR pStrImage);    LPCTSTR GetFocusedImage() const;    void SetFocusedImage(LPCTSTR pStrImage);    LPCTSTR GetSepImage() const;    void SetSepImage(LPCTSTR pStrImage);    void DoEvent(TEventUI& event);    SIZE EstimateSize(SIZE szAvailable);    void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);    RECT GetThumbRect() const;    void PaintText(HDC hDC);    void PaintStatusImage(HDC hDC);protected:    POINT ptLastMouse;    bool m_bDragable;    UINT m_uButtonState;    int m_iSepWidth;    DWORD m_dwTextColor;    int m_iFont;    UINT m_uTextStyle;    bool m_bShowHtml;RECT m_rcTextPadding;    CDuiString m_sNormalImage;    CDuiString m_sHotImage;    CDuiString m_sPushedImage;    CDuiString m_sFocusedImage;    CDuiString m_sSepImage;    CDuiString m_sSepImageModify;};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListElementUI : public CControlUI, public IListItemUI{public:    CListElementUI();    LPCTSTR GetClass() const;    UINT GetControlFlags() const;    LPVOID GetInterface(LPCTSTR pstrName);    void SetEnabled(bool bEnable = true);    int GetIndex() const;    void SetIndex(int iIndex);    IListOwnerUI* GetOwner();    void SetOwner(CControlUI* pOwner);    void SetVisible(bool bVisible = true);    bool IsSelected() const;    bool Select(bool bSelect = true);    bool IsExpanded() const;    bool Expand(bool bExpand = true);    void Invalidate(); // 直接CControl::Invalidate会导致滚动条刷新,重写减少刷新区域    bool Activate();    void DoEvent(TEventUI& event);    void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);    void DrawItemBk(HDC hDC, const RECT& rcItem);protected:    int m_iIndex;    bool m_bSelected;    UINT m_uButtonState;    IListOwnerUI* m_pOwner;};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListLabelElementUI : public CListElementUI{public:    CListLabelElementUI();    LPCTSTR GetClass() const;    LPVOID GetInterface(LPCTSTR pstrName);    void DoEvent(TEventUI& event);    SIZE EstimateSize(SIZE szAvailable);    void DoPaint(HDC hDC, const RECT& rcPaint);    void DrawItemText(HDC hDC, const RECT& rcItem);};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListTextElementUI : public CListLabelElementUI{public:    CListTextElementUI();    ~CListTextElementUI();    LPCTSTR GetClass() const;    LPVOID GetInterface(LPCTSTR pstrName);    UINT GetControlFlags() const;    LPCTSTR GetText(int iIndex) const;    void SetText(int iIndex, LPCTSTR pstrText);    void SetOwner(CControlUI* pOwner);    CDuiString* GetLinkContent(int iIndex);    void DoEvent(TEventUI& event);    SIZE EstimateSize(SIZE szAvailable);    void DrawItemText(HDC hDC, const RECT& rcItem);protected:    enum { MAX_LINK = 8 };    int m_nLinks;    RECT m_rcLinks[MAX_LINK];    CDuiString m_sLinks[MAX_LINK];    int m_nHoverLink;    IListUI* m_pOwner;    CStdPtrArray m_aTexts;};///////////////////////////////////////////////////////////////////////////////////////class UILIB_API CListContainerElementUI : public CContainerUI, public IListItemUI{public:    CListContainerElementUI();    LPCTSTR GetClass() const;    UINT GetControlFlags() const;    LPVOID GetInterface(LPCTSTR pstrName);    int GetIndex() const;    void SetIndex(int iIndex);    IListOwnerUI* GetOwner();    void SetOwner(CControlUI* pOwner);    void SetVisible(bool bVisible = true);    void SetEnabled(bool bEnable = true);    bool IsSelected() const;    bool Select(bool bSelect = true);    bool IsExpanded() const;    bool Expand(bool bExpand = true);    void Invalidate(); // 直接CControl::Invalidate会导致滚动条刷新,重写减少刷新区域    bool Activate();    void DoEvent(TEventUI& event);    void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);    void DoPaint(HDC hDC, const RECT& rcPaint);    void DrawItemText(HDC hDC, const RECT& rcItem);        void DrawItemBk(HDC hDC, const RECT& rcItem);protected:    int m_iIndex;    bool m_bSelected;    UINT m_uButtonState;    IListOwnerUI* m_pOwner;};} // namespace DuiLib#endif // __UILIST_H__



#include "StdAfx.h"namespace DuiLib {/////////////////////////////////////////////////////////////////////////////////////////CListUI::CListUI() : m_pCallback(NULL), m_bScrollSelect(false), m_iCurSel(-1), m_iExpandedItem(-1){    m_pList = new CListBodyUI(this);    m_pHeader = new CListHeaderUI;    Add(m_pHeader);    CVerticalLayoutUI::Add(m_pList);    m_ListInfo.nColumns = 0;    m_ListInfo.nFont = -1;    m_ListInfo.uTextStyle = DT_VCENTER; // m_uTextStyle(DT_VCENTER | DT_END_ELLIPSIS)    m_ListInfo.dwTextColor = 0xFF000000;    m_ListInfo.dwBkColor = 0;    m_ListInfo.bAlternateBk = false;    m_ListInfo.dwSelectedTextColor = 0xFF000000;    m_ListInfo.dwSelectedBkColor = 0xFFC1E3FF;    m_ListInfo.dwHotTextColor = 0xFF000000;    m_ListInfo.dwHotBkColor = 0xFFE9F5FF;    m_ListInfo.dwDisabledTextColor = 0xFFCCCCCC;    m_ListInfo.dwDisabledBkColor = 0xFFFFFFFF;    m_ListInfo.dwLineColor = 0;    m_ListInfo.bShowHtml = false;    m_ListInfo.bMultiExpandable = false;    ::ZeroMemory(&m_ListInfo.rcTextPadding, sizeof(m_ListInfo.rcTextPadding));    ::ZeroMemory(&m_ListInfo.rcColumn, sizeof(m_ListInfo.rcColumn));}LPCTSTR CListUI::GetClass() const{    return _T("ListUI");}UINT CListUI::GetControlFlags() const{    return UIFLAG_TABSTOP;}LPVOID CListUI::GetInterface(LPCTSTR pstrName){if( _tcscmp(pstrName, DUI_CTR_LIST) == 0 ) return static_cast<CListUI*>(this);    if( _tcscmp(pstrName, _T("IList")) == 0 ) return static_cast<IListUI*>(this);    if( _tcscmp(pstrName, _T("IListOwner")) == 0 ) return static_cast<IListOwnerUI*>(this);    return CVerticalLayoutUI::GetInterface(pstrName);}CControlUI* CListUI::GetItemAt(int iIndex) const{    return m_pList->GetItemAt(iIndex);}int CListUI::GetItemIndex(CControlUI* pControl) const{    if( pControl->GetInterface(_T("ListHeader")) != NULL ) return CVerticalLayoutUI::GetItemIndex(pControl);    // We also need to recognize header sub-items    if( _tcsstr(pControl->GetClass(), _T("ListHeaderItemUI")) != NULL ) return m_pHeader->GetItemIndex(pControl);    return m_pList->GetItemIndex(pControl);}bool CListUI::SetItemIndex(CControlUI* pControl, int iIndex){    if( pControl->GetInterface(_T("ListHeader")) != NULL ) return CVerticalLayoutUI::SetItemIndex(pControl, iIndex);    // We also need to recognize header sub-items    if( _tcsstr(pControl->GetClass(), _T("ListHeaderItemUI")) != NULL ) return m_pHeader->SetItemIndex(pControl, iIndex);    int iOrginIndex = m_pList->GetItemIndex(pControl);    if( iOrginIndex == -1 ) return false;    if( iOrginIndex == iIndex ) return true;    IListItemUI* pSelectedListItem = NULL;    if( m_iCurSel >= 0 ) pSelectedListItem =         static_cast<IListItemUI*>(GetItemAt(m_iCurSel)->GetInterface(_T("ListItem")));    if( !m_pList->SetItemIndex(pControl, iIndex) ) return false;    int iMinIndex = min(iOrginIndex, iIndex);    int iMaxIndex = max(iOrginIndex, iIndex);    for(int i = iMinIndex; i < iMaxIndex + 1; ++i) {        CControlUI* p = m_pList->GetItemAt(i);        IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));        if( pListItem != NULL ) {            pListItem->SetIndex(i);        }    }    if( m_iCurSel >= 0 && pSelectedListItem != NULL ) m_iCurSel = pSelectedListItem->GetIndex();    return true;}int CListUI::GetCount() const{    return m_pList->GetCount();}bool CListUI::Add(CControlUI* pControl){    // Override the Add() method so we can add items specifically to    // the intended widgets. Headers are assumed to be    // answer the correct interface so we can add multiple list headers.    if( pControl->GetInterface(_T("ListHeader")) != NULL ) {        if( m_pHeader != pControl && m_pHeader->GetCount() == 0 ) {            CVerticalLayoutUI::Remove(m_pHeader);            m_pHeader = static_cast<CListHeaderUI*>(pControl);        }        m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);        return CVerticalLayoutUI::AddAt(pControl, 0);    }    // We also need to recognize header sub-items    if( _tcsstr(pControl->GetClass(), _T("ListHeaderItemUI")) != NULL ) {        bool ret = m_pHeader->Add(pControl);        m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);        return ret;    }    // The list items should know about us    IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));    if( pListItem != NULL ) {        pListItem->SetOwner(this);        pListItem->SetIndex(GetCount());    }    return m_pList->Add(pControl);}bool CListUI::AddAt(CControlUI* pControl, int iIndex){    // Override the AddAt() method so we can add items specifically to    // the intended widgets. Headers and are assumed to be    // answer the correct interface so we can add multiple list headers.    if( pControl->GetInterface(_T("ListHeader")) != NULL ) {        if( m_pHeader != pControl && m_pHeader->GetCount() == 0 ) {            CVerticalLayoutUI::Remove(m_pHeader);            m_pHeader = static_cast<CListHeaderUI*>(pControl);        }        m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);        return CVerticalLayoutUI::AddAt(pControl, 0);    }    // We also need to recognize header sub-items    if( _tcsstr(pControl->GetClass(), _T("ListHeaderItemUI")) != NULL ) {        bool ret = m_pHeader->AddAt(pControl, iIndex);        m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);        return ret;    }    if (!m_pList->AddAt(pControl, iIndex)) return false;    // The list items should know about us    IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));    if( pListItem != NULL ) {        pListItem->SetOwner(this);        pListItem->SetIndex(iIndex);    }    for(int i = iIndex + 1; i < m_pList->GetCount(); ++i) {        CControlUI* p = m_pList->GetItemAt(i);        pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));        if( pListItem != NULL ) {            pListItem->SetIndex(i);        }    }    if( m_iCurSel >= iIndex ) m_iCurSel += 1;    return true;}bool CListUI::Remove(CControlUI* pControl){    if( pControl->GetInterface(_T("ListHeader")) != NULL ) return CVerticalLayoutUI::Remove(pControl);    // We also need to recognize header sub-items    if( _tcsstr(pControl->GetClass(), _T("ListHeaderItemUI")) != NULL ) return m_pHeader->Remove(pControl);    int iIndex = m_pList->GetItemIndex(pControl);    if (iIndex == -1) return false;    if (!m_pList->RemoveAt(iIndex)) return false;    for(int i = iIndex; i < m_pList->GetCount(); ++i) {        CControlUI* p = m_pList->GetItemAt(i);        IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));        if( pListItem != NULL ) {            pListItem->SetIndex(i);        }    }    if( iIndex == m_iCurSel && m_iCurSel >= 0 ) {        int iSel = m_iCurSel;        m_iCurSel = -1;        SelectItem(FindSelectable(iSel, false));    }    else if( iIndex < m_iCurSel ) m_iCurSel -= 1;    return true;}bool CListUI::RemoveAt(int iIndex){    if (!m_pList->RemoveAt(iIndex)) return false;    for(int i = iIndex; i < m_pList->GetCount(); ++i) {        CControlUI* p = m_pList->GetItemAt(i);        IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));        if( pListItem != NULL ) pListItem->SetIndex(i);    }    if( iIndex == m_iCurSel && m_iCurSel >= 0 ) {        int iSel = m_iCurSel;        m_iCurSel = -1;        SelectItem(FindSelectable(iSel, false));    }    else if( iIndex < m_iCurSel ) m_iCurSel -= 1;    return true;}void CListUI::RemoveAll(){    m_iCurSel = -1;    m_iExpandedItem = -1;    m_pList->RemoveAll();}void CListUI::SetPos(RECT rc){    CVerticalLayoutUI::SetPos(rc);    if( m_pHeader == NULL ) return;    // Determine general list information and the size of header columns    m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);    // The header/columns may or may not be visible at runtime. In either case    // we should determine the correct dimensions...    if( !m_pHeader->IsVisible() ) {        for( int it = 0; it < m_pHeader->GetCount(); it++ ) {            static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(true);        }        m_pHeader->SetPos(CDuiRect(rc.left, 0, rc.right, 0));    }    int iOffset = m_pList->GetScrollPos().cx;    for( int i = 0; i < m_ListInfo.nColumns; i++ ) {        CControlUI* pControl = static_cast<CControlUI*>(m_pHeader->GetItemAt(i));        if( !pControl->IsVisible() ) continue;        if( pControl->IsFloat() ) continue;        RECT rcPos = pControl->GetPos();        if( iOffset > 0 ) {            rcPos.left -= iOffset;            rcPos.right -= iOffset;            pControl->SetPos(rcPos);        }        m_ListInfo.rcColumn[i] = pControl->GetPos();    }    if( !m_pHeader->IsVisible() ) {        for( int it = 0; it < m_pHeader->GetCount(); it++ ) {            static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(false);        }    }}void CListUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pParent != NULL ) m_pParent->DoEvent(event);        else CVerticalLayoutUI::DoEvent(event);        return;    }    if( event.Type == UIEVENT_SETFOCUS )     {        m_bFocused = true;        return;    }    if( event.Type == UIEVENT_KILLFOCUS )     {        m_bFocused = false;        return;    }    switch( event.Type ) {    case UIEVENT_KEYDOWN:        switch( event.chKey ) {        case VK_UP:            SelectItem(FindSelectable(m_iCurSel - 1, false), true);            return;        case VK_DOWN:            SelectItem(FindSelectable(m_iCurSel + 1, true), true);            return;        case VK_PRIOR:            PageUp();            return;        case VK_NEXT:            PageDown();            return;        case VK_HOME:            SelectItem(FindSelectable(0, false), true);            return;        case VK_END:            SelectItem(FindSelectable(GetCount() - 1, true), true);            return;        case VK_RETURN:            if( m_iCurSel != -1 ) GetItemAt(m_iCurSel)->Activate();            return;            }        break;    case UIEVENT_SCROLLWHEEL:        {            switch( LOWORD(event.wParam) ) {            case SB_LINEUP:                if( m_bScrollSelect ) SelectItem(FindSelectable(m_iCurSel - 1, false), true);                else LineUp();                return;            case SB_LINEDOWN:                if( m_bScrollSelect ) SelectItem(FindSelectable(m_iCurSel + 1, true), true);                else LineDown();                return;            }        }        break;    }    CVerticalLayoutUI::DoEvent(event);}CListHeaderUI* CListUI::GetHeader() const{    return m_pHeader;}CContainerUI* CListUI::GetList() const{    return m_pList;}bool CListUI::GetScrollSelect(){    return m_bScrollSelect;}void CListUI::SetScrollSelect(bool bScrollSelect){    m_bScrollSelect = bScrollSelect;}int CListUI::GetCurSel() const{    return m_iCurSel;}bool CListUI::SelectItem(int iIndex, bool bTakeFocus){    if( iIndex == m_iCurSel ) return true;    int iOldSel = m_iCurSel;    // We should first unselect the currently selected item    if( m_iCurSel >= 0 ) {        CControlUI* pControl = GetItemAt(m_iCurSel);        if( pControl != NULL) {            IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));            if( pListItem != NULL ) pListItem->Select(false);        }        m_iCurSel = -1;    }    if( iIndex < 0 ) return false;    CControlUI* pControl = GetItemAt(iIndex);    if( pControl == NULL ) return false;    if( !pControl->IsVisible() ) return false;    if( !pControl->IsEnabled() ) return false;    IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));    if( pListItem == NULL ) return false;    m_iCurSel = iIndex;    if( !pListItem->Select(true) ) {        m_iCurSel = -1;        return false;    }    EnsureVisible(m_iCurSel);    if( bTakeFocus ) pControl->SetFocus();    if( m_pManager != NULL ) {        m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMSELECT, m_iCurSel, iOldSel);    }    return true;}TListInfoUI* CListUI::GetListInfo(){    return &m_ListInfo;}int CListUI::GetChildPadding() const{    return m_pList->GetChildPadding();}void CListUI::SetChildPadding(int iPadding){    m_pList->SetChildPadding(iPadding);}void CListUI::SetItemFont(int index){    m_ListInfo.nFont = index;    NeedUpdate();}void CListUI::SetItemTextStyle(UINT uStyle){    m_ListInfo.uTextStyle = uStyle;    NeedUpdate();}void CListUI::SetItemTextPadding(RECT rc){    m_ListInfo.rcTextPadding = rc;    NeedUpdate();}RECT CListUI::GetItemTextPadding() const{return m_ListInfo.rcTextPadding;}void CListUI::SetItemTextColor(DWORD dwTextColor){    m_ListInfo.dwTextColor = dwTextColor;    Invalidate();}void CListUI::SetItemBkColor(DWORD dwBkColor){    m_ListInfo.dwBkColor = dwBkColor;    Invalidate();}void CListUI::SetItemBkImage(LPCTSTR pStrImage){    m_ListInfo.sBkImage = pStrImage;    Invalidate();}void CListUI::SetAlternateBk(bool bAlternateBk){    m_ListInfo.bAlternateBk = bAlternateBk;    Invalidate();}DWORD CListUI::GetItemTextColor() const{return m_ListInfo.dwTextColor;}DWORD CListUI::GetItemBkColor() const{return m_ListInfo.dwBkColor;}LPCTSTR CListUI::GetItemBkImage() const{return m_ListInfo.sBkImage;}bool CListUI::IsAlternateBk() const{    return m_ListInfo.bAlternateBk;}void CListUI::SetSelectedItemTextColor(DWORD dwTextColor){    m_ListInfo.dwSelectedTextColor = dwTextColor;    Invalidate();}void CListUI::SetSelectedItemBkColor(DWORD dwBkColor){    m_ListInfo.dwSelectedBkColor = dwBkColor;    Invalidate();}void CListUI::SetSelectedItemImage(LPCTSTR pStrImage){    m_ListInfo.sSelectedImage = pStrImage;    Invalidate();}DWORD CListUI::GetSelectedItemTextColor() const{return m_ListInfo.dwSelectedTextColor;}DWORD CListUI::GetSelectedItemBkColor() const{return m_ListInfo.dwSelectedBkColor;}LPCTSTR CListUI::GetSelectedItemImage() const{return m_ListInfo.sSelectedImage;}void CListUI::SetHotItemTextColor(DWORD dwTextColor){    m_ListInfo.dwHotTextColor = dwTextColor;    Invalidate();}void CListUI::SetHotItemBkColor(DWORD dwBkColor){    m_ListInfo.dwHotBkColor = dwBkColor;    Invalidate();}void CListUI::SetHotItemImage(LPCTSTR pStrImage){    m_ListInfo.sHotImage = pStrImage;    Invalidate();}DWORD CListUI::GetHotItemTextColor() const{return m_ListInfo.dwHotTextColor;}DWORD CListUI::GetHotItemBkColor() const{return m_ListInfo.dwHotBkColor;}LPCTSTR CListUI::GetHotItemImage() const{return m_ListInfo.sHotImage;}void CListUI::SetDisabledItemTextColor(DWORD dwTextColor){    m_ListInfo.dwDisabledTextColor = dwTextColor;    Invalidate();}void CListUI::SetDisabledItemBkColor(DWORD dwBkColor){    m_ListInfo.dwDisabledBkColor = dwBkColor;    Invalidate();}void CListUI::SetDisabledItemImage(LPCTSTR pStrImage){    m_ListInfo.sDisabledImage = pStrImage;    Invalidate();}DWORD CListUI::GetDisabledItemTextColor() const{return m_ListInfo.dwDisabledTextColor;}DWORD CListUI::GetDisabledItemBkColor() const{return m_ListInfo.dwDisabledBkColor;}LPCTSTR CListUI::GetDisabledItemImage() const{return m_ListInfo.sDisabledImage;}DWORD CListUI::GetItemLineColor() const{return m_ListInfo.dwLineColor;}void CListUI::SetItemLineColor(DWORD dwLineColor){    m_ListInfo.dwLineColor = dwLineColor;    Invalidate();}bool CListUI::IsItemShowHtml(){    return m_ListInfo.bShowHtml;}void CListUI::SetItemShowHtml(bool bShowHtml){    if( m_ListInfo.bShowHtml == bShowHtml ) return;    m_ListInfo.bShowHtml = bShowHtml;    NeedUpdate();}void CListUI::SetMultiExpanding(bool bMultiExpandable){    m_ListInfo.bMultiExpandable = bMultiExpandable;}bool CListUI::ExpandItem(int iIndex, bool bExpand /*= true*/){    if( m_iExpandedItem >= 0 && !m_ListInfo.bMultiExpandable) {        CControlUI* pControl = GetItemAt(m_iExpandedItem);        if( pControl != NULL ) {            IListItemUI* pItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));            if( pItem != NULL ) pItem->Expand(false);        }        m_iExpandedItem = -1;    }    if( bExpand ) {        CControlUI* pControl = GetItemAt(iIndex);        if( pControl == NULL ) return false;        if( !pControl->IsVisible() ) return false;        IListItemUI* pItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));        if( pItem == NULL ) return false;        m_iExpandedItem = iIndex;        if( !pItem->Expand(true) ) {            m_iExpandedItem = -1;            return false;        }    }    NeedUpdate();    return true;}int CListUI::GetExpandedItem() const{    return m_iExpandedItem;}void CListUI::EnsureVisible(int iIndex){    if( m_iCurSel < 0 ) return;    RECT rcItem = m_pList->GetItemAt(iIndex)->GetPos();    RECT rcList = m_pList->GetPos();    RECT rcListInset = m_pList->GetInset();    rcList.left += rcListInset.left;    rcList.top += rcListInset.top;    rcList.right -= rcListInset.right;    rcList.bottom -= rcListInset.bottom;    CScrollBarUI* pHorizontalScrollBar = m_pList->GetHorizontalScrollBar();    if( pHorizontalScrollBar && pHorizontalScrollBar->IsVisible() ) rcList.bottom -= pHorizontalScrollBar->GetFixedHeight();    int iPos = m_pList->GetScrollPos().cy;    if( rcItem.top >= rcList.top && rcItem.bottom < rcList.bottom ) return;    int dx = 0;    if( rcItem.top < rcList.top ) dx = rcItem.top - rcList.top;    if( rcItem.bottom > rcList.bottom ) dx = rcItem.bottom - rcList.bottom;    Scroll(0, dx);}void CListUI::Scroll(int dx, int dy){    if( dx == 0 && dy == 0 ) return;    SIZE sz = m_pList->GetScrollPos();    m_pList->SetScrollPos(CSize(sz.cx + dx, sz.cy + dy));}void CListUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue){    if( _tcscmp(pstrName, _T("header")) == 0 ) GetHeader()->SetVisible(_tcscmp(pstrValue, _T("hidden")) != 0);    else if( _tcscmp(pstrName, _T("headerbkimage")) == 0 ) GetHeader()->SetBkImage(pstrValue);    else if( _tcscmp(pstrName, _T("scrollselect")) == 0 ) SetScrollSelect(_tcscmp(pstrValue, _T("true")) == 0);    else if( _tcscmp(pstrName, _T("multiexpanding")) == 0 ) SetMultiExpanding(_tcscmp(pstrValue, _T("true")) == 0);    else if( _tcscmp(pstrName, _T("itemfont")) == 0 ) m_ListInfo.nFont = _ttoi(pstrValue);    else if( _tcscmp(pstrName, _T("itemalign")) == 0 ) {        if( _tcsstr(pstrValue, _T("left")) != NULL ) {            m_ListInfo.uTextStyle &= ~(DT_CENTER | DT_RIGHT);            m_ListInfo.uTextStyle |= DT_LEFT;        }        if( _tcsstr(pstrValue, _T("center")) != NULL ) {            m_ListInfo.uTextStyle &= ~(DT_LEFT | DT_RIGHT);            m_ListInfo.uTextStyle |= DT_CENTER;        }        if( _tcsstr(pstrValue, _T("right")) != NULL ) {            m_ListInfo.uTextStyle &= ~(DT_LEFT | DT_CENTER);            m_ListInfo.uTextStyle |= DT_RIGHT;        }    }    else if( _tcscmp(pstrName, _T("itemendellipsis")) == 0 ) {        if( _tcscmp(pstrValue, _T("true")) == 0 ) m_ListInfo.uTextStyle |= DT_END_ELLIPSIS;        else m_ListInfo.uTextStyle &= ~DT_END_ELLIPSIS;    }        if( _tcscmp(pstrName, _T("itemtextpadding")) == 0 ) {        RECT rcTextPadding = { 0 };        LPTSTR pstr = NULL;        rcTextPadding.left = _tcstol(pstrValue, &pstr, 10);  ASSERT(pstr);            rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10);    ASSERT(pstr);            rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10);  ASSERT(pstr);            rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);            SetItemTextPadding(rcTextPadding);    }    else if( _tcscmp(pstrName, _T("itemtextcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetItemTextColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itembkcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetItemBkColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itembkimage")) == 0 ) SetItemBkImage(pstrValue);    else if( _tcscmp(pstrName, _T("itemaltbk")) == 0 ) SetAlternateBk(_tcscmp(pstrValue, _T("true")) == 0);    else if( _tcscmp(pstrName, _T("itemselectedtextcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetSelectedItemTextColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemselectedbkcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetSelectedItemBkColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemselectedimage")) == 0 ) SetSelectedItemImage(pstrValue);    else if( _tcscmp(pstrName, _T("itemhottextcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetHotItemTextColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemhotbkcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetHotItemBkColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemhotimage")) == 0 ) SetHotItemImage(pstrValue);    else if( _tcscmp(pstrName, _T("itemdisabledtextcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetDisabledItemTextColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemdisabledbkcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetDisabledItemBkColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemdisabledimage")) == 0 ) SetDisabledItemImage(pstrValue);    else if( _tcscmp(pstrName, _T("itemlinecolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetItemLineColor(clrColor);    }    else if( _tcscmp(pstrName, _T("itemshowhtml")) == 0 ) SetItemShowHtml(_tcscmp(pstrValue, _T("true")) == 0);    else CVerticalLayoutUI::SetAttribute(pstrName, pstrValue);}IListCallbackUI* CListUI::GetTextCallback() const{    return m_pCallback;}void CListUI::SetTextCallback(IListCallbackUI* pCallback){    m_pCallback = pCallback;}SIZE CListUI::GetScrollPos() const{    return m_pList->GetScrollPos();}SIZE CListUI::GetScrollRange() const{    return m_pList->GetScrollRange();}void CListUI::SetScrollPos(SIZE szPos){    m_pList->SetScrollPos(szPos);}void CListUI::LineUp(){    m_pList->LineUp();}void CListUI::LineDown(){    m_pList->LineDown();}void CListUI::PageUp(){    m_pList->PageUp();}void CListUI::PageDown(){    m_pList->PageDown();}void CListUI::HomeUp(){    m_pList->HomeUp();}void CListUI::EndDown(){    m_pList->EndDown();}void CListUI::LineLeft(){    m_pList->LineLeft();}void CListUI::LineRight(){    m_pList->LineRight();}void CListUI::PageLeft(){    m_pList->PageLeft();}void CListUI::PageRight(){    m_pList->PageRight();}void CListUI::HomeLeft(){    m_pList->HomeLeft();}void CListUI::EndRight(){    m_pList->EndRight();}void CListUI::EnableScrollBar(bool bEnableVertical, bool bEnableHorizontal){    m_pList->EnableScrollBar(bEnableVertical, bEnableHorizontal);}CScrollBarUI* CListUI::GetVerticalScrollBar() const{    return m_pList->GetVerticalScrollBar();}CScrollBarUI* CListUI::GetHorizontalScrollBar() const{    return m_pList->GetHorizontalScrollBar();}/////////////////////////////////////////////////////////////////////////////////////////CListBodyUI::CListBodyUI(CListUI* pOwner) : m_pOwner(pOwner){    ASSERT(m_pOwner);}void CListBodyUI::SetScrollPos(SIZE szPos){    int cx = 0;    int cy = 0;    if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {        int iLastScrollPos = m_pVerticalScrollBar->GetScrollPos();        m_pVerticalScrollBar->SetScrollPos(szPos.cy);        cy = m_pVerticalScrollBar->GetScrollPos() - iLastScrollPos;    }    if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {        int iLastScrollPos = m_pHorizontalScrollBar->GetScrollPos();        m_pHorizontalScrollBar->SetScrollPos(szPos.cx);        cx = m_pHorizontalScrollBar->GetScrollPos() - iLastScrollPos;    }    if( cx == 0 && cy == 0 ) return;    RECT rcPos;    for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {        CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);        if( !pControl->IsVisible() ) continue;        if( pControl->IsFloat() ) continue;        rcPos = pControl->GetPos();        rcPos.left -= cx;        rcPos.right -= cx;        rcPos.top -= cy;        rcPos.bottom -= cy;        pControl->SetPos(rcPos);    }    Invalidate();    if( cx != 0 && m_pOwner ) {        CListHeaderUI* pHeader = m_pOwner->GetHeader();        if( pHeader == NULL ) return;        TListInfoUI* pInfo = m_pOwner->GetListInfo();        pInfo->nColumns = MIN(pHeader->GetCount(), UILIST_MAX_COLUMNS);        if( !pHeader->IsVisible() ) {            for( int it = 0; it < pHeader->GetCount(); it++ ) {                static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(true);            }        }        for( int i = 0; i < pInfo->nColumns; i++ ) {            CControlUI* pControl = static_cast<CControlUI*>(pHeader->GetItemAt(i));            if( !pControl->IsVisible() ) continue;            if( pControl->IsFloat() ) continue;            RECT rcPos = pControl->GetPos();            rcPos.left -= cx;            rcPos.right -= cx;            pControl->SetPos(rcPos);            pInfo->rcColumn[i] = pControl->GetPos();        }        if( !pHeader->IsVisible() ) {            for( int it = 0; it < pHeader->GetCount(); it++ ) {                static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(false);            }        }    }}void CListBodyUI::SetPos(RECT rc){    CControlUI::SetPos(rc);    rc = m_rcItem;    // Adjust for inset    rc.left += m_rcInset.left;    rc.top += m_rcInset.top;    rc.right -= m_rcInset.right;    rc.bottom -= m_rcInset.bottom;    if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) rc.right -= m_pVerticalScrollBar->GetFixedWidth();    if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();    // Determine the minimum size    SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };    if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() )         szAvailable.cx += m_pHorizontalScrollBar->GetScrollRange();    int cxNeeded = 0;    int nAdjustables = 0;    int cyFixed = 0;    int nEstimateNum = 0;    for( int it1 = 0; it1 < m_items.GetSize(); it1++ ) {        CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);        if( !pControl->IsVisible() ) continue;        if( pControl->IsFloat() ) continue;        SIZE sz = pControl->EstimateSize(szAvailable);        if( sz.cy == 0 ) {            nAdjustables++;        }        else {            if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight();            if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight();        }        cyFixed += sz.cy + pControl->GetPadding().top + pControl->GetPadding().bottom;        RECT rcPadding = pControl->GetPadding();        sz.cx = MAX(sz.cx, 0);        if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth();        if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth();        cxNeeded = MAX(cxNeeded, sz.cx);        nEstimateNum++;    }    cyFixed += (nEstimateNum - 1) * m_iChildPadding;    if( m_pOwner ) {        CListHeaderUI* pHeader = m_pOwner->GetHeader();        if( pHeader != NULL && pHeader->GetCount() > 0 ) {            cxNeeded = MAX(0, pHeader->EstimateSize(CSize(rc.right - rc.left, rc.bottom - rc.top)).cx);        }    }    // Place elements    int cyNeeded = 0;    int cyExpand = 0;    if( nAdjustables > 0 ) cyExpand = MAX(0, (szAvailable.cy - cyFixed) / nAdjustables);    // Position the elements    SIZE szRemaining = szAvailable;    int iPosY = rc.top;    if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {        iPosY -= m_pVerticalScrollBar->GetScrollPos();    }    int iPosX = rc.left;    if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {        iPosX -= m_pHorizontalScrollBar->GetScrollPos();    }    int iAdjustable = 0;    int cyFixedRemaining = cyFixed;    for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {        CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);        if( !pControl->IsVisible() ) continue;        if( pControl->IsFloat() ) {            SetFloatPos(it2);            continue;        }        RECT rcPadding = pControl->GetPadding();        szRemaining.cy -= rcPadding.top;        SIZE sz = pControl->EstimateSize(szRemaining);        if( sz.cy == 0 ) {            iAdjustable++;            sz.cy = cyExpand;            // Distribute remaining to last element (usually round-off left-overs)            if( iAdjustable == nAdjustables ) {                sz.cy = MAX(0, szRemaining.cy - rcPadding.bottom - cyFixedRemaining);            }             if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight();            if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight();        }        else {            if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight();            if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight();            cyFixedRemaining -= sz.cy;        }        sz.cx = MAX(cxNeeded, szAvailable.cx - rcPadding.left - rcPadding.right);        if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth();        if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth();        RECT rcCtrl = { iPosX + rcPadding.left, iPosY + rcPadding.top, iPosX + rcPadding.left + sz.cx, iPosY + sz.cy + rcPadding.top + rcPadding.bottom };        pControl->SetPos(rcCtrl);        iPosY += sz.cy + m_iChildPadding + rcPadding.top + rcPadding.bottom;        cyNeeded += sz.cy + rcPadding.top + rcPadding.bottom;        szRemaining.cy -= sz.cy + m_iChildPadding + rcPadding.bottom;    }    cyNeeded += (nEstimateNum - 1) * m_iChildPadding;    if( m_pHorizontalScrollBar != NULL ) {        if( cxNeeded > rc.right - rc.left ) {            if( m_pHorizontalScrollBar->IsVisible() ) {                m_pHorizontalScrollBar->SetScrollRange(cxNeeded - (rc.right - rc.left));            }            else {                m_pHorizontalScrollBar->SetVisible(true);                m_pHorizontalScrollBar->SetScrollRange(cxNeeded - (rc.right - rc.left));                m_pHorizontalScrollBar->SetScrollPos(0);                rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();            }        }        else {            if( m_pHorizontalScrollBar->IsVisible() ) {                m_pHorizontalScrollBar->SetVisible(false);                m_pHorizontalScrollBar->SetScrollRange(0);                m_pHorizontalScrollBar->SetScrollPos(0);                rc.bottom += m_pHorizontalScrollBar->GetFixedHeight();            }        }    }    // Process the scrollbar    ProcessScrollBar(rc, cxNeeded, cyNeeded);}void CListBodyUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pOwner != NULL ) m_pOwner->DoEvent(event);        else CControlUI::DoEvent(event);        return;    }    if( m_pOwner != NULL ) m_pOwner->DoEvent(event); else CControlUI::DoEvent(event);}/////////////////////////////////////////////////////////////////////////////////////////CListHeaderUI::CListHeaderUI(){}LPCTSTR CListHeaderUI::GetClass() const{    return _T("ListHeaderUI");}LPVOID CListHeaderUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTHEADER) == 0 ) return this;    return CHorizontalLayoutUI::GetInterface(pstrName);}SIZE CListHeaderUI::EstimateSize(SIZE szAvailable){    SIZE cXY = {0, m_cxyFixed.cy};if( cXY.cy == 0 && m_pManager != NULL ) {for( int it = 0; it < m_items.GetSize(); it++ ) {cXY.cy = MAX(cXY.cy,static_cast<CControlUI*>(m_items[it])->EstimateSize(szAvailable).cy);}int nMin = m_pManager->GetDefaultFontInfo()->tm.tmHeight + 6;cXY.cy = MAX(cXY.cy,nMin);}    for( int it = 0; it < m_items.GetSize(); it++ ) {        cXY.cx +=  static_cast<CControlUI*>(m_items[it])->EstimateSize(szAvailable).cx;    }    return cXY;}/////////////////////////////////////////////////////////////////////////////////////////CListHeaderItemUI::CListHeaderItemUI() : m_bDragable(true), m_uButtonState(0), m_iSepWidth(4),m_uTextStyle(DT_VCENTER | DT_CENTER | DT_SINGLELINE), m_dwTextColor(0), m_iFont(-1), m_bShowHtml(false){SetTextPadding(CDuiRect(2, 0, 2, 0));    ptLastMouse.x = ptLastMouse.y = 0;    SetMinWidth(16);}LPCTSTR CListHeaderItemUI::GetClass() const{    return _T("ListHeaderItemUI");}LPVOID CListHeaderItemUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTHEADERITEM) == 0 ) return this;    return CControlUI::GetInterface(pstrName);}UINT CListHeaderItemUI::GetControlFlags() const{    if( IsEnabled() && m_iSepWidth != 0 ) return UIFLAG_SETCURSOR;    else return 0;}void CListHeaderItemUI::SetEnabled(bool bEnable){    CControlUI::SetEnabled(bEnable);    if( !IsEnabled() ) {        m_uButtonState = 0;    }}bool CListHeaderItemUI::IsDragable() const{return m_bDragable;}void CListHeaderItemUI::SetDragable(bool bDragable){    m_bDragable = bDragable;    if ( !m_bDragable ) m_uButtonState &= ~UISTATE_CAPTURED;}DWORD CListHeaderItemUI::GetSepWidth() const{return m_iSepWidth;}void CListHeaderItemUI::SetSepWidth(int iWidth){    m_iSepWidth = iWidth;}DWORD CListHeaderItemUI::GetTextStyle() const{return m_uTextStyle;}void CListHeaderItemUI::SetTextStyle(UINT uStyle){    m_uTextStyle = uStyle;    Invalidate();}DWORD CListHeaderItemUI::GetTextColor() const{return m_dwTextColor;}void CListHeaderItemUI::SetTextColor(DWORD dwTextColor){    m_dwTextColor = dwTextColor;}RECT CListHeaderItemUI::GetTextPadding() const{return m_rcTextPadding;}void CListHeaderItemUI::SetTextPadding(RECT rc){m_rcTextPadding = rc;Invalidate();}void CListHeaderItemUI::SetFont(int index){    m_iFont = index;}bool CListHeaderItemUI::IsShowHtml(){    return m_bShowHtml;}void CListHeaderItemUI::SetShowHtml(bool bShowHtml){    if( m_bShowHtml == bShowHtml ) return;    m_bShowHtml = bShowHtml;    Invalidate();}LPCTSTR CListHeaderItemUI::GetNormalImage() const{return m_sNormalImage;}void CListHeaderItemUI::SetNormalImage(LPCTSTR pStrImage){    m_sNormalImage = pStrImage;    Invalidate();}LPCTSTR CListHeaderItemUI::GetHotImage() const{    return m_sHotImage;}void CListHeaderItemUI::SetHotImage(LPCTSTR pStrImage){    m_sHotImage = pStrImage;    Invalidate();}LPCTSTR CListHeaderItemUI::GetPushedImage() const{    return m_sPushedImage;}void CListHeaderItemUI::SetPushedImage(LPCTSTR pStrImage){    m_sPushedImage = pStrImage;    Invalidate();}LPCTSTR CListHeaderItemUI::GetFocusedImage() const{    return m_sFocusedImage;}void CListHeaderItemUI::SetFocusedImage(LPCTSTR pStrImage){    m_sFocusedImage = pStrImage;    Invalidate();}LPCTSTR CListHeaderItemUI::GetSepImage() const{    return m_sSepImage;}void CListHeaderItemUI::SetSepImage(LPCTSTR pStrImage){    m_sSepImage = pStrImage;    Invalidate();}void CListHeaderItemUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue){    if( _tcscmp(pstrName, _T("dragable")) == 0 ) SetDragable(_tcscmp(pstrValue, _T("true")) == 0);    else if( _tcscmp(pstrName, _T("sepwidth")) == 0 ) SetSepWidth(_ttoi(pstrValue));    else if( _tcscmp(pstrName, _T("align")) == 0 ) {        if( _tcsstr(pstrValue, _T("left")) != NULL ) {            m_uTextStyle &= ~(DT_CENTER | DT_RIGHT);            m_uTextStyle |= DT_LEFT;        }        if( _tcsstr(pstrValue, _T("center")) != NULL ) {            m_uTextStyle &= ~(DT_LEFT | DT_RIGHT);            m_uTextStyle |= DT_CENTER;        }        if( _tcsstr(pstrValue, _T("right")) != NULL ) {            m_uTextStyle &= ~(DT_LEFT | DT_CENTER);            m_uTextStyle |= DT_RIGHT;        }    }    else if( _tcscmp(pstrName, _T("endellipsis")) == 0 ) {        if( _tcscmp(pstrValue, _T("true")) == 0 ) m_uTextStyle |= DT_END_ELLIPSIS;        else m_uTextStyle &= ~DT_END_ELLIPSIS;    }        else if( _tcscmp(pstrName, _T("font")) == 0 ) SetFont(_ttoi(pstrValue));    else if( _tcscmp(pstrName, _T("textcolor")) == 0 ) {        if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);        LPTSTR pstr = NULL;        DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);        SetTextColor(clrColor);    }else if( _tcscmp(pstrName, _T("textpadding")) == 0 ) {RECT rcTextPadding = { 0 };LPTSTR pstr = NULL;rcTextPadding.left = _tcstol(pstrValue, &pstr, 10);  ASSERT(pstr);    rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10);    ASSERT(pstr);    rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10);  ASSERT(pstr);    rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);    SetTextPadding(rcTextPadding);}    else if( _tcscmp(pstrName, _T("showhtml")) == 0 ) SetShowHtml(_tcscmp(pstrValue, _T("true")) == 0);    else if( _tcscmp(pstrName, _T("normalimage")) == 0 ) SetNormalImage(pstrValue);    else if( _tcscmp(pstrName, _T("hotimage")) == 0 ) SetHotImage(pstrValue);    else if( _tcscmp(pstrName, _T("pushedimage")) == 0 ) SetPushedImage(pstrValue);    else if( _tcscmp(pstrName, _T("focusedimage")) == 0 ) SetFocusedImage(pstrValue);    else if( _tcscmp(pstrName, _T("sepimage")) == 0 ) SetSepImage(pstrValue);    else CControlUI::SetAttribute(pstrName, pstrValue);}void CListHeaderItemUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pParent != NULL ) m_pParent->DoEvent(event);        else CControlUI::DoEvent(event);        return;    }    if( event.Type == UIEVENT_SETFOCUS )     {        Invalidate();    }    if( event.Type == UIEVENT_KILLFOCUS )     {        Invalidate();    }    if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_DBLCLICK )    {        if( !IsEnabled() ) return;        RECT rcSeparator = GetThumbRect();if (m_iSepWidth>=0)//111024 by cddjr, 增加分隔符区域,方便用户拖动rcSeparator.left-=4;elsercSeparator.right+=4;        if( ::PtInRect(&rcSeparator, event.ptMouse) ) {            if( m_bDragable ) {                m_uButtonState |= UISTATE_CAPTURED;                ptLastMouse = event.ptMouse;            }        }        else {            m_uButtonState |= UISTATE_PUSHED;            m_pManager->SendNotify(this, DUI_MSGTYPE_HEADERCLICK);            Invalidate();        }        return;    }    if( event.Type == UIEVENT_BUTTONUP )    {        if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {            m_uButtonState &= ~UISTATE_CAPTURED;            if( GetParent() )                 GetParent()->NeedParentUpdate();        }        else if( (m_uButtonState & UISTATE_PUSHED) != 0 ) {            m_uButtonState &= ~UISTATE_PUSHED;            Invalidate();        }        return;    }    if( event.Type == UIEVENT_MOUSEMOVE )    {        if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {            RECT rc = m_rcItem;            if( m_iSepWidth >= 0 ) {                rc.right -= ptLastMouse.x - event.ptMouse.x;            }            else {                rc.left -= ptLastMouse.x - event.ptMouse.x;            }                        if( rc.right - rc.left > GetMinWidth() ) {                m_cxyFixed.cx = rc.right - rc.left;                ptLastMouse = event.ptMouse;                if( GetParent() )                     GetParent()->NeedParentUpdate();            }        }        return;    }    if( event.Type == UIEVENT_SETCURSOR )    {        RECT rcSeparator = GetThumbRect();if (m_iSepWidth>=0)//111024 by cddjr, 增加分隔符区域,方便用户拖动rcSeparator.left-=4;elsercSeparator.right+=4;        if( IsEnabled() && m_bDragable && ::PtInRect(&rcSeparator, event.ptMouse) ) {            ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));            return;        }    }    if( event.Type == UIEVENT_MOUSEENTER )    {        if( IsEnabled() ) {            m_uButtonState |= UISTATE_HOT;            Invalidate();        }        return;    }    if( event.Type == UIEVENT_MOUSELEAVE )    {        if( IsEnabled() ) {            m_uButtonState &= ~UISTATE_HOT;            Invalidate();        }        return;    }    CControlUI::DoEvent(event);}SIZE CListHeaderItemUI::EstimateSize(SIZE szAvailable){    if( m_cxyFixed.cy == 0 ) return CSize(m_cxyFixed.cx, m_pManager->GetDefaultFontInfo()->tm.tmHeight + 14);    return CControlUI::EstimateSize(szAvailable);}RECT CListHeaderItemUI::GetThumbRect() const{    if( m_iSepWidth >= 0 ) return CDuiRect(m_rcItem.right - m_iSepWidth, m_rcItem.top, m_rcItem.right, m_rcItem.bottom);    else return CDuiRect(m_rcItem.left, m_rcItem.top, m_rcItem.left - m_iSepWidth, m_rcItem.bottom);}void CListHeaderItemUI::PaintStatusImage(HDC hDC){    if( IsFocused() ) m_uButtonState |= UISTATE_FOCUSED;    else m_uButtonState &= ~ UISTATE_FOCUSED;    if( (m_uButtonState & UISTATE_PUSHED) != 0 ) {        if( m_sPushedImage.IsEmpty() && !m_sNormalImage.IsEmpty() ) DrawImage(hDC, (LPCTSTR)m_sNormalImage);        if( !DrawImage(hDC, (LPCTSTR)m_sPushedImage) ) m_sPushedImage.Empty();    }    else if( (m_uButtonState & UISTATE_HOT) != 0 ) {        if( m_sHotImage.IsEmpty() && !m_sNormalImage.IsEmpty() ) DrawImage(hDC, (LPCTSTR)m_sNormalImage);        if( !DrawImage(hDC, (LPCTSTR)m_sHotImage) ) m_sHotImage.Empty();    }    else if( (m_uButtonState & UISTATE_FOCUSED) != 0 ) {        if( m_sFocusedImage.IsEmpty() && !m_sNormalImage.IsEmpty() ) DrawImage(hDC, (LPCTSTR)m_sNormalImage);        if( !DrawImage(hDC, (LPCTSTR)m_sFocusedImage) ) m_sFocusedImage.Empty();    }    else {        if( !m_sNormalImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)m_sNormalImage) ) m_sNormalImage.Empty();        }    }    if( !m_sSepImage.IsEmpty() ) {        RECT rcThumb = GetThumbRect();        rcThumb.left -= m_rcItem.left;        rcThumb.top -= m_rcItem.top;        rcThumb.right -= m_rcItem.left;        rcThumb.bottom -= m_rcItem.top;        m_sSepImageModify.Empty();        m_sSepImageModify.SmallFormat(_T("dest='%d,%d,%d,%d'"), rcThumb.left, rcThumb.top, rcThumb.right, rcThumb.bottom);        if( !DrawImage(hDC, (LPCTSTR)m_sSepImage, (LPCTSTR)m_sSepImageModify) ) m_sSepImage.Empty();    }}void CListHeaderItemUI::PaintText(HDC hDC){    if( m_dwTextColor == 0 ) m_dwTextColor = m_pManager->GetDefaultFontColor();RECT rcText = m_rcItem;rcText.left += m_rcTextPadding.left;rcText.top += m_rcTextPadding.top;rcText.right -= m_rcTextPadding.right;rcText.bottom -= m_rcTextPadding.bottom;    if( m_sText.IsEmpty() ) return;    int nLinks = 0;    if( m_bShowHtml )        CRenderEngine::DrawHtmlText(hDC, m_pManager, rcText, m_sText, m_dwTextColor, \        NULL, NULL, nLinks, DT_SINGLELINE | m_uTextStyle);    else        CRenderEngine::DrawText(hDC, m_pManager, rcText, m_sText, m_dwTextColor, \        m_iFont, DT_SINGLELINE | m_uTextStyle);}/////////////////////////////////////////////////////////////////////////////////////////CListElementUI::CListElementUI() : m_iIndex(-1),m_pOwner(NULL), m_bSelected(false),m_uButtonState(0){}LPCTSTR CListElementUI::GetClass() const{    return _T("ListElementUI");}UINT CListElementUI::GetControlFlags() const{    return UIFLAG_WANTRETURN;}LPVOID CListElementUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTITEM) == 0 ) return static_cast<IListItemUI*>(this);if( _tcscmp(pstrName, DUI_CTR_LISTELEMENT) == 0 ) return static_cast<CListElementUI*>(this);    return CControlUI::GetInterface(pstrName);}IListOwnerUI* CListElementUI::GetOwner(){    return m_pOwner;}void CListElementUI::SetOwner(CControlUI* pOwner){    m_pOwner = static_cast<IListOwnerUI*>(pOwner->GetInterface(_T("IListOwner")));}void CListElementUI::SetVisible(bool bVisible){    CControlUI::SetVisible(bVisible);    if( !IsVisible() && m_bSelected)    {        m_bSelected = false;        if( m_pOwner != NULL ) m_pOwner->SelectItem(-1);    }}void CListElementUI::SetEnabled(bool bEnable){    CControlUI::SetEnabled(bEnable);    if( !IsEnabled() ) {        m_uButtonState = 0;    }}int CListElementUI::GetIndex() const{    return m_iIndex;}void CListElementUI::SetIndex(int iIndex){    m_iIndex = iIndex;}void CListElementUI::Invalidate(){    if( !IsVisible() ) return;    if( GetParent() ) {        CContainerUI* pParentContainer = static_cast<CContainerUI*>(GetParent()->GetInterface(_T("Container")));        if( pParentContainer ) {            RECT rc = pParentContainer->GetPos();            RECT rcInset = pParentContainer->GetInset();            rc.left += rcInset.left;            rc.top += rcInset.top;            rc.right -= rcInset.right;            rc.bottom -= rcInset.bottom;            CScrollBarUI* pVerticalScrollBar = pParentContainer->GetVerticalScrollBar();            if( pVerticalScrollBar && pVerticalScrollBar->IsVisible() ) rc.right -= pVerticalScrollBar->GetFixedWidth();            CScrollBarUI* pHorizontalScrollBar = pParentContainer->GetHorizontalScrollBar();            if( pHorizontalScrollBar && pHorizontalScrollBar->IsVisible() ) rc.bottom -= pHorizontalScrollBar->GetFixedHeight();            RECT invalidateRc = m_rcItem;            if( !::IntersectRect(&invalidateRc, &m_rcItem, &rc) )             {                return;            }            CControlUI* pParent = GetParent();            RECT rcTemp;            RECT rcParent;            while( pParent = pParent->GetParent() )            {                rcTemp = invalidateRc;                rcParent = pParent->GetPos();                if( !::IntersectRect(&invalidateRc, &rcTemp, &rcParent) )                 {                    return;                }            }            if( m_pManager != NULL ) m_pManager->Invalidate(invalidateRc);        }        else {            CControlUI::Invalidate();        }    }    else {        CControlUI::Invalidate();    }}bool CListElementUI::Activate(){    if( !CControlUI::Activate() ) return false;    if( m_pManager != NULL ) m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMACTIVATE);    return true;}bool CListElementUI::IsSelected() const{    return m_bSelected;}bool CListElementUI::Select(bool bSelect){    if( !IsEnabled() ) return false;    if( bSelect == m_bSelected ) return true;    m_bSelected = bSelect;    if( bSelect && m_pOwner != NULL ) m_pOwner->SelectItem(m_iIndex);    Invalidate();    return true;}bool CListElementUI::IsExpanded() const{    return false;}bool CListElementUI::Expand(bool /*bExpand = true*/){    return false;}void CListElementUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pOwner != NULL ) m_pOwner->DoEvent(event);        else CControlUI::DoEvent(event);        return;    }    if( event.Type == UIEVENT_DBLCLICK )    {        if( IsEnabled() ) {            Activate();            Invalidate();        }        return;    }    if( event.Type == UIEVENT_KEYDOWN && IsEnabled() )    {        if( event.chKey == VK_RETURN ) {            Activate();            Invalidate();            return;        }    }    // An important twist: The list-item will send the event not to its immediate    // parent but to the "attached" list. A list may actually embed several components    // in its path to the item, but key-presses etc. needs to go to the actual list.    if( m_pOwner != NULL ) m_pOwner->DoEvent(event); else CControlUI::DoEvent(event);}void CListElementUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue){    if( _tcscmp(pstrName, _T("selected")) == 0 ) Select();    else CControlUI::SetAttribute(pstrName, pstrValue);}void CListElementUI::DrawItemBk(HDC hDC, const RECT& rcItem){    ASSERT(m_pOwner);    if( m_pOwner == NULL ) return;    TListInfoUI* pInfo = m_pOwner->GetListInfo();    DWORD iBackColor = 0;    if( !pInfo->bAlternateBk || m_iIndex % 2 == 0 ) iBackColor = pInfo->dwBkColor;    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        iBackColor = pInfo->dwHotBkColor;    }    if( IsSelected() ) {        iBackColor = pInfo->dwSelectedBkColor;    }    if( !IsEnabled() ) {        iBackColor = pInfo->dwDisabledBkColor;    }    if ( iBackColor != 0 ) {        CRenderEngine::DrawColor(hDC, m_rcItem, GetAdjustColor(iBackColor));    }    if( !IsEnabled() ) {        if( !pInfo->sDisabledImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sDisabledImage) ) pInfo->sDisabledImage.Empty();            else return;        }    }    if( IsSelected() ) {        if( !pInfo->sSelectedImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sSelectedImage) ) pInfo->sSelectedImage.Empty();            else return;        }    }    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        if( !pInfo->sHotImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sHotImage) ) pInfo->sHotImage.Empty();            else return;        }    }    if( !m_sBkImage.IsEmpty() ) {        if( !pInfo->bAlternateBk || m_iIndex % 2 == 0 ) {            if( !DrawImage(hDC, (LPCTSTR)m_sBkImage) ) m_sBkImage.Empty();        }    }    if( m_sBkImage.IsEmpty() ) {        if( !pInfo->sBkImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sBkImage) ) pInfo->sBkImage.Empty();            else return;        }    }    if ( pInfo->dwLineColor != 0 ) {        RECT rcLine = { m_rcItem.left, m_rcItem.bottom - 1, m_rcItem.right, m_rcItem.bottom - 1 };        CRenderEngine::DrawLine(hDC, rcLine, 1, GetAdjustColor(pInfo->dwLineColor));    }}/////////////////////////////////////////////////////////////////////////////////////////CListLabelElementUI::CListLabelElementUI(){}LPCTSTR CListLabelElementUI::GetClass() const{    return _T("ListLabelElementUI");}LPVOID CListLabelElementUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTLABELELEMENT) == 0 ) return static_cast<CListLabelElementUI*>(this);    return CListElementUI::GetInterface(pstrName);}void CListLabelElementUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pOwner != NULL ) m_pOwner->DoEvent(event);        else CListElementUI::DoEvent(event);        return;    }    if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_RBUTTONDOWN )    {        if( IsEnabled() ) {            m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMCLICK);            Select();            Invalidate();        }        return;    }    if( event.Type == UIEVENT_MOUSEMOVE )     {        return;    }    if( event.Type == UIEVENT_BUTTONUP )    {        return;    }    if( event.Type == UIEVENT_MOUSEENTER )    {        if( IsEnabled() ) {            m_uButtonState |= UISTATE_HOT;            Invalidate();        }        return;    }    if( event.Type == UIEVENT_MOUSELEAVE )    {        if( (m_uButtonState & UISTATE_HOT) != 0 ) {            m_uButtonState &= ~UISTATE_HOT;            Invalidate();        }        return;    }    CListElementUI::DoEvent(event);}SIZE CListLabelElementUI::EstimateSize(SIZE szAvailable){    if( m_pOwner == NULL ) return CSize(0, 0);    TListInfoUI* pInfo = m_pOwner->GetListInfo();    SIZE cXY = m_cxyFixed;    if( cXY.cy == 0 && m_pManager != NULL ) {        cXY.cy = m_pManager->GetFontInfo(pInfo->nFont)->tm.tmHeight + 8;        cXY.cy += pInfo->rcTextPadding.top + pInfo->rcTextPadding.bottom;    }    if( cXY.cx == 0 && m_pManager != NULL ) {        RECT rcText = { 0, 0, 9999, cXY.cy };        if( pInfo->bShowHtml ) {            int nLinks = 0;            CRenderEngine::DrawHtmlText(m_pManager->GetPaintDC(), m_pManager, rcText, m_sText, 0, NULL, NULL, nLinks, DT_SINGLELINE | DT_CALCRECT | pInfo->uTextStyle & ~DT_RIGHT & ~DT_CENTER);        }        else {            CRenderEngine::DrawText(m_pManager->GetPaintDC(), m_pManager, rcText, m_sText, 0, pInfo->nFont, DT_SINGLELINE | DT_CALCRECT | pInfo->uTextStyle & ~DT_RIGHT & ~DT_CENTER);        }        cXY.cx = rcText.right - rcText.left + pInfo->rcTextPadding.left + pInfo->rcTextPadding.right;            }    return cXY;}void CListLabelElementUI::DoPaint(HDC hDC, const RECT& rcPaint){    if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;    DrawItemBk(hDC, m_rcItem);    DrawItemText(hDC, m_rcItem);}void CListLabelElementUI::DrawItemText(HDC hDC, const RECT& rcItem){    if( m_sText.IsEmpty() ) return;    if( m_pOwner == NULL ) return;    TListInfoUI* pInfo = m_pOwner->GetListInfo();    DWORD iTextColor = pInfo->dwTextColor;    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        iTextColor = pInfo->dwHotTextColor;    }    if( IsSelected() ) {        iTextColor = pInfo->dwSelectedTextColor;    }    if( !IsEnabled() ) {        iTextColor = pInfo->dwDisabledTextColor;    }    int nLinks = 0;    RECT rcText = rcItem;    rcText.left += pInfo->rcTextPadding.left;    rcText.right -= pInfo->rcTextPadding.right;    rcText.top += pInfo->rcTextPadding.top;    rcText.bottom -= pInfo->rcTextPadding.bottom;    if( pInfo->bShowHtml )        CRenderEngine::DrawHtmlText(hDC, m_pManager, rcText, m_sText, iTextColor, \        NULL, NULL, nLinks, DT_SINGLELINE | pInfo->uTextStyle);    else        CRenderEngine::DrawText(hDC, m_pManager, rcText, m_sText, iTextColor, \        pInfo->nFont, DT_SINGLELINE | pInfo->uTextStyle);}/////////////////////////////////////////////////////////////////////////////////////////CListTextElementUI::CListTextElementUI() : m_nLinks(0), m_nHoverLink(-1), m_pOwner(NULL){    ::ZeroMemory(&m_rcLinks, sizeof(m_rcLinks));}CListTextElementUI::~CListTextElementUI(){    CDuiString* pText;    for( int it = 0; it < m_aTexts.GetSize(); it++ ) {        pText = static_cast<CDuiString*>(m_aTexts[it]);        if( pText ) delete pText;    }    m_aTexts.Empty();}LPCTSTR CListTextElementUI::GetClass() const{    return _T("ListTextElementUI");}LPVOID CListTextElementUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTTEXTELEMENT) == 0 ) return static_cast<CListTextElementUI*>(this);    return CListLabelElementUI::GetInterface(pstrName);}UINT CListTextElementUI::GetControlFlags() const{    return UIFLAG_WANTRETURN | ( (IsEnabled() && m_nLinks > 0) ? UIFLAG_SETCURSOR : 0);}LPCTSTR CListTextElementUI::GetText(int iIndex) const{    CDuiString* pText = static_cast<CDuiString*>(m_aTexts.GetAt(iIndex));    if( pText ) return pText->GetData();    return NULL;}void CListTextElementUI::SetText(int iIndex, LPCTSTR pstrText){    if( m_pOwner == NULL ) return;    TListInfoUI* pInfo = m_pOwner->GetListInfo();    if( iIndex < 0 || iIndex >= pInfo->nColumns ) return;    while( m_aTexts.GetSize() < pInfo->nColumns ) { m_aTexts.Add(NULL); }    CDuiString* pText = static_cast<CDuiString*>(m_aTexts[iIndex]);    if( (pText == NULL && pstrText == NULL) || (pText && *pText == pstrText) ) return;if ( pText ) //by cddjr 2011/10/20pText->Assign(pstrText);elsem_aTexts.SetAt(iIndex, new CDuiString(pstrText));    Invalidate();}void CListTextElementUI::SetOwner(CControlUI* pOwner){    CListElementUI::SetOwner(pOwner);    m_pOwner = static_cast<IListUI*>(pOwner->GetInterface(_T("IList")));}CDuiString* CListTextElementUI::GetLinkContent(int iIndex){    if( iIndex >= 0 && iIndex < m_nLinks ) return &m_sLinks[iIndex];    return NULL;}void CListTextElementUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pOwner != NULL ) m_pOwner->DoEvent(event);        else CListLabelElementUI::DoEvent(event);        return;    }    // When you hover over a link    if( event.Type == UIEVENT_SETCURSOR ) {        for( int i = 0; i < m_nLinks; i++ ) {            if( ::PtInRect(&m_rcLinks[i], event.ptMouse) ) {                ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));                return;            }        }          }    if( event.Type == UIEVENT_BUTTONUP && IsEnabled() ) {        for( int i = 0; i < m_nLinks; i++ ) {            if( ::PtInRect(&m_rcLinks[i], event.ptMouse) ) {                m_pManager->SendNotify(this, DUI_MSGTYPE_LINK, i);                return;            }        }    }    if( m_nLinks > 0 && event.Type == UIEVENT_MOUSEMOVE ) {        int nHoverLink = -1;        for( int i = 0; i < m_nLinks; i++ ) {            if( ::PtInRect(&m_rcLinks[i], event.ptMouse) ) {                nHoverLink = i;                break;            }        }        if(m_nHoverLink != nHoverLink) {            Invalidate();            m_nHoverLink = nHoverLink;        }    }    if( m_nLinks > 0 && event.Type == UIEVENT_MOUSELEAVE ) {        if(m_nHoverLink != -1) {            Invalidate();            m_nHoverLink = -1;        }    }    CListLabelElementUI::DoEvent(event);}SIZE CListTextElementUI::EstimateSize(SIZE szAvailable){    TListInfoUI* pInfo = NULL;    if( m_pOwner ) pInfo = m_pOwner->GetListInfo();    SIZE cXY = m_cxyFixed;    if( cXY.cy == 0 && m_pManager != NULL ) {        cXY.cy = m_pManager->GetFontInfo(pInfo->nFont)->tm.tmHeight + 8;        if( pInfo ) cXY.cy += pInfo->rcTextPadding.top + pInfo->rcTextPadding.bottom;    }    return cXY;}void CListTextElementUI::DrawItemText(HDC hDC, const RECT& rcItem){    if( m_pOwner == NULL ) return;    TListInfoUI* pInfo = m_pOwner->GetListInfo();    DWORD iTextColor = pInfo->dwTextColor;    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        iTextColor = pInfo->dwHotTextColor;    }    if( IsSelected() ) {        iTextColor = pInfo->dwSelectedTextColor;    }    if( !IsEnabled() ) {        iTextColor = pInfo->dwDisabledTextColor;    }    IListCallbackUI* pCallback = m_pOwner->GetTextCallback();    //ASSERT(pCallback);    //if( pCallback == NULL ) return;    m_nLinks = 0;    int nLinks = lengthof(m_rcLinks);    for( int i = 0; i < pInfo->nColumns; i++ )    {        RECT rcItem = { pInfo->rcColumn[i].left, m_rcItem.top, pInfo->rcColumn[i].right, m_rcItem.bottom };        rcItem.left += pInfo->rcTextPadding.left;        rcItem.right -= pInfo->rcTextPadding.right;        rcItem.top += pInfo->rcTextPadding.top;        rcItem.bottom -= pInfo->rcTextPadding.bottom;        CDuiString strText;//不使用LPCTSTR,否则限制太多 by cddjr 2011/10/20        if( pCallback ) strText = pCallback->GetItemText(this, m_iIndex, i);        else strText.Assign(GetText(i));        if( pInfo->bShowHtml )            CRenderEngine::DrawHtmlText(hDC, m_pManager, rcItem, strText.GetData(), iTextColor, \                &m_rcLinks[m_nLinks], &m_sLinks[m_nLinks], nLinks, DT_SINGLELINE | pInfo->uTextStyle);        else            CRenderEngine::DrawText(hDC, m_pManager, rcItem, strText.GetData(), iTextColor, \            pInfo->nFont, DT_SINGLELINE | pInfo->uTextStyle);        m_nLinks += nLinks;        nLinks = lengthof(m_rcLinks) - m_nLinks;     }    for( int i = m_nLinks; i < lengthof(m_rcLinks); i++ ) {        ::ZeroMemory(m_rcLinks + i, sizeof(RECT));        ((CDuiString*)(m_sLinks + i))->Empty();    }}/////////////////////////////////////////////////////////////////////////////////////////CListContainerElementUI::CListContainerElementUI() : m_iIndex(-1),m_pOwner(NULL), m_bSelected(false),m_uButtonState(0){}LPCTSTR CListContainerElementUI::GetClass() const{    return _T("ListContainerElementUI");}UINT CListContainerElementUI::GetControlFlags() const{    return UIFLAG_WANTRETURN;}LPVOID CListContainerElementUI::GetInterface(LPCTSTR pstrName){    if( _tcscmp(pstrName, DUI_CTR_LISTITEM) == 0 ) return static_cast<IListItemUI*>(this);if( _tcscmp(pstrName, DUI_CTR_LISTCONTAINERELEMENT) == 0 ) return static_cast<CListContainerElementUI*>(this);    return CContainerUI::GetInterface(pstrName);}IListOwnerUI* CListContainerElementUI::GetOwner(){    return m_pOwner;}void CListContainerElementUI::SetOwner(CControlUI* pOwner){    m_pOwner = static_cast<IListOwnerUI*>(pOwner->GetInterface(_T("IListOwner")));}void CListContainerElementUI::SetVisible(bool bVisible){    CContainerUI::SetVisible(bVisible);    if( !IsVisible() && m_bSelected)    {        m_bSelected = false;        if( m_pOwner != NULL ) m_pOwner->SelectItem(-1);    }}void CListContainerElementUI::SetEnabled(bool bEnable){    CControlUI::SetEnabled(bEnable);    if( !IsEnabled() ) {        m_uButtonState = 0;    }}int CListContainerElementUI::GetIndex() const{    return m_iIndex;}void CListContainerElementUI::SetIndex(int iIndex){    m_iIndex = iIndex;}void CListContainerElementUI::Invalidate(){    if( !IsVisible() ) return;    if( GetParent() ) {        CContainerUI* pParentContainer = static_cast<CContainerUI*>(GetParent()->GetInterface(_T("Container")));        if( pParentContainer ) {            RECT rc = pParentContainer->GetPos();            RECT rcInset = pParentContainer->GetInset();            rc.left += rcInset.left;            rc.top += rcInset.top;            rc.right -= rcInset.right;            rc.bottom -= rcInset.bottom;            CScrollBarUI* pVerticalScrollBar = pParentContainer->GetVerticalScrollBar();            if( pVerticalScrollBar && pVerticalScrollBar->IsVisible() ) rc.right -= pVerticalScrollBar->GetFixedWidth();            CScrollBarUI* pHorizontalScrollBar = pParentContainer->GetHorizontalScrollBar();            if( pHorizontalScrollBar && pHorizontalScrollBar->IsVisible() ) rc.bottom -= pHorizontalScrollBar->GetFixedHeight();            RECT invalidateRc = m_rcItem;            if( !::IntersectRect(&invalidateRc, &m_rcItem, &rc) )             {                return;            }            CControlUI* pParent = GetParent();            RECT rcTemp;            RECT rcParent;            while( pParent = pParent->GetParent() )            {                rcTemp = invalidateRc;                rcParent = pParent->GetPos();                if( !::IntersectRect(&invalidateRc, &rcTemp, &rcParent) )                 {                    return;                }            }            if( m_pManager != NULL ) m_pManager->Invalidate(invalidateRc);        }        else {            CContainerUI::Invalidate();        }    }    else {        CContainerUI::Invalidate();    }}bool CListContainerElementUI::Activate(){    if( !CContainerUI::Activate() ) return false;    if( m_pManager != NULL ) m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMACTIVATE);    return true;}bool CListContainerElementUI::IsSelected() const{    return m_bSelected;}bool CListContainerElementUI::Select(bool bSelect){    if( !IsEnabled() ) return false;    if( bSelect == m_bSelected ) return true;    m_bSelected = bSelect;    if( bSelect && m_pOwner != NULL ) m_pOwner->SelectItem(m_iIndex);    Invalidate();    return true;}bool CListContainerElementUI::IsExpanded() const{    return false;}bool CListContainerElementUI::Expand(bool /*bExpand = true*/){    return false;}void CListContainerElementUI::DoEvent(TEventUI& event){    if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {        if( m_pOwner != NULL ) m_pOwner->DoEvent(event);        else CContainerUI::DoEvent(event);        return;    }    if( event.Type == UIEVENT_DBLCLICK )    {        if( IsEnabled() ) {            Activate();            Invalidate();        }        return;    }    if( event.Type == UIEVENT_KEYDOWN && IsEnabled() )    {        if( event.chKey == VK_RETURN ) {            Activate();            Invalidate();            return;        }    }    if( event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_RBUTTONDOWN )    {        if( IsEnabled() ){            m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMCLICK);            Select();            Invalidate();        }        return;    }    if( event.Type == UIEVENT_BUTTONUP )     {        return;    }    if( event.Type == UIEVENT_MOUSEMOVE )    {        return;    }    if( event.Type == UIEVENT_MOUSEENTER )    {        if( IsEnabled() ) {            m_uButtonState |= UISTATE_HOT;            Invalidate();        }        return;    }    if( event.Type == UIEVENT_MOUSELEAVE )    {        if( (m_uButtonState & UISTATE_HOT) != 0 ) {            m_uButtonState &= ~UISTATE_HOT;            Invalidate();        }        return;    }    // An important twist: The list-item will send the event not to its immediate    // parent but to the "attached" list. A list may actually embed several components    // in its path to the item, but key-presses etc. needs to go to the actual list.    if( m_pOwner != NULL ) m_pOwner->DoEvent(event); else CControlUI::DoEvent(event);}void CListContainerElementUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue){    if( _tcscmp(pstrName, _T("selected")) == 0 ) Select();    else CContainerUI::SetAttribute(pstrName, pstrValue);}void CListContainerElementUI::DoPaint(HDC hDC, const RECT& rcPaint){    if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;    DrawItemBk(hDC, m_rcItem);    CContainerUI::DoPaint(hDC, rcPaint);}void CListContainerElementUI::DrawItemText(HDC hDC, const RECT& rcItem){    return;}void CListContainerElementUI::DrawItemBk(HDC hDC, const RECT& rcItem){    ASSERT(m_pOwner);    if( m_pOwner == NULL ) return;    TListInfoUI* pInfo = m_pOwner->GetListInfo();    DWORD iBackColor = 0;    if( !pInfo->bAlternateBk || m_iIndex % 2 == 0 ) iBackColor = pInfo->dwBkColor;    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        iBackColor = pInfo->dwHotBkColor;    }    if( IsSelected() ) {        iBackColor = pInfo->dwSelectedBkColor;    }    if( !IsEnabled() ) {        iBackColor = pInfo->dwDisabledBkColor;    }    if ( iBackColor != 0 ) {        CRenderEngine::DrawColor(hDC, m_rcItem, GetAdjustColor(iBackColor));    }    if( !IsEnabled() ) {        if( !pInfo->sDisabledImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sDisabledImage) ) pInfo->sDisabledImage.Empty();            else return;        }    }    if( IsSelected() ) {        if( !pInfo->sSelectedImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sSelectedImage) ) pInfo->sSelectedImage.Empty();            else return;        }    }    if( (m_uButtonState & UISTATE_HOT) != 0 ) {        if( !pInfo->sHotImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sHotImage) ) pInfo->sHotImage.Empty();            else return;        }    }    if( !m_sBkImage.IsEmpty() ) {        if( !pInfo->bAlternateBk || m_iIndex % 2 == 0 ) {            if( !DrawImage(hDC, (LPCTSTR)m_sBkImage) ) m_sBkImage.Empty();        }    }    if( m_sBkImage.IsEmpty() ) {        if( !pInfo->sBkImage.IsEmpty() ) {            if( !DrawImage(hDC, (LPCTSTR)pInfo->sBkImage) ) pInfo->sBkImage.Empty();            else return;        }    }    if ( pInfo->dwLineColor != 0 ) {        RECT rcLine = { m_rcItem.left, m_rcItem.bottom - 1, m_rcItem.right, m_rcItem.bottom - 1 };        CRenderEngine::DrawLine(hDC, rcLine, 1, GetAdjustColor(pInfo->dwLineColor));    }}} // namespace DuiLib


原创粉丝点击