Duilib中list控件支持ctrl和shif多行选中的实现

一、 由于diulib不支持list控件的多选修改。下面是修改的原理。

Ctrl+左键多选,按下Ctrl键点击,主要有三种情况:

  • 选中一个
  • 再点击,又选中一个
  • 再点击前一个,前一个选中状态消失

总结分析:ctrl按下的情况,点击,不会使前一个(一部分)选中项失去选中状态,而只是让当前点击的项改变选中状态,并将焦点移到当前项。

shift+左键,主要有4中情况

  • 点击选中一个(ID为2),向下选中一个(ID为5),则2-5被选中

  • 再向下选中一个(ID为10),则2-10被选中

  • 向上选中一个(ID为8),则2-8被选中

  • 向上选中一个(ID为1),则1-2被选中。

总结分析:shift按下的情况,点击,是选中一个范围,起始项为焦点所在的项,shift点击的项为结束项。

二、代码修改

UIList.cpp将Select修改如下:

bool CListElementUI::Select(bool bSelect, bool bCallback)
{BOOL bShift = (GetKeyState(VK_SHIFT) & 0x8000);BOOL bCtrl = (GetKeyState(VK_CONTROL) & 0x8000);if (!IsEnabled()) return false;//if( bSelect == m_bSelected ) return true;if (bCtrl) {m_bSelected = !m_bSelected;}else {m_bSelected = bSelect;}if (m_bSelected == false) {Hot(false);}else {Hot(true);}if (bCallback && m_pOwner != NULL) {if (bShift) {m_pOwner->SelectRange(m_iIndex);}else {m_pOwner->SelectItem(m_iIndex);}}Invalidate();return true;
}

添加hot函数:

bool CListElementUI::Hot(bool bHot)
{if (!IsEnabled()) return false;if (bHot){m_uButtonState |= UISTATE_HOT;}else {if ((m_uButtonState & UISTATE_HOT) != 0) {m_uButtonState &= ~UISTATE_HOT;}}//m_pOwner->HotItem(m_iIndex, bHot);Invalidate();return true;
}

修改SelectItem函数的实现:

bool CListUI::SelectItem(int iIndex, bool bTakeFocus)
{BOOL bCtrl = (GetKeyState(VK_CONTROL) & 0x8000);//if( iIndex == m_iCurSel ) return true; //int iTempSel = -1;// We should first unselect the currently selected item if (!bCtrl) {//if( m_iCurSel >= 0 ) { for (int i = 0;i < GetCount();i++) {if (i != iIndex) {CControlUI* pControl = GetItemAt(i);if (pControl != NULL) {IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));if (pListItem != NULL) {if (pListItem->IsSelected()) {pListItem->Select(false,false);}}}}}m_iCurSel = -1;//} }if (iIndex == m_iCurSel) return true;int iOldSel = m_iCurSel;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 (!bCtrl) {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;
}

添加下面的函数:

bool CListUI::SelectRange(int iIndex, bool bTakeFocus)
{int i = 0;int iFirst = m_iCurSel;int iLast = iIndex;int iCount = GetCount();if (iFirst == iLast) return true;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;if (!pListItem->Select(true,false)) {m_iCurSel = -1;return false;}EnsureVisible(iIndex);if (bTakeFocus) pControl->SetFocus();if (m_pManager != NULL) {m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMSELECT, iIndex, m_iCurSel);}//locate (and select) either first or last// (so order is arbitrary)while (i < iCount) {if (i == iFirst || i == iLast) {i++;break;}CControlUI* pControl = GetItemAt(i);if (pControl != NULL) {IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));if (pListItem != NULL) pListItem->Select(false, false);}i++;}// select rest of rangewhile (i < iCount) {CControlUI* pControl = GetItemAt(i);if (pControl != NULL) {IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));if (pListItem != NULL) pListItem->Select(true, false);}if (i == iFirst || i == iLast) {i++;break;}i++;}// unselect rest of rangewhile (i < iCount) {CControlUI* pControl = GetItemAt(i);if (pControl != NULL) {IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));if (pListItem != NULL) pListItem->Select(false, false);}i++;}return true;
}

● UIList.h在class IListOwnerUI中添加虚函数:

virtual bool SelectRange(int iIndex, bool bTakeFocus = false) = 0;//@xdrt81y@20140218@支持shift多选

在class IListItemUI中替换select函数的声明:

virtual bool Select(bool bSelect = true, bool bCallback = true) = 0;

在class UILIB_API CListUI中添加函数声明:

bool SelectRange(int iIndex, bool bTakeFocus = false);//@xdrt81y@20140218@支持shift多选

在class UILIB_API CListElementUI中修改函数声明:

bool Select(bool bSelect = true, bool bCallback = true);

在class UILIB_API CListContainerElementUI中修改声明:

bool Select(bool bSelect = true, bool bCallback = true);

● UICombo.cpp添加函数实现:

bool CComboUI::SelectRange(int iIndex, bool bTakeFocus)
{return true;
}

● UICombo.h添加函数声明:

bool SelectRange(int iIndex, bool bTakeFocus = false);//@xdrt81y@20140218

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击下方“内容举报”进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部