Шаг 162 - Дальше о заполнении списка из БД , улучшения

То, что мы сделали в прошлом шаге это конечно круто. Но было бы еще круче, если бы мы нажимали на авторе и рядом бы появлялся список с годами. Почти как по настоящему :-). Ну давайте берите прошлый проект. Помещайте рядом элемент список и имя ему давайте дадим m_ListBoxExt связывая с переменной типа элемент управления.

class CTestBaseDlg : public CDialog
{
..............
// Dialog Data
	//{{AFX_DATA(CTestBaseDlg)
	enum { IDD = IDD_TESTBASE_DIALOG };
	CListBox	m_ListBoxExt;
	CListBox	m_ListBox;
	//}}AFX_DATA
..............
};

Так как пользоваться классами БД мы будет несколько раз, наиболее общие надо бы вынести в объявления на уровне класса.

class CTestBaseDlg : public CDialog
{
// Construction
public:
	void ListFullDao();
	CTestBaseDlg(CWnd* pParent = NULL);	// standard constructor
	CDaoWorkspace cw;
	CDaoDatabase* cd;
.............
};

Запуск DAO надо бы перенести в инициализацию диалога и инициализацию основных классов туда же.

///////////////////////////////////////////////
// CTestBaseDlg message handlers

BOOL CTestBaseDlg::OnInitDialog()
{
..................
	// TODO: Add extra initialization here
	AfxDaoInit();
	cd = new CDaoDatabase(&cw);
	cw.Open();
	if (cw.IsOpen())
	{
		
			cd->Open("d:\\TestDB\\test.mdb");
			if (cd->IsOpen()) 
			{
				ListFullDao();
				return TRUE;  
			}
    }
	return FALSE;
}

Это знакомо. Соотвественно функция ListFullDao() упростится.

void CTestBaseDlg::ListFullDao()
{
	CDaoTableDef cf(cd);
	CDaoRecordset cr;
	cf.Open("test");
		if (cf.IsOpen())
			{
			cr.Open(&cf);
			while (!cr.IsEOF())
			{
				char buf[256];
				COleVariant val;
				cr.GetFieldValue("family",val); 
				sprintf(buf,"%s",val.bstrVal);
				m_ListBox.AddString(buf);
				cr.MoveNext(); 
			}
			}
		else AfxMessageBox("Error Open Table");
	cr.Close(); 
	cf.Close();
 }

Закрывать глобальные классы и останавливать выполнение DAO мы будет путем перегрузки функции DestroyWindow.

BOOL CTestBaseDlg::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	cd->Close();
	delete cd;
	cw.Close();
	AfxDaoTerm();
	return CDialog::DestroyWindow();
}

Для реализации выборки по выбору фамилии нам необходимо перехватить сообщение от списка. Сделать это можно использовав ClassWizard.

162_1.gif (5936 b)

Ну и код естественно.

void CTestBaseDlg::OnSelchangeList1() 
{
	CString s;
	char SQLbuff[256];
	m_ListBox.GetText(m_ListBox.GetCurSel(),s); 
	for (int x=0;x<(m_ListBoxExt.GetCount()+1);x++)
		m_ListBoxExt.DeleteString(x);
	CDaoQueryDef cf(cd);
	CDaoRecordset cr;
	cd->DeleteQueryDef("MFCtemp"); 
	sprintf(SQLbuff,"SELECT * FROM Query1 WHERE family='%s';",s);
	cf.Create("MFCtemp",SQLbuff);
	cf.Append();
	cf.Close(); 
	cf.Open("MFCtemp"); 
	if (cf.IsOpen())
	{
	 cr.Open(&cf); 
	 if (cr.IsOpen())
	 {
		 while (!cr.IsEOF())
			{
				char buf[256];
				COleVariant val;
				cr.GetFieldValue("year",val); 
				sprintf(buf,"%s",val.bstrVal);
				m_ListBoxExt.AddString(buf);
				cr.MoveNext();
		 }	
	 }
	}
	cr.Close(); 
    cf.Close(); 
}

Логика такая. Мы делаем набор строк CDaoRecordset на основе запроса. Только вот формировать запрос будете сами ;-) Смотрите код. Для начала мы удалим запрос из БД, а потом создадим его заново. Он физически будет добавлен в БД ACCESS. Вот он.

162_2.gif (869 b)

Итак. Удаляем старый cd->DeleteQueryDef("MFCtemp"); и создаем новый cf.Create("MFCtemp",SQLbuff); этот новый запрос помещаем в БД cf.Append(); закрываем его и открываем снова для того, чтобы он явился источником строк. Вот и вся идея. А дальше как всегда побежали по полям по делам.

Можно тестировать.

162_3.gif (2455 b)

Работает !!! А куда он денется :-). Новая версия MDB в проекте.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 22.03.2000