在项目中遇到一个 CListUI的显示问题.
* 先建立一个CListUI, 因为暂时符合显示条件,不允许显示, 先隐藏.
/// create dlg have a LitUI
if (NULL == m_pDlgHaveListUI)
{
m_pDlgHaveListUI = new CDlgHaveListUI(XML_FILE_NAME_DlgHaveListUI, WND_CLASS_NAME_DlgHaveListUI);
if (NULL == m_pDlgHaveListUI)
break;
m_pDlgHaveListUI->SetOwner(this);
m_pDlgHaveListUI->Create(this->GetHWND(), WND_DISP_NAME_DlgHaveListUI, UI_WNDSTYLE_CHILD, WS_EX_WINDOWEDGE);
UiInit_List(); ///< initial m_pDlgHaveListUI's ListUI
m_pDlgHaveListUI->ShowWindow(false, false); ///< 不符合显示条件,先隐藏.
AddSubDlgOnMainDlg(m_pDlgHaveListUI); ///< 将new出来的DuiLib对象放入List, delete时用
}
就等于是 : 必须要使ListUI抖一下, size变了才刷新成正常显示.
最后,我改了DuiLib库来解决这个问题. 在 CListUI::SetPos 中调用 NeedUpdate(), 就能达到不变化size, 进行刷新ListUI的目的.
修改后的UIList.h
class UILIB_API CListUI : public CVerticalLayoutUI, public IListUI
{
public:
CListUI();
LPCTSTR GetClassName() const;
UINT GetControlFlags() const;
LPVOID GetInterface(LPCTSTR pstrName);
bool GetScrollSelect();
void SetScrollSelect(bool bScrollSelect);
int GetCurSel() const;
void SetCurSel(int iSel);
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);
BOOL rect_compare(const RECT& rtDst, const RECT& rtSrc);
void rect_copy(RECT& rtDst, const RECT& rtSrc);
virtual BOOL 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;
BOOL SortItems(PULVCompareFunc pfnCompare, UINT_PTR dwData);
protected:
bool m_bScrollSelect;
int m_iCurSelect;
int m_iExpandedItem;
IListCallbackUI* m_pCallback;
CListBodyUI* m_pList;
CListHeaderUI* m_pHeader;
TListInfoUI m_ListInfo;
/// 我们会在SetPos中, 调用NeedUpdate
/// 为了防止递归调用, 如果 SetPos's rc != m_rcLastSetPos, 就调用一次NeedUpdate来刷新UI
/// 用来解决ListUI由隐藏变到显示时,设置了UI行元素,不显示或显示为灰的问题.
RECT m_rcLastSetPos; ///< 最后一次设置的Pos
};
namespace DuiLib
{
CListUI::CListUI() :
m_pCallback(NULL),
m_bScrollSelect(false),
m_iCurSelect(-1),
m_iExpandedItem(-1)
{
::ZeroMemory(&m_rcLastSetPos, sizeof(RECT));
BOOL CListUI::rect_compare(const RECT& rtDst, const RECT& rtSrc)
{
BOOL bRc = FALSE;
do
{
if (rtSrc.left != rtDst.left)
break;
if (rtSrc.top != rtDst.top)
break;
if (rtSrc.right != rtDst.right)
break;
if (rtSrc.bottom != rtDst.bottom)
break;
bRc = TRUE;
} while (0);
return bRc;
}
void CListUI::rect_copy(RECT& rtDst, const RECT& rtSrc)
{
rtDst.left = rtSrc.left;
rtDst.top = rtSrc.top;
rtDst.right = rtSrc.right;
rtDst.bottom = rtSrc.bottom;
}
void CListUI::SetPos(RECT rc)
{
CVerticalLayoutUI::SetPos(rc);
if( m_pHeader == NULL )
return;
if (rect_compare(m_rcLastSetPos, rc))
return;
else
{
rect_copy(m_rcLastSetPos, rc);
}
// 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(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(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(m_pHeader->GetItemAt(it))->SetInternVisible(false);
}
}
NeedUpdate();
}
<2015-0311>
这几天发现,上述的修改导致拖动ListUI题头时, List's Body不随动.
想了一下, NeedUpdate()的条件判断应放在函数最后面。修改后好了.
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(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(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(m_pHeader->GetItemAt(it))->SetInternVisible(false);
}
}
/// 如果size变了, 刷一下
/// 用来解决 hide => show 时, ListUI不显示或为灰色
if (!rect_compare(m_rcLastSetPos, rc))
{
rect_copy(m_rcLastSetPos, rc);
NeedUpdate();
}
}