CListContainerElementUI 没有实现setpos。而是调用CContainerUI的SetPos(),从而导致了元素排版不正确。如果重写CListContainerElementUI的setpos则会导致CtreeUI的问题。解决方法:
Step One:
新建类CListContainerElementUIEx,来实现setpos。此时虽然排版正确了,但在拖动滚动条时,可能导致排版不正确。
class UILIB_API CListContainerElementUIEx:public CListContainerElementUI { public: CListContainerElementUIEx(); virtual void Invalidate(); virtual void SetPos(RECT rc); };
成员实现:
CListContainerElementUIEx::CListContainerElementUIEx() { } void CListContainerElementUIEx::SetPos(RECT rc) { CContainerUI::SetPos(rc); rc = m_rcItem; rc.left += m_rcInset.left; rc.top += m_rcInset.top; rc.right -= m_rcInset.right; rc.bottom -= m_rcInset.bottom; TListInfoUI *plistinfo = GetOwner()->GetListInfo(); SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top }; 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(); SIZE sz = pControl->EstimateSize(szAvailable); if( sz.cx == 0 ) { if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth(); if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth(); } else { if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth(); if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth(); } sz.cy = pControl->GetFixedHeight(); if( sz.cy == 0 ) sz.cy = rc.bottom - rc.top - rcPadding.top - rcPadding.bottom; if( sz.cy < 0 ) sz.cy = 0; if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight(); if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight(); RECT rcCtrl = { plistinfo->rcColumn[it2].left + rcPadding.left, rc.top + rcPadding.top, plistinfo->rcColumn[it2].right + rcPadding.left, rc.top + sz.cy + rcPadding.top + rcPadding.bottom }; pControl->SetPos(rcCtrl); } } void CListContainerElementUIEx::Invalidate() { CListContainerElementUI::Invalidate(); }
Step two:
在UIDefine.h文件中定义:
#define DUI_CTR_LISTCONTAINERELEMENTEX (_T("ListContainerElementEx"))
在CDialogBuilder的_Parse方法中添加以下代码:
case 22: if( _tcscmp(pstrClass,DUI_CTR_LISTCONTAINERELEMENTEX) == 0 ) pControl = new CListContainerElementUIEx; break;
Step three:
在实现DuiLib::WindowImplBase类中添加以下方法,目的修复滚动条导致的排版不正确:
LRESULT XOnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT XOnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) ;
(例如CListWnd类):
class CListWnd :public DuiLib::WindowImplBase, public DuiLib::IListCallbackUI,public DuiLib::IDialogBuilderCallback { public: virtual LPCTSTR GetItemText(DuiLib::CControlUI* pList, int iItem, int iSubItem); CListWnd(); ~CListWnd(void); virtual void InitWindow(); virtual void Notify(DuiLib::TNotifyUI& msg); virtual LPCTSTR GetWindowClassName() const; // virtual DuiLib::CDuiString GetSkinFolder(); virtual DuiLib::CDuiString GetSkinFile();/**/ virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); virtual LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); virtual DuiLib::UILIB_RESOURCETYPE GetResourceType() const; DWORD GetBkColor(); void SetBkColor(DWORD dwBackColor); virtual LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); DuiLib::CControlUI* FindControlByName(CString Name); DuiLib::CListUI* m_pListUi; void OnFinalMessage( HWND hWnd ); void NeedUpdate(); /****添加方法***/ LRESULT XOnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT XOnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) ; protected: CString m_strSkinFolder; CString m_strSkinFile; DuiLib::CTreeNodeUI* m_pNodeNeedMove; DuiLib::CControlUI* m_pDragingCtrl; CString WndName; };
实现:
#include "StdAfx.h" #include "ListWnd.h" #include <list> struct SkinChangedParam { DWORD bkcolor; DuiLib::CDuiString bgimage; }; const TCHAR* const kBackgroundControlName = _T("bg"); CListWnd::CListWnd() { } CListWnd::~CListWnd(void) { } LPCTSTR CListWnd::GetItemText(DuiLib::CControlUI* pList, int iItem, int iSubItem) { return "SSS"; } void CListWnd::InitWindow(){ }; void CListWnd::Notify(DuiLib::TNotifyUI& msg){ } LPCTSTR CListWnd::GetWindowClassName() const { return _T("CListWnd"); } DuiLib::CDuiString CListWnd::GetSkinFolder() { return (DuiLib::CDuiString)m_strSkinFolder; } DuiLib::CDuiString CListWnd::GetSkinFile() { return m_strSkinFile; } LRESULT CListWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT Ok=0; BOOL bHandled =true; if(uMsg ==WM_LBUTTONUP) Ok=XOnLButtonUp(uMsg, wParam, lParam, bHandled); /**/ if(uMsg ==WM_MOUSEMOVE) Ok=XOnMouseMove(uMsg, wParam, lParam, bHandled); /**/ return WindowImplBase::HandleMessage(uMsg,wParam, lParam); } //WM_LBUTTONUP消息处理函数 LRESULT CListWnd::XOnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; DuiLib::CControlUI* pNewHover =this->m_PaintManager.FindControl(pt); if(pNewHover!=NULL) { CString abcd=pNewHover->GetClass(); if(abcd!=_T("ScrollBarUI")) return 0; DuiLib::CControlUI* pParent=pNewHover->GetParent(); if(pParent!=NULL) { CString name=pParent->GetClass(); pParent=pParent->GetParent(); name=pParent->GetClass(); if(name==_T("ListUI")) { m_pListUi->SetPos(m_pListUi->GetPos()); } } } return 0; } //WM_MOUSEMOVE消息处理函数 LRESULT CListWnd::XOnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if(!(wParam&MK_LBUTTON)) return 0; POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; DuiLib::CControlUI* pNewHover =this->m_PaintManager.FindControl(pt); if(pNewHover!=NULL) { CString abcd=pNewHover->GetClass(); if(abcd!=_T("ScrollBarUI")) return 0; DuiLib::CControlUI* pParent=pNewHover->GetParent(); if(pParent!=NULL) { CString name=pParent->GetClass(); pParent=pParent->GetParent(); name=pParent->GetClass(); if(name==_T("ListUI")) { m_pListUi->SetPos(m_pListUi->GetPos()); } } } return 0; } LRESULT CListWnd::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { #if defined(WIN32) && !defined(UNDER_CE) BOOL bZoomed = ::IsZoomed(m_hWnd); LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam); if (::IsZoomed(m_hWnd) != bZoomed) { } #else return __super::OnSysCommand(uMsg, wParam, lParam, bHandled); #endif return 0; } DuiLib::UILIB_RESOURCETYPE CListWnd::GetResourceType() const { return DuiLib::UILIB_FILE; } DWORD CListWnd::GetBkColor() { DuiLib::CControlUI* background = m_PaintManager.FindControl(kBackgroundControlName); if (background != NULL) return background->GetBkColor(); return 0; } void CListWnd::SetBkColor(DWORD dwBackColor) { DuiLib::CControlUI* background = m_PaintManager.FindControl(kBackgroundControlName); if (background != NULL) { background->SetBkImage(_T("")); background->SetBkColor(dwBackColor); background->NeedUpdate(); SkinChangedParam param; param.bkcolor = background->GetBkColor(); param.bgimage = background->GetBkImage(); //skin_changed_observer_.Broadcast(param); } } LRESULT CListWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 1; } void CListWnd::OnFinalMessage( HWND hWnd ) { WindowImplBase::OnFinalMessage(hWnd); delete this; } DuiLib::CControlUI* CListWnd::FindControlByName(CString Name) { return this->m_PaintManager.FindControl(Name); } CString CListWnd::GetWndName() { return this->WndName; } void CListWnd::NeedUpdate(){ /**用以刷新**/ RECT rcClient; ::GetClientRect(GetHWND(), &rcClient); if( !::IsRectEmpty(&rcClient) ) { this->m_PaintManager.GetRoot()->SetPos(rcClient); } }
效果图: