BOOL CDbView::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if(message == WM_NOTIFY) { NMHDR* phdr = (NMHDR*)lParam; // these 3 notifications are only sent by virtual listviews switch(phdr->code) { case LVN_GETDISPINFO: { NMLVDISPINFO* pLvdi; pLvdi = (NMLVDISPINFO*)lParam; GetDispInfo(&pLvdi->item); } void CDbView::GetDispInfo(LVITEM* pItem) { if (!m_dSource.IsOpen()) { return; } //if the recordset is empty, we display a notification label for the user if (pItem->iItem == 0 && m_dSource.GetRecordCount() == 0) { if (pItem->iSubItem == m_firstVisibleColumn ) { RemoveSelection(); pItem->pszText = (LPTSTR)(LPCTSTR)m_emptyString; } return; } // called when the listview needs to display data if(pItem->mask & LVIF_TEXT) { // first, move to the appropriate row in the database CString itemText, itemTextTrunc; if( m_dSource.PositionCursor(pItem->iItem) && (m_dSource.GetValueByColName(m_columnHeaders.GetViewFieldName((short)pItem->iSubItem), itemText) )) { //if there is an index column, it is used for indexing the displayed items //this is used only for the first column item because there's no reason to duplicate //the information //Truncate string if necessary. if (itemText.GetLength() > pItem->cchTextMax) { CString itemTextTrunc; itemTextTrunc.LoadString(IDS_STRING_TO_LONG); int nTrunc = itemTextTrunc.GetLength() + 1; itemText = itemText.Left(pItem->cchTextMax - nTrunc) + itemTextTrunc; } lstrcpy(pItem->pszText, (LPCTSTR)itemText ); } else { m_isRecordSetDirty = TRUE; } if (m_isRecordSetDirty) { SetRecordsetDirty(); m_isRecordSetDirty = FALSE; } }