#ifndef __UILIST_H__ #define __UILIST_H__ #pragma once #include "Layout/UIVerticalLayout.h" #include "Layout/UIHorizontalLayout.h" namespace DuiLib { ///////////////////////////////////////////////////////////////////////////////////// // class CListHeaderUI; #define UILIST_MAX_COLUMNS 32 typedef 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; else rcSeparator.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; else rcSeparator.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/20 pText->Assign(pstrText); else m_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