То, что мы сделали в прошлом шаге это конечно круто. Но было бы еще круче, если бы мы нажимали на авторе и рядом бы появлялся список с годами. Почти как по настоящему :-). Ну давайте берите прошлый проект. Помещайте рядом элемент список и имя ему давайте дадим 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.
Ну и код естественно.
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. Вот он.
Итак. Удаляем старый cd->DeleteQueryDef("MFCtemp"); и создаем новый cf.Create("MFCtemp",SQLbuff); этот новый запрос помещаем в БД cf.Append(); закрываем его и открываем снова для того, чтобы он явился источником строк. Вот и вся идея. А дальше как всегда побежали по полям по делам.
Можно тестировать.
Работает !!! А куда он денется :-). Новая версия MDB в проекте.