То, что мы сделали в прошлом шаге это конечно круто. Но было бы еще круче, если бы мы нажимали на авторе и рядом бы появлялся список с годами. Почти как по настоящему :-). Ну давайте берите прошлый проект. Помещайте рядом элемент список и имя ему давайте дадим 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 в проекте.