// *.h
CListCtrl m_listView; // окно списка "Сертификаты"
LV_ITEM *m_lvItem; // структура класса CListCtrl - просмотровое окно списка "Сертификаты"
// *.cpp
void COttsView::CreateCertificatesLV()
{
.........
// Координаты и размеры просмотрового окна списка
m_listView.Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER |
LBS_NOTIFY | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
CRect(0, 0, appRect.Width() - 4, appRect.Height() - 4), this, IDC_MAIN_LV); // просмотровое окно списка
// Формируем колонки
LV_COLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 150;
lvColumn.iSubItem = 0;
lvColumn.pszText = "№ сертификата";
m_listView.InsertColumn(0, &lvColumn);
lvColumn.cx = 110; lvColumn.iSubItem = 1; lvColumn.pszText = "Объект";
m_listView.InsertColumn(1, &lvColumn);
lvColumn.cx = 100; lvColumn.iSubItem = 2; lvColumn.pszText = "Шасси";
m_listView.InsertColumn(2, &lvColumn);
lvColumn.cx = 80; lvColumn.iSubItem = 3; lvColumn.pszText = "Срок действия";
m_listView.InsertColumn(3, &lvColumn);
lvColumn.cx = 75; lvColumn.iSubItem = 4; lvColumn.pszText = "Тип";
m_listView.InsertColumn(4, &lvColumn);
lvColumn.cx = 150; lvColumn.iSubItem = 5; lvColumn.pszText = "Примечание";
m_listView.InsertColumn(5, &lvColumn);
FillListView(); // заполняем список строками
.........
}
void COttsView::FillListView()
{
m_lvItem->mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
m_lvItem->state = 0;
m_lvItem->stateMask = 0;
m_listView.SetItemCount(m_pSet->GetRecordCount() + 1); // для лучшего перераспределения памяти
int i = 0;
while ( !m_pSet->IsEOF() )
{
AddOrChangeItem(TRUE, i); // добавляем в таблицу строку и заполняем ее
m_pSet->MoveNext();
i++;
}
.........
}
void COttsView::AddOrChangeItem(BOOL bIsAdd, int itemNum)
{
.........
// ID
m_lvItem->iItem = itemNum;
m_lvItem->iSubItem = 0;
m_lvItem->pszText = "000";
m_listView.SetItem(m_lvItem);
/*!!*/ m_listView.InsertItem(m_lvItem); // !!!!!! вылетает здесь на 32-м цикле !!!!!!
// Объект сертификации
m_listView.SetItemText(itemNum, 1, "111");
// Шасси
m_listView.SetItemText(itemNum, 2, "222");
// Срок действия
m_listView.SetItemText(itemNum, 3, "333");
// Тип сертификата (ОТТС/ сертификат)
m_listView.SetItemText(itemNum, 4, "444");
// Примечание
m_listView.SetItemText(itemNum, 5, "555");
.........
}
CListCtrl: при добавлении 32-го элемента вылетает
Код такой (место вылета обозначено "/*!!*/"):
class CCoaDlg
{
...
CMyDoc *m_pDocument;
CListCtrl CoaList;
bool Filling;
...
};
BOOL CCoaDlg::OnInitDialog()
{
CDialog::OnInitDialog();
Filling = true;
CoaList.InsertColumn(0, "ФИО", LVCFMT_LEFT, 192, 0);
CoaList.InsertColumn(1, "Звание", LVCFMT_LEFT, 224, 1);
if (!m_pDocument->CoaSet.IsEmpty())
{
m_pDocument->CoaSet.MoveFirst();
int i = 0;
do
{
CoaList.InsertItem(LVIF_TEXT | LVIF_STATE, i, m_pDocument->CoaSet.m_coaSurname + ' ' + m_pDocument->CoaSet.m_coaInitials,
m_pDocument->CoaSet.m_coaID == m_coaID ? LVIS_SELECTED : 0, LVIS_SELECTED, 0, 0);
CoaList.SetItemData(i, m_pDocument->CoaSet.m_coaID);
CoaList.SetItemText(i, 1, m_pDocument->CoaSet.m_coaTitle);
m_pDocument->CoaSet.MoveNext();
i++;
}
while (!m_pDocument->CoaSet.IsEOF());
m_pDocument->CoaSet.FindPrimary(m_coaID);
}
Filling = false;
return TRUE;
}
Вообще, приведенный в моем вопросе код (вернее, его суть) я уже использовал в другом приложении, и там все работает...
Цитата:
Originally posted by Doomych
Попробовал. Все равно вылетает. И тоже на InsertItem(), и тоже на 32-й строке. Чудеса, типа.
Вообще, приведенный в моем вопросе код (вернее, его суть) я уже использовал в другом приложении, и там все работает...
Попробовал. Все равно вылетает. И тоже на InsertItem(), и тоже на 32-й строке. Чудеса, типа.
Вообще, приведенный в моем вопросе код (вернее, его суть) я уже использовал в другом приложении, и там все работает...
Значит причина не в коде, т.к. у меня все тоже великолепно работает. Попробуй создать заново проект -- бывают глюки. Или вирус у тебя. В общем причина где-то рядом.
Ладно, по-порядку. Создание проекта заново не помогло. Проблема оказалась в другом: Сообщения окну списка я обрабатывал в OnNotify().
Код:
BOOL COttsView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if ( m_bIsDBOpen == false ) // если БД не была открыта
return CFormView::OnNotify(wParam, lParam, pResult);
LV_DISPINFO* lv_dispInfo = (LV_DISPINFO*) lParam;
NMLVKEYDOWN* nmlvKeyDown = (NMLVKEYDOWN*) lParam; // для отлова нажатия клавиш
......
// Двойной клик на строке или нажатие F2 или Пробела
if ( lv_dispInfo->hdr.code == LVN_ITEMACTIVATE || nmlvKeyDown->wVKey == VK_F2 ||
nmlvKeyDown->wVKey == VK_SPACE )
{
......
}
// Нажатие Delete
if ( nmlvKeyDown->wVKey == VK_DELETE )
{
......
}
......
return CFormView::OnNotify(wParam, lParam, pResult);
}
{
if ( m_bIsDBOpen == false ) // если БД не была открыта
return CFormView::OnNotify(wParam, lParam, pResult);
LV_DISPINFO* lv_dispInfo = (LV_DISPINFO*) lParam;
NMLVKEYDOWN* nmlvKeyDown = (NMLVKEYDOWN*) lParam; // для отлова нажатия клавиш
......
// Двойной клик на строке или нажатие F2 или Пробела
if ( lv_dispInfo->hdr.code == LVN_ITEMACTIVATE || nmlvKeyDown->wVKey == VK_F2 ||
nmlvKeyDown->wVKey == VK_SPACE )
{
......
}
// Нажатие Delete
if ( nmlvKeyDown->wVKey == VK_DELETE )
{
......
}
......
return CFormView::OnNotify(wParam, lParam, pResult);
}
Так вот. При числе записей более 32 нажатие пробела (VK_SPACE) обрабатывается не только при, собственно, нажатии, но и еще в каких-то неподходящих ситуациях. Кстати, аналогичная ситуация беда обнаружилась и с VK_DELETE (пришлось для него назначить акселератор).
Если кто-то может прокомментировать, пишите!
В общем, я обрабатывал нажатия конкретных клавиш при каждом срабатывании OnNotify(), а надо - только при сообщении LVN_KEYDOWN.
Например, вместо
Код:
// Нажатие Delete
if ( nmlvKeyDown->wVKey == VK_DELETE )
{
......
}
if ( nmlvKeyDown->wVKey == VK_DELETE )
{
......
}
надо писать:
Код:
// Нажатие Delete
if ( nmlvKeyDown->wVKey == LVN_KEYDOWN && nmlvKeyDown->wVKey == VK_DELETE )
{
......
}
if ( nmlvKeyDown->wVKey == LVN_KEYDOWN && nmlvKeyDown->wVKey == VK_DELETE )
{
......
}