- •Мета практити
- •Порядок проходження практики
- •Створення прикладних програм Створення Проекту
- •Проект програми на основі Діалогу
- •Створення Програми
- •Обробка повідомлень
- •Завдання
- •Однодокументна програма
- •Створення Програми
- •Завдання
- •Багатодокументна програма
- •Завдання
- •Типові завдання
- •Зміст звіту про практику
- •Навчально-методичні матеріали
Створення Програми
Клас CTestApp містить функцію InitInstance(), з якої починається виконання програми і створення об’єкту програми theApp (Рис. 37). В функції InitInstance() створюється об’єкт вікна програми, до нього приєднується вікно програми і вікно програми на екрані.
Клас CMainFrame містить об’єкти класів CStatusBar, CToolBar та CChildView і функції, що підтримують зовнішній вигляд вікна програми (Рис. 38).
Клас CChildView містить функції PreCreateWindow() та OnPaint() (Рис. 39). У функції PreCreateWindow() налаштовується зовнішній вигляд робочої області вікна програми, а функція OnPaint() дозволяє здійснювати графічний вивід у робочу область вікна програми. Для цього вона містить об’єкт класу контексту екрана CPaintDC.
Контекст екрана інкапсулює весь графічний вивід в робочу область вікна програми.
Якщо, програма, що створюється повинна працювати з текстовими документами, то базовим класом для класу дочірнього вікна CChildView у діалозі Рис. 35 необхідно вибрати клас CEditView. Тоді, майстер створення проекту автоматично згенерує класи «документу» та «вигляду» для підтримки текстових даних, та забезпечить їх збереження у файлі.
Рисунок 38. Клас CMainFrame.
Рисунок 39. Клас CChildView.
Якщо запустити програму на компіляцію і виконання, то вона створить вікно програми (Рис. 40), але не буде виконувати ніяких корисних дій.
Рисунок 40. Вікно програми після виконання.
Завдання
Використовуючи програму з однодокументною архітектурою забезпечити читання та запис текстових файлів з полями (розділяються комами) заданих об’єктів. За допомогою розробленої програми можна додавати нові записи до відкритого файлу.
Багатодокументна програма
Процес створення багатодокументної програми аналогічний процесу створення однодокументної. Лише у діалозі Рис. 30 необхідно вибрати прапорець “Multiple documents”.
Для того, щоб урізноманітнити вигляд у якому будуть виводитися дані для багатодокументної програми пропонується створити клас дочірнього вікна CChildView на основі стандартного для MFC касу CListView. Для цього необхідно в діалозі Рис. 35 зробити відповідний вибір. У результаті майстер проектів створить відповідні класи «документу» та «вигляду», які підтримують відображення даних у вигляді таблиці.
Нижче приведено приклад вмісту файлів заголовків та реалізації «документу» та його «вигляду» для відображення даних в таблиці.
Код для роботи з «документом»:
// CTableDoc document
class CTableDoc : public CDocument {
DECLARE_DYNCREATE(CTableDoc)
public:
CTableDoc();
virtual ~CTableDoc();
virtual void Serialize(CArchive& ar); // overridden for document i/o
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
virtual void DeleteContents();
int GetRowTotal();
STableRow * GetTable();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
virtual BOOL OnNewDocument();
protected:
int m_RowTotal;
STableRow * m_pTable;
DECLARE_MESSAGE_MAP()
};
// ****************************************************************************
inline int CTableDoc::GetRowTotal() { return m_RowTotal; }
// ****************************************************************************
inline STableRow * CTableDoc::GetTable() { return m_pTable; }
// ****************************************************************************
BOOL CTableDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
int i;
char szInBuff[1024];
char * szCurr;
FILE * fIn = fopen(lpszPathName, "r");
size_t nLenKeyStr = strlen(g_KeyRowTotal);
while (!feof(fIn)) {
fgets(szInBuff, 1024, fIn);
szCurr = strtok(szInBuff, ";");
if (szCurr && !strncmp(szCurr, g_KeyRowTotal, nLenKeyStr)) {
m_RowTotal = atoi(szCurr + nLenKeyStr);
break;
}
}
nLenKeyStr = strlen(g_szSurfFilePref);
if (m_RowTotal) {
m_pTable = (STableRow *)malloc(m_RowTotal * sizeof(STableRow));
i = 0;
while (!feof(fIn) && i < m_RowTotal) {
fgets(szInBuff, 1024, fIn);
if (szInBuff && !strncmp(szInBuff, g_szSurfFilePref, nLenKeyStr)) {
if (szCurr = strtok(szInBuff, ";")) {
sscanf(szCurr, "%s", m_pTable[i].szVoidName);
}
if (szCurr = strtok(NULL, ";")) {
m_pTable[i].nFaceCount = atoi(szCurr);
}
if (szCurr = strtok(NULL, ";")) {
sscanf(szCurr, "%f", &m_pTable[i].fVolume);
}
if (szCurr = strtok(NULL, ";")) {
m_pTable[i].centr.x = atoi(szCurr);
}
if (szCurr = strtok(NULL, ";")) {
m_pTable[i].centr.y = atoi(szCurr);
}
if (szCurr = strtok(NULL, ";")) {
m_pTable[i].centr.z = atoi(szCurr);
}
i++;
}
}
m_RowTotal = i;
}
fclose(fIn);
return TRUE;
}
// ****************************************************************************
void CTableDoc::DeleteContents()
{
if (m_RowTotal) free(m_pTable), m_RowTotal = 0;
CDocument::DeleteContents();
}
// ****************************************************************************
Код для роботи з «виглядом»:
// CTableView view
class CTableView : public CListView
{
DECLARE_DYNCREATE(CTableView)
STableRow m_SelectedPos;
protected:
CTableView(); // protected constructor used by dynamic creation
virtual ~CTableView();
protected:
virtual void OnInitialUpdate(); // called first time after construct
public:
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
DECLARE_MESSAGE_MAP()
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
public:
afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
};
// CTableView
#define NUM_COLUMNS 6
enum EListCol {
LC_OBJ_NAME = 0,
LC_FACES,
LC_VOLUME,
LC_COORD_X,
LC_COORD_Y,
LC_COORD_Z
};
static _TCHAR * g_szColumnLabel[NUM_COLUMNS] = {
_T("Name Object"), _T("Faces"), _T("Volume"), _T("X-coord"), _T("Y-coord"), _T("Z-coord")
};
static int g_nColumnFmt[NUM_COLUMNS] = {
LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT
};
static int g_nColumnWidth[NUM_COLUMNS] = {
150, 100, 100, 100, 100, 100
};
// ****************************************************************************
IMPLEMENT_DYNCREATE(CTableView, CListView)
// ****************************************************************************
CTableView::CTableView() { }
// ****************************************************************************
CTableView::~CTableView() { }
// ****************************************************************************
BEGIN_MESSAGE_MAP(CTableView, CListView)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnNMDblclk)
END_MESSAGE_MAP()
// ****************************************************************************
BOOL CTableView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= LVS_SHOWSELALWAYS | LVS_REPORT;
return CListView::PreCreateWindow(cs);
}
// ****************************************************************************
void CTableView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
CListCtrl & ListCtrl = GetListCtrl();
ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT);
int i;
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for(i = 0; i < NUM_COLUMNS; i++) {
lvc.iSubItem = i;
lvc.pszText = g_szColumnLabel[i];
lvc.cx = g_nColumnWidth[i];
lvc.fmt = g_nColumnFmt[i];
ListCtrl.InsertColumn(i, &lvc);
}
// insert items
CTableDoc * pDoc = (CTableDoc *)GetDocument();
int nRowTotal = pDoc->GetRowTotal();
STableRow * pTable = pDoc->GetTable();
LV_ITEM lvi;
char szIntBuff[32];
lvi.mask = LVIF_TEXT;
lvi.iSubItem = 0;
lvi.iImage = i;
ListCtrl.SetItemCount(nRowTotal);
for(i = 0; i < nRowTotal; i++) {
lvi.iItem = i;
lvi.pszText = pTable[i].szVoidName;
ListCtrl.InsertItem(&lvi);
// set item text for additional columns
sprintf(szIntBuff, "%d", pTable[i].nFaceCount);
ListCtrl.SetItemText(i, LC_FACES, szIntBuff);
sprintf(szIntBuff, "%9.2f", pTable[i].fVolume);
ListCtrl.SetItemText(i, LC_VOLUME, szIntBuff);
sprintf(szIntBuff, "%d", pTable[i].centr.x);
ListCtrl.SetItemText(i, LC_COORD_X, szIntBuff);
sprintf(szIntBuff, "%d", pTable[i].centr.y);
ListCtrl.SetItemText(i, LC_COORD_Y, szIntBuff);
sprintf(szIntBuff, "%d", pTable[i].centr.z);
ListCtrl.SetItemText(i, LC_COORD_Z, szIntBuff);
}
}
// ****************************************************************************
// CTableView diagnostics
#ifdef _DEBUG
// ****************************************************************************
void CTableView::AssertValid() const
{
CListView::AssertValid();
}
// ****************************************************************************
void CTableView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
#endif //_DEBUG
// CTableView message handlers
// ****************************************************************************
void CTableView::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult) {
int nRetLen;
CListCtrl & listCtrl = GetListCtrl();
POSITION pos = listCtrl.GetFirstSelectedItemPosition();
int nBuffLen = 32;
char strBuffer[32];
if (pos) {
int nItem = listCtrl.GetNextSelectedItem(pos);
nRetLen = listCtrl.GetItemText(nItem, LC_OBJ_NAME, m_SelectedPos.szVoidName, nBuffLen);
nRetLen = listCtrl.GetItemText(nItem, LC_COORD_X, strBuffer, nBuffLen);
m_SelectedPos.centr.x = atoi(strBuffer);
nRetLen = listCtrl.GetItemText(nItem, LC_COORD_Y, strBuffer, nBuffLen);
m_SelectedPos.centr.y = atoi(strBuffer);
nRetLen = listCtrl.GetItemText(nItem, LC_COORD_Z, strBuffer, nBuffLen);
m_SelectedPos.centr.z = atoi(strBuffer);
theApp.OnVoidListViewDbClick((WPARAM)&m_SelectedPos, 0);
}
*pResult = 0;
}
// ****************************************************************************