TietgenSkolen - Datamatikeruddannelsen


Microsoft Windows Applikationsudvikling

med

Visual C++ 4.0 og MFC


Dokumenter og Views

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