Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Удаление выделенной строки CListBox :)


Автор: kometa_triatlon 25.11.2006, 16:30
Мне нужно сделать Листбокс, из которого по нажатию Delete удалялись бы выделенные строки, казалось бы, что сложного. Я вот делал на диалоге кнопку, которая делает это:
Код

void CInputItemsDlg::OnBnClickedDelSelected()
{
    int iSelCount = m_listSequence.GetSelCount();
    int* iSelIndexes = new int[iSelCount];
    m_listSequence.GetSelItems(m_listSequence.GetCount(), iSelIndexes);
    for(int i=0; i < iSelCount; i++)
        m_listSequence.DeleteString(iSelIndexes[i]-i);
    delete [] iSelIndexes;

}


Но кнопка это не совсем то, захотелось дать юзеру возможность работать с помощью delete. Наследовал свой класс от CListBox, создал обработчик:
Код

void CEditableListBox::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if( nChar == VK_DELETE )
        DeleteSelected();

    CListBox::OnKeyUp(nChar, nRepCnt, nFlags);
}

void CEditableListBox::DeleteSelected(void)
{
    int iSelCount = GetSelCount();
    int* iSelIndexes = new int[iSelCount];
    GetSelItems(GetCount(), iSelIndexes);
    for(int i=0; i < iSelCount; i++)
        DeleteString(iSelIndexes[i]-i);
    delete [] iSelIndexes;
}

Но не работает smile Вылетаю с out of memory smile
Отладчик показывает что Symbol "iSelCount" not found, значения его показать не может, в итоге я выделяю непонятно сколько памяти...

Вот сижу и думаю, наверное я в этой жизни что-то делаю не так...

Автор: SergeCpp 25.11.2006, 19:17
GetSelItems( GetSelCount() /* а лучше iSelCount user posted image */, iSelIndexes );

а вообще-то лучше назвать не iSelIndexes, а pSelIndexes...

DeleteString( iSelIndexes[ i ] - i ); // хитроумная конструкция... user posted image

Автор: kometa_triatlon 25.11.2006, 19:48
Ты в курсе, что означают параметры GetSelCount?
Цитата

int GetSelItems(
   int nMaxItems,
   LPINT rgIndex 
) const;

Parameters

nMaxItems 
Specifies the maximum number of selected items whose item numbers are to be placed in the buffer. 

rgIndex 
Specifies a long pointer to a buffer large enough for the number of integers specified by nMaxItems. 

Так что если я хочу, чтобы пользователь мог удалить последнюю строку, то первым параметром мне нужно передавать именно количество всех элементов.

Что касается 
Цитата

DeleteString( iSelIndexes[ i ] - i ); // хитроумная конструкция... 

То она как раз правильная. Пусть пользователь выбрал 3 и 5-ую строки. При проходе по циклу я удалю 3-ю, 5-ая сместится на четвертое место и мне уже надо будет удалить четвертую. Эти строки написаны кровью smile

Не может быть, чтобы кто-то не делал чего-нибудь похожего... Отзовитесь, кто знает!

Автор: SergeCpp 25.11.2006, 19:59
  • Вас не смущает, что размер iSelIndexes is not large enough for holding GetCount() indexes?..
  • Про хитроумность я написал, чтобы предоставить Вам самому возможность догадаться, что удалять лучше с конца...

Автор: kometa_triatlon 25.11.2006, 20:58
Цитата

Вас не смущает, что размер iSelIndexes is not large enough for holding GetCount() indexes?..

??
Ему и не нужно содержать все индексы, только выделенных строк, именно столько памяти я и выделяю...
В первом посте приведен работающий код.

Вся проблема в том, я что прога вылетает на строке:
Код

int* iSelIndexes = new int[iSelCount];

Я пробовал посмотреть под отладкой, сколько же строк выделено, отладчик ругается symbol iSelCount not found.
Пробовал запихнуть в watch GetSelCount(), тоже нифига... 

Автор: SergeCpp 25.11.2006, 21:58
Цитата(kometa_triatlon @  25.11.2006,  22:58 Найти цитируемый пост)
Ему и не нужно содержать все индексы

Цитата(kometa_triatlon @  25.11.2006,  21:48 Найти цитируемый пост)
int GetSelItems(
rgIndex 
Specifies a long pointer to a buffer large enough for the number of integers specified by nMaxItems.

У Вас nMaxItems == GetCount(), что >= выделяемого Вами iSelCount == GetSelCount()

Так и не попробовали?..

Цитата(SergeCpp @  25.11.2006,  21:17 Найти цитируемый пост)
GetSelItems( GetSelCount() /* а лучше iSelCount  */, iSelIndexes );

а вообще-то лучше назвать не iSelIndexes, а pSelIndexes...


Автор: kometa_triatlon 25.11.2006, 22:23
Попробовал, ничего не дало, что неудивительно, ведь до той строки даже не доходит, вылетает при выделении памяти.
Что касается large enough for the number of integers specified by nMaxItems, то как показывает практика, все равно, что передавать в качестве первого аргумента: GetCount или GetSelCount. Правильней наверное GetSelCount, но это моей проблемы мало касается...


Попробовал еще так:
Код

CArray<int,int> arrSelIndexes;
    arrSelIndexes.SetSize(GetSelCount());

    GetSelItems(GetSelCount(), arrSelIndexes.GetData());
    for(int i = GetSelCount()-1; i >= 0; i--)
        DeleteString(arrSelIndexes[i]);

после выполнения
GetSelItems(GetSelCount(), arrSelIndexes.GetData());
Размер массива становится равным -1....
Что за бред, почему я не могу внутри наследованного класса узнать количество выделенных строк?

Автор: Earnest 27.11.2006, 16:02
1) Чтобы отладчик показывал значения переменных, убедись, что у тебя нормальная debug-версия.
2) Или, в конце концов распечатай значение nSelCount с помощью TRACE. Наверняка дело в нем. Т.е. он либо 0, либо -1. 
3) Поставь проверку if (nSelCount > 0), т.к. часто попытка выделить 0 байтов именно Out of memory и заканчивается.

Добавлено @ 16:05 
Причиной того, что iSelCount=-1, может быть неправильный тип листбокса:
Цитата

If the list box is a single-selection list box, the return value is LB_ERR.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)