void CWeightHorizontalLayoutUI::SetPos(RECT rc) { CControlUI::SetPos(rc); rc = m_rcItem; std::map<CControlUI*, int /*width*/> mapAjust; // 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_items.GetSize() == 0) { PRocessScrollBar(rc, 0, 0); return; } if (!m_bScrollFloat && m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible()) rc.right -= m_pVerticalScrollBar->GetFixedWidth(); if (!m_bScrollFloat && m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight(); ResetWeightDisplayControlState(); // 讀取當(dāng)前子控件的權(quán)重 m_mapWeight.clear(); for (int i = 0; i < m_items.GetSize(); i++) { DuiLib::CControlUI* pControl = static_cast<DuiLib::CControlUI*>(m_items[i]); if (pControl == nullptr) continue; CStdString strweight = pControl->GetCustomAttribute(L"weight"); int nweight = _ttoi(strweight.GetData()); m_mapWeight[i] = nweight; } m_mapWeightCache = m_mapWeight; // 查找最小權(quán)重控件 auto HideMinWeigth = [&](int index) -> bool { CControlUI* pControl = static_cast<CControlUI*>(m_items[index]); if (pControl && pControl->IsVisible()) { pControl->SetInternVisible(false); m_arrWeightHideControl.push_back(pControl); return true; } return false; }; // Determine the width of elements that are sizeable SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top }; if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) szAvailable.cx += m_pHorizontalScrollBar->GetScrollRange(); int nAdjustables = 0; int cxFixed = 0; int nEstimateNum = 0; int cxExpand = 0; std::pair<int, int> min_weight; // first:control index, second:weight std::map<CControlUI*, int /*width*/> m_mapEstimateWidth; // 試算時(shí)控件的預(yù)設(shè)寬度 std::map<CControlUI*, int /*width*/> m_mapBookWidth; do { // 查找出當(dāng)前權(quán)重值最小,并且顯示著的控件 min_weight = std::make_pair(999, 999); std::for_each(m_mapWeight.begin(), m_mapWeight.end(), [&](std::pair<int, int> item)-> void { CControlUI* pControl = static_cast<CControlUI*>(m_items[item.first]); if (item.second <= min_weight.second && pControl->IsVisible()) min_weight = item; }); // 已經(jīng)找到后從map中移除,以避免下次查找的還是這個(gè)控件 auto min_it = std::find_if(m_mapWeight.begin(), m_mapWeight.end(), [min_weight](std::pair<int, int> item)-> bool { return (item.first == min_weight.first && item.second == item.second); }); if (min_it != m_mapWeight.end()) m_mapWeight.erase(min_it); // 試算中 nAdjustables = 0; cxFixed = 0; nEstimateNum = 0; for (int it1 = 0; it1 < m_items.GetSize(); it1++) { CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]); if (pControl->IsFloat()) continue; if (!pControl->IsVisible()) continue; SIZE sz = pControl->EstimateSize(szAvailable); if (sz.cx == 0) { nAdjustables++; } else { if (sz.cx < pControl->GetMinWidth()) sz.cx = pControl->GetMinWidth(); if (sz.cx > pControl->GetMaxWidth()) sz.cx = pControl->GetMaxWidth(); } m_mapEstimateWidth[pControl] = sz.cx; cxFixed += sz.cx + pControl->GetPadding().left + pControl->GetPadding().right; nEstimateNum++; } cxFixed += (nEstimateNum - 1) * m_iChildPadding; cxExpand = 0; if (nAdjustables > 0) cxExpand = max(0, (szAvailable.cx - cxFixed) / nAdjustables);// 此處下節(jié)解釋 // 如果小于空間不夠,先嘗試從低到高縮減帶有adjust屬性的控件 if (szAvailable.cx - cxFixed < 0) { std::vector<std::pair<CControlUI*, int>> adj_ctrls; for (int it1 = 0; it1 < m_items.GetSize(); it1++) { CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]); if (pControl->IsFloat()) continue; //if (!pControl->IsVisible()) continue; if (pControl->GetCustomAttribute(L"adjustwidth") == NULL || _tcscmp(pControl->GetCustomAttribute(L"adjustwidth"), L"true")) continue; adj_ctrls.push_back(std::make_pair(pControl, m_mapWeightCache[it1])); } // 自小到大按權(quán)重,先嘗試最小權(quán)重 std::sort(adj_ctrls.begin(), adj_ctrls.end(), [&](std::pair<CControlUI*, int> lhs, std::pair<CControlUI*, int> rhs) -> bool { return lhs.second < rhs.second; }); for (auto it = adj_ctrls.begin(); it != adj_ctrls.end(); it++) { auto ctrl = it->first; if (m_mapEstimateWidth[ctrl] > ctrl->GetMinWidth()) { int sub_width = min(abs(szAvailable.cx - cxFixed), m_mapEstimateWidth[ctrl] - ctrl->GetMinWidth()); m_mapEstimateWidth[ctrl] = m_mapEstimateWidth[ctrl] - sub_width; // 新的試算寬度 m_mapBookWidth[ctrl] = m_mapEstimateWidth[ctrl]; cxFixed -= sub_width; if (szAvailable.cx - cxFixed >= 0) break; // 已經(jīng)滿足排列空間 } } } // 空間不夠,從權(quán)重最小的依次隱藏 } while (szAvailable.cx - cxFixed < 0 && HideMinWeigth(min_weight.first)); // Position the elements SIZE szRemaining = szAvailable; int iposX = rc.left; if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) { iPosX -= m_pHorizontalScrollBar->GetScrollPos(); } int iAdjustable = 0; int cxFixedRemaining = cxFixed; 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.cx -= rcPadding.left; SIZE sz = pControl->EstimateSize(szRemaining); if (sz.cx == 0) { iAdjustable++; sz.cx = cxExpand; //最后一個(gè)自適應(yīng)尺寸大小無(wú)需另行計(jì)算 //if( iAdjustable == nAdjustables ) { // sz.cx = MAX(0, szRemaining.cx -cxFixedRemaining); //} 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(); //padding不算控件寬度//2012/09/12 //RECT rcCtrl = { iPosX + rcPadding.left, rc.top + rcPadding.top, iPosX + sz.cx + rcPadding.left + rcPadding.right, rc.top + rcPadding.top + sz.cy}; if (m_mapBookWidth.find(pControl) != m_mapBookWidth.end() && m_mapBookWidth[pControl] != sz.cx) { sz.cx = m_mapBookWidth[pControl]; } RECT rcCtrl = { iPosX + rcPadding.left, rc.top + rcPadding.top, min(iPosX + sz.cx + rcPadding.left, rc.right) , rc.top + rcPadding.top + sz.cy }; pControl->SetPos(rcCtrl); iPosX += sz.cx + m_iChildPadding + rcPadding.left + rcPadding.right; szRemaining.cx -= sz.cx + m_iChildPadding + rcPadding.right; if (m_bWholeDisplay && rcCtrl.right > rc.left + szAvailable.cx) m_arrWholeDisplayControl.push_back(pControl); } // Process the scrollbar ProcessScrollBar(rc, 0, 0); }以上代碼主要是在試算過(guò)程中,在剩余的空間寬度不足時(shí)隱藏一下最小的權(quán)重控件,再次試算一遍需要留心的是當(dāng)Hide時(shí)不能夠直接調(diào)用子控件的SetVisible接口,這樣會(huì)改變控件的基礎(chǔ)狀態(tài),而應(yīng)使用SetInternVisible,并且在再次SetPos時(shí),清除這樣的記錄,并將狀態(tài)重置,這樣,不影響再次的試算過(guò)程。基本以上實(shí)現(xiàn)了控制欄的自定義隱藏順序。而我們只需要在xml文件中配置一下各個(gè)控件的權(quán)重即可。實(shí)現(xiàn)效果:
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注