Duilibのlistコントロールはctrlとshifの複数行選択の実現をサポートする

33606 ワード

一、diulibはlistコントロールの多選択修正をサポートしていないため.次は修正の原理です.
Ctrl+左ボタンを複数選択し、Ctrlボタンを押してクリックすると、主に3つのケースがあります.
  • を選択
  • をクリックし、
  • を選択します.
  • 前をクリックすると、前の選択状態が
  • 消えます.
    総括分析:ctrlが押された場合、クリックすると、前の(一部)の選択項目が選択状態を失うことはなく、現在クリックした項目が選択状態を変更し、現在の項目に焦点を合わせるだけです.
    shift+左ボタン、主に4つのケースがあります
  • クリックで1つ(IDが2)を選択し、次に1つ(IDが5)を選択すると、2-5が
  • に選択される.
  • がさらに1つ下に選択すると(IDは10)、2-10が
  • に選択される.
  • が1つ上に選択すると(IDは8)、2-8が
  • に選択される.
  • を1つ上に選択すると(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 range
        while (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 range
        while (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