И В Радинский (c) .. , 18.07.1999.
Часто при работе с БД, или просто с отдельной таблицей приходиться сталкиваться с делемой - как отобразить в табличном виде содержимое того или иного запроса. Использовать DbGrid? Использовать DataGrid? А может Microsoft FlexGrid? Или лучьше Microsoft Hierarchical FlexGrid? Обилие Grid-ов смущает и вносит сумятицу, тратишь пол-дня на тестирование очередного Grid-а, чтобы в конце концов от него отказаться - обычное дело, когда пару месяцов их не используешь. А ведь часто надо просто отобразить данные, безо всякого модифицирования данных! Вот тут и всоминаешь про CListCtrl. Всю эту рутину по заполнению данными я оформил в класс CListCtrlDb.
/////////////////////////////////////////////////////////////////////////////
// CListCtrlDb window
class CListCtrlDb : public CListCtrl
{
// Construction
public:
CListCtrlDb();
// Implementation
public:
void FillControl();
BOOL SetSQL(LPCTSTR szSQL);
BOOL OpenRecordset();
BOOL PrepareColumns();
void PrepareControl();
BOOL SetRecordset(CRecordset *pRecordset);
virtual ~CListCtrlDb();
protected:
CRecordset* m_pRecordset;
CString m_strSQL;
int nFieldCount;
};
/////////////////////////////////////////////////////////////////////////////
// CListCtrlDb
CListCtrlDb::CListCtrlDb()
{
m_pRecordset = NULL;
nFieldCount = 0;
}
CListCtrlDb::~CListCtrlDb()
{
}
BOOL CListCtrlDb::SetRecordset(CRecordset *pRecordset)
{
// проверим параметры
ASSERT(pRecordset);
// теперь можно и установить Recordset
m_pRecordset =
pRecordset;
return TRUE;
}
void CListCtrlDb::PrepareControl()
{
ASSERT(::IsWindow(m_hWnd));
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
dwStyle &= ~(LVS_TYPEMASK); dwStyle &= ~(LVS_EDITLABELS);
SetWindowLong( m_hWnd, GWL_STYLE, dwStyle | LVS_REPORT |
LVS_SHOWSELALWAYS | LVS_SINGLESEL);
// Полнострочное выделение
DWORD styles =
LVS_EX_FULLROWSELECT;
ListView_SetExtendedListViewStyleEx(m_hWnd, styles, styles );
}
BOOL CListCtrlDb::PrepareColumns()
{
// проверим
m_pRecordset
ASSERT(m_pRecordset);
ASSERT(m_pRecordset->IsOpen());
// Удалим все колонки
while(DeleteColumn(0));
// Получим колличество полей в запросе
nFieldCount =
m_pRecordset->GetODBCFieldCount();
// Добавим столько колонок, сколько в
запросе,
// причем названия колонок берутся из
самого запроса
for (int i =
0; i < nFieldCount; i++)
{
CODBCFieldInfo fi;
m_pRecordset->GetODBCFieldInfo(i, fi);
InsertColumn(i, fi.m_strName);
}
return TRUE;
}
BOOL CListCtrlDb::OpenRecordset()
{
// если это
длительная операция, то пользователь
// должен хотябы догадываться об этом
CWaitCursor wait;
return m_pRecordset->Open(CRecordset::snapshot,
m_strSQL, CRecordset::readOnly);
}
BOOL CListCtrlDb::SetSQL(LPCTSTR szSQL)
{
// РТПЧЕТЙН
РБТБНЕФТЩ
ASSERT(szSQL);
m_strSQL = szSQL;
return TRUE;
}
void CListCtrlDb::FillControl()
{
// РТПЧЕТЙН
m_pRecordset
ASSERT(m_pRecordset);
ASSERT(m_pRecordset->IsOpen());
// ЕУМЙ ЬФП ДМЙФЕМШОБС ПРЕТБГЙС, ФП
РПМШЪПЧБФЕМШ
// ДПМЦЕО ИПФСВЩ ДПЗБДЩЧБФШУС ПВ ЬФПН
CWaitCursor wait;
// ХДБМЙН ЧУЕ ЮФП ВЩМП
DeleteAllItems();
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
CString strItem;
int nItem = 0;
// ЪБРПМОЙН ListCtrlDb
m_pRecordset->MoveFirst();
do
{
for (int nSubItem = 0; nSubItem <
nFieldCount; nSubItem++)
{
m_pRecordset->GetFieldValue(nSubItem, strItem);
lvItem.iItem = nItem;
lvItem.iSubItem =
nSubItem;
lvItem.pszText =
strItem.GetBuffer(strItem.GetLength() + 1);
if (nSubItem == 0)
InsertItem(&lvItem);
else
SetItem(&lvItem);
}
m_pRecordset->MoveNext();
nItem++;
}
while(!m_pRecordset->IsEOF());
}
/////////////////////////////////////////////////////////////////////////////
йУПМШЪПЧБОЙЕ ЛМБУУБ ДПЧПМШОП РТПУФП:
m_ctrlList.SetRecordset(m_pRecordset);
m_ctrlList.SetSQL("select
* from Streets");
if (!m_ctrlList.OpenRecordset())
return;
if (!m_ctrlList.PrepareColumns())
return;
m_ctrlList.FillControl();
й ЧУЕ!