Ved applikationer, der er baseret på dokumenter, anvendes
nedarvning fra MFC klasserne CDocument og CView (alternativt
CScrollView, hvis dokumentet er større end applikationens klient
areal og derfor skal kunne scrolles). AppWizard genererer de to
nedarvede klasser, ved Ts applikationen CTsDoc og CTsView.
Metrics
For at behandle dokumenter korrekt skal diverse system værdier anvendes. Disse værdier kaldes under et for system metrics. Ved arbejdet med system metrics oprettes først de nødvendige metrics variable i applikations view klassen nedarvet fra CView klassen:
protected: // Beregn rapport metrics void ComputeReportMetrics(CDC *pDC); // Member variable til rapport CSize m_SizeTotal; // Total rapport størrelse CSize m_PageSize; // Side scroll størrelse CSize m_LineSize; // Linie scroll størrelse int m_nLinesPerPage; // Antal linier pr side int m_nLineHeight; // Antal pixels pr linie int m_nLineWidth; // Maximum linie længde int m_nMinCharWidth; // Minimum karakter bredde int m_nAvgCharWidth; // Middel karakter bredde int m_nMaxCharWidth; // Maximum karakter bredde
Derefter implementeres en funktion til beregning af de
nødvendige system metrics i applikation View implementations fil
(TsView.cpp):
void CTsView::ComputeReportMetrics(CDC *pDC) { TEXTMETRIC tm; CRect rectClient; int nPageHeight; if (!pDC->IsPrinting()) pDC->SetMapMode(MM_TEXT); else pDC->SetMapMode(MM_LOMETRIC); if (!pDC->GetTextMetrics(&tm)) { AfxMessageBox("TextMetrics er ikke tilgængelige!",MB_OK | MB_ICONSTOP); return; } m_nMinCharWidth = tm.tmAveCharWidth; m_nAvgCharWidth = (tm.tmAveCharWidth + tm.tmMaxCharWidth) / 2; m_nMaxCharWidth = tm.tmMaxCharWidth; m_nLineHeight = tm.tmHeight + tm.tmExternalLeading; m_nLineWidth = m_nAvgCharWidth * 76; if (!pDC->IsPrinting()) { GetClientRect(&rectClient); // Vindue størrelse pDC->DPtoLP(&rectClient); // Konverter til logisk rectClient.NormalizeRect(); // Normaliser nPageHeight = rectClient.Height();// Side højde (logisk) } else { int nHRes = pDC->GetDeviceCaps(HORZRES);// Print x-pix int nVRes = pDC->GetDeviceCaps(VERTRES);// Print y-pix rectClient.SetRect(0, 0, nHRes, nVRes); // Print side pDC->DPtoLP(&rectClient); // Konverter til logisk rectClient.NormalizeRect(); // Normaliser nPageHeight = rectClient.Height();// Side højde (logisk) } // Beregn helt antal linier pr side m_nLinesPerPage = nPageHeight / m_nLineHeight; // Frihold 8 printer linier til margen samt header og footer if (pDC->IsPrinting) m_nLinesPerPage -= 8; // Beregn pixels pr side til helt antal linier nPageHeight = m_nLinesPerPage * m_nLineHeight; // Horizontal side scroll 1/5 linie m_PageSize.cx = m_nLineWidth / 5; // Vertikal side scroll m_PageSize.cy = max(m_nLineHeight, nPageHeight); // Horizontal linie scroll 1/20 linie m_LineSize.cx = m_nLineWidth / 20; // Vertikal linie scroll m_LineSize.cy = m_nLineHeight; }
Scrolling
Hvis applikationen skal supportere scrolling skal følgende
ændringer foretages:
Klassen, der nedarver fra MFC CView, skal nedarve fra MFC CScrollViewclass:
class CTsView : public CScrollView
I message loop for CTsView skal der ændres til CScrollView (TsView.cpp):
IMPLEMENT_DYNCREATE(CTsView, CScrollView) BEGIN_MESSAGE_MAP(CTsView, CScrollView)
I dokument klassen CTsDoc indføres en public attribut til at
indeholde dokumentets information, en public attribut til at
indeholde antal linier i dokumentet, en public attribut til at
indeholde dokument typen, samt en public operation til at
returnerer antallet af linier i dokumentet:
// Attributes public: int nDocType; CStringArray csaDocLines; long m_lDocLines; // Operations public: long GetDocLines(void) { return m_lDocLines; }
I CTsDoc constructoren initialiseres dokument indhold og størrelse:
CTsDoc::CTsDoc() { // Initializer dokument typen (Ingen visning: Type 0) nDocType = 0; // Åben tabel set CrsPostNr* pPostNr; pPostNr = new CrsPostNr(NULL); pPostNr->Open(); // Indlæs records fra tabellen CString Text; while (!pPostNr->IsEOF()) { // Opbyg tekst streng Text.Format("%ld %s", pPostNr->m_PostNr, pPostNr->m_Distrikt); // Gem tekst streng i streng array csaDocLines.Add(Text); // Hent næste record pPostNr->MoveNext(); } // Gem dokument størrelse m_lDocLines = pPostNr->GetRecordCount(); // Luk tabel set pPostNr->Close(); }
I ClassWizard vælges under fanebladet "Message Maps" view klassen "Class name: CTsView", "Object IDs: CTsView", "Messages: OnInitialUpdate" og <Add Function...>. OnInitialUpdate er en funktion, der kaldes, når view'et første gang forbindes til et dokument.
Derefter vælges <Edit Code> for initial update, og dokument størrelse tilføjes:
void CTsView::OnInitialUpdate() { CScrollView::OnInitialUpdate(); CClientDC aDC(this); ComputeReportMetrics(&aDC); CSize DocSize(m_nLineWidth, (m_nLineHeight * GetDocument()->GetDocLines())); SetScrollSizes(MM_TEXT, DocSize, m_PageSize, m_LineSize); }
Endelig oprettes ved hjælp af ClassWizard funktionen OnScroll() i view klassen, og der tilføjes et kald til Invalidate() for at slette vinduets oprindelige indhold før nyt indhold vises:
BOOL CSportView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) { Invalidate(); return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll); }
Oversæt og kør applikationen
Document / View
Applikationens Document / View arkitektur kan nu
implementeres:
I view klassens member funktion til visning (CTsView::OnDraw()) skrives koden, der skal vise det aktuelle dokument (fx indeholdende alle post distrikter):
void CTsView::OnDraw(CDC* pDC) { CTsDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here if (pDoc->nDocType == 1) // Hvis dokument skal vises { ComputeReportMetrics(pDC); for (long nLine = 0; nLine < pDoc->GetDocLines(); nLine++) { // Vis tekst pDC->TextOut((m_nMaxCharWidth * 2), (m_nLineHeight * nLine), pDoc->csaDocLines[nLine]); } } }
Indsæt inkludering af record set definition filen i filen, der indeholder definitionen af view klassen (TsView.cpp):
#include "TsSet.h"
I den CMainFrame member funktion, hvor der skal bestilles visning af dokumentet ved hjælp af et menu punkt (fx CMainFrame::OnRapportPostdistrikt()) indsættes kode til at modificere dokument type variablen:
void CMainFrame::OnRapporterPostdistrikter() { // TODO: Add your command handler code here CTsView* pView = (CTsView*)GetActiveView(); CTsDoc* pDoc = pView->GetDocument(); pDoc->nDocType = 1; pDoc->UpdateAllViews(NULL); }
Derefter indsættes inkludering af dokument og view klassernes definition i MainFrm.cpp filen:
#include "TsDoc.h" #include "TsView.h"
Disse sider er udarbejdet af:
Sidst opdateret 97-04-19 af Ole Christiansen