И В Радинский (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());
}
/////////////////////////////////////////////////////////////////////////////
йУПМШЪПЧБОЙЕ ЛМБУУБ ДПЧПМШОП РТПУФП:
дПВБЧЙФШ РЕТЕНЕООХА ФЙРБ CListCtrlDb Ч ДЙБМПЗ, Ч
ЛПФПТПН ЙУРПМШЪХЕФУС ListCtrl.
б ДБМШЫЕ РТЙНЕТОП ФБЛ:
m_ctrlList.SetRecordset(m_pRecordset);
m_ctrlList.SetSQL( "select
* from Streets" );
if (!m_ctrlList.OpenRecordset())
return ;
if (!m_ctrlList.PrepareColumns())
return ;
m_ctrlList.FillControl();
й ЧУЕ!
//include "/ssi/right_banner.html"; ?>