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を以下のように変更します.
hot関数を追加するには:
SelectItem関数の実装を変更するには、次の手順に従います.
次の関数を追加します.
● UIList.h class IListOwnerUIに虚関数を追加する:
class IListItemUIでselect関数の宣言を置き換えます.
class UILIB_でAPI CListUIに関数宣言を追加:
class UILIB_でAPI CListElementUIでの関数宣言の変更:
class UILIB_でAPI CListContainerElementUIでの変更宣言:
● UICombo.cpp追加関数実装:
● UICombo.h関数宣言を追加する:
Ctrl+左ボタンを複数選択し、Ctrlボタンを押してクリックすると、主に3つのケースがあります.
総括分析:ctrlが押された場合、クリックすると、前の(一部)の選択項目が選択状態を失うことはなく、現在クリックした項目が選択状態を変更し、現在の項目に焦点を合わせるだけです.
shift+左ボタン、主に4つのケースがあります
総括分析: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