wtorek, 1 kwietnia 2014

Microsoft Foundation Classes

Struktura programu opartego na MFC składa się z dwóch pojęć związanych z aplikacją:
  • dokumentu czyli kolekcji danych w aplikacji, z którymi ma styczność użytkownik przy jednoczesnym wyborze tego czy użytkownik będzie korzystał Single Document Interface czy też Multiple Document Interface,
  • widoku, który określa sposób w jaki dane będą wyświetlone w oknie oraz możliwe interakcje użytkownika z nimi (własna klasa widoku jest wyprowadzana z klasy CView).
MFC zawiera mechanizm integrujący dokument z jego widokami oraz okno ramek z aktywnym widokiem, które przechowuje wskaźnik do aktywnego obiektu widoku. Natomiast koordynacją między dokumentem, widokiem i oknem ramek zajmuje się klasa zwana szablonami dokumentów. Aby zdefiniować szablon dokumentów dla aplikacji SDI należy użyć klasy CSingleDocTemplate natomiast do typu MDI służy CMultiDocTemplate.

Aplikacja MFC posiada cztery podstawowe typy ("My" to nazwa naszej aplikacji):
  • CMyApp czyli klasę aplikacji,
  • CMyWnd czyli klasę okna ramki,
  • CMyView czyli klasę widoku, która definiuje w jaki w obszarze klienta okna utworzonego przez obiekt CMyWnd będą wyświetlane dane zawarte w CMyDoc,
  • CMyDoc czyli klasę dokumentu definiującą dokument zawierający dane aplikacji.



Aby stworzyć nowy projekt MFC w środowisku Microsoft Visual Studio 2010 należy:
  • uruchomić nowy projekt,
  • jako szablon wybrać "Visual C++" i "MFC", a następnie "Aplikacja MFC",
  • wprowadzić nazwę projektu i kliknąć "OK",
  • w oknie "MFC Application Wizard" dla aplikacji SDI:
    • wchodzimy w "Application Type",
    • wciskamy pole "Single document",
    • wyłącz opcję "Use Unicode libraries" (jeżeli jest aktywna to aplikacja spodziewa się wejścia w formacie Unicode, pliki są w formacie Unicode i na skutek tego nie można ich odczytać w programach, które oczekują formatu ASCII),
    • określamy styl graficzny naszego programu,
    • określamy w jaki sposób kod bibliotek MFC jest wykorzystywany w programie (aplikacje z łączeniem statycznym są szybsze natomiast te z łączeniem dynamicznym zapewniają lepsze użycie pamięci),
    • wybieramy z menu po lewej stronie "Document Template Properties" i określamy jakie rozszerzenie ma tworzyć nasz program,
    • przechodzimy do "User Interface Features" gdzie określamy takie opcje jak np. domyślna maksymalizacja okna,
    • kolejna sekcja to "Advanced Features" i tutaj uaktywniamy opcje "Printing and print preview" (dodaje do menu "File" takie opcje jak np. "Page Setup", a kreator aplikacji dodaje kod obsługi) i "Context-sensitive Help (HTML)" (podstawowa obsługa pomocy zależnej od kontekstu),
    • klikamy na "Generated Classes" po lewej stronie gdzie możemy sprawdzić jakie klasy zostaną wygenerowane w kodzie aplikacji i tak np. klasy bazowe to:
      • CEditView: umożliwia prostę wielowierszową edycję tekstu, a także funkcje wyszukiwania, zamieniania oraz drukowania,
      • CFormView: dostarcza widok będący formularzem (oknem dialogowym, które może zawierać kontrolki do wyświetlania danych oraz wprowadzania danych przez użytkownika),
      • CHtmlEditView: rozszerza klasę CHtmlView i dodaje możliwość edytowania witryn HTML, 
      • CHtmlView: dostarcza widok, w którym można przeglądać strony WWW oraz lokalne pliki HTML,
      • CListView: umożliwia korzystanie z architektury "dokument i widok" z kontrolkami list,
      • CRichEditView: umożliwia wyświetlanie i edycję RTF,
      • CScrollView: dostarcza widok, który automatycznie dodaje paski przewijania jeżeli wyświetlane dane tego wymagają,
      • CTreeView: umożliwia korzystanie z architektury "dokument i widok" z kontrolkami drzewa,
      • CView: dostarcza podstawowych możliwości przeglądania dokumentu,
      • CChildFrame (dla MDI): dostarcza okno ramowe dla widoku dokumentu, który pojawia się wewnątrz okna aplikacji utworzone przez obiekt typu CMainFrame,
    • jako klasę bazową klasy typu CMyView (gdzie "My" to nazwa projektu) wybierz np. CEditView aby automatycznie uzyskać podstawowe możliwości edycji tekstu,
    • kliknij "Finish",
  • dla aplikacji MDI robimy zmiany tylko w dwóch miejscach:
    • w sekcji "Application Type" pozostawiamy domyślną opcję "Multiple documents",
    • w sekcji "Generated Classes" pozstawiamy klasę CView jako klasę bazową CMyView.
W oknie "Eksplorator rozwiązań" Visual Studio w pliku "ReadMe.txt" na liście rozwiązania znajduje się opis wszystkich plików wchodzących w skład projektu jak następuje:
  • "My.vcxproj": to główny plik projektu zawierający informacje o wersji Visual C++, który wygenerował plik, a także informacje o platformach, konfiguracjach i cechach projektu wybranych w kreatorze aplikacji,
  •  "My.vcxproj.filters": plik filtrów projektu zawierający informacje o związku pomiędzy plikami a filtrami,
  • "My.h": pliki nagłówkowe aplikacji (zawiera deklarację klasy CMyApp),
  • "My.cpp": główny plik źródłowy zawierający klasę CMyApp oraz definicję klasy CAboutDlg,
  • "My.rc": lista wszystkich zasobów Microsoft Windows, które używa program,
  • "My.ico": plik ikon,
  • "My.rc2": zawiera zasoby, które nie są edytowane przez Microsoft Visual C++ (wszystkie nieedytowalne przez edytor zasobów zasoby powinny zostać tutaj umieszczone),
  • "My.reg": przykładowy plik pokazują rodzaj ustawień rejestracji struktury, które zostaną skonfigurowane,
  • "MainFrm.h" i "MainFrm.cpp": zawiera klasę CMainFrame, która wywodzi się z CFrameWnd i kontroluje wszystkie właściwości ramki SDI,
  • "LeftView.h" i "LeftView.cpp": zawiera klasę CLeftView wywodzącą się z CTreeView,
  • "Toolbar.bmp": plik mapy bitowej użyty do stworzenia kafelkowych obrazów dla paska narzędzi (początkowy pasek narzędzi i pasek stanu są konstruowane w klasie CMainFrame),
  • "MyDoc.h" i "MyDoc.cpp": klasa CMyDoc,
  • "MyView.h" i "MyView.cpp": widok dokumentu i klasa CMyView,
  • "StdAfx.h" i "StdAfx.cpp": pliki używane do budowanie prekompilowanych plików nagłówkowych i prekompilowanych plików typów,
  • "Resource.h": standardowy plik zasobu, które definiuje nowe identyfikatory zasobu, 
  • "My.manifest": pliki manifestu aplikacji użyte przez Windows XP do opisu zależności aplikacji od konkretnych wersji zespołów "Side-by-Side".
Definicje klas:
  • CMyApp:
    • makrodefinicja "DECLARE_MESSAGE_APP": definiuje które funkcje klasy będą obsługiwały które komunikaty Windowsa,
  • CMainFrame: 
    • składowe chronione "m_wndStatusBar" i "m_wndToolbar": egzemplarze klas MFC (odpowiednio CStatusBar i CToolBar) tworzące i zarządzające paskiem stanu pojawiającym się na dole okna aplikacji oraz paskiem narzędzi dostarczającym przyciski umożliwiające dostęp do standardowych elementów menu,
  • CMyDoc:
    • makrodefinicja "DECLARE_DYNCREATE": umożliwia dynamiczne tworzenie obiektu klasy poprzez jego syntezę danych odczytanych z pliku,
    • makrodefinicja "DECLARE_MESSAGE_APP": obsługa komunikatów Windowsa przez jej funkcje składowe,
  • CMyView:
    • funkcja GetDocument: zwraca wskaźnik do obiektu dokumentu odpowiadającego widokowi.
Działanie programu:
  • utworzenie zmiennej "theApp" typu CMyApp będącej obiektem aplikacji,
  • wywołanie funkcji "WinMain" dostarczonej przez MFC,
  • uruchomienie za pomocą "WinMain" funkcji "InitInstance", która tworzy szablon dokumentu, główne okno ramowe, dokument oraz widok,
  • wywołanie za pomocą "WinMain" funkcji "Run", która uruchamia główną pętlę komunikatów pobierającą i przesyłającą komunikaty Windowsa.
Powiązanie między konkretnym komunikatem a obsługującą go funkcją w programie dokonywane jest przez mapę komunikatów, która musi mieć każda obsługująca komunikaty Windowsa klasa w programie. Mapa komunikatów jest tworzona automatycznie lub poprzez ClassWizard. W kodzie programu początek mapy komunikatów jest określony makrodefinicją "BEGIN_MESSAGE_MAP", a koniec "END_MESSAGE_MAP".
Kategorie komunikatów:
  • komunikat Windowsa: oprócz komunikatów "WM_COMMAND" są to standardowe komunikaty rozpoczynające się prefiksem "WM_",
  • komunikaty powiadamiające z kontrolek: komunikaty "WM_COMMAND" przesyłane z kontrolek (takich jak lista wyboru) do okna, które utworzyło kontrolkę lub z okna potomnego do macierzystego,
  • komunikaty poleceń: komunikaty "WM_COMMAND" pochodzące z elementów interfejsu użytkownika takich jak elementy menu i przyciski pasków narzędzi.
Rodzaje komunikatów, które mogą powstać dla danego identyfikatora menu:
  • "COMMAND": komunikat wysyłany gdy dany element menu został wybrany,
  • "UPDATE_COMMAND_UI": przesyłany gdy menu powinno zostać uaktualnione zależnie od jego stanu.
Argumentem przesyłanym do funkcji uaktualniającej (komunikat "UPDATE_COMMAND_UI") jest wskaźnik do obiektu klasy CCmdUI. Jest to klasa MFC używana jedynie z procedurami obsługi uaktualnień i posiadająca pięć funkcji składowych:
  • ContinuteRouting: przesyła komunikat do procedury o niższym priorytecie,
  • Enable: włącza lub wyłącza stosowny element interfejsu,
  • SetCheck: ustawia znacznik wyboru dla stosownego elementu interfejsu,
  • SetRadio: włącza lub wyłącza przycisk w grupie przycisków opcji,
  • SetText: ustawia tekst dla stosownego elementu interfejsu.
Gdy chcesz narysować coś na graficznym urządzeniu musisz wykorzystać kontekst urządzenia. Kontekst urządzenia jest strukturą danych definiowaną przez system Windows zawierającą informacje pozwalające Windowsowi tłumaczyć żądanie wyjścia na działania na wykorzystywanym fizycznie urządzeniu. Kontekst urządzenia zapewnia wybór układów współrzędnych zwanych trybami mapowania, które są automatycznie konwertowane do współrzędnych klienta:
  • "MM_TEXT": jednostką logiczną jest jeden piksel urządzenia o dodatnim x od lewej do prawej i dodatnim y od góry do dołu obszaru klienta okna,
  • "MM_LOENGLISH": jednostką logiczną jest 0,01 cala o dodatnim x od lewej do prawej i dodatnim y od góry obszaru klienta okna w górę,
  • "MM_HIENGLISH": jednostką logiczną jest 0,001 cala o kierunkach x i y jak dla "MM_LOENGLISH",
  • "MM_LOMETRIC": jednostką logiczną jest 0,1 milimetra o kierunkach x i y jak dla "MM_LOENGLISH",
  • "MM_HIMETRIC":  ednostką logiczną jest 0,01 milimetra o kierunkach x i y jak dla "MM_LOENGLISH", 
  • "MM_ISOTROPIC": jednostka logiczna jest dowolnej długości jednak takiej samej na osi x i y (kierunki x i y są takie same jakd dla "MM_LOENGLISH"),
  • "MM_ANISOTROPIC": ten tryb jest podobny do "MM_ISOTROPIC" jednak pozwala aby długość jednostki logicznej na osi x była inna niż na osi y,
  • "MM_TWIPS": jednostką logiczną jest TWIP (0,05 punktu czyli 1/72 cala) o takich samych kierunkach x i y jak dla "MM_LOENGLISH".
Aby coś narysować musimy użyć obiektu pióra, który ma typ CPen. Obiekt ten posiada funkcję składową CreatePen, która jest wywoływana z trzeba argumentami. Drugi argument definiuje grubość linii, trzeci określa kolor używany podczas rysowania natomiast ostatni to jedna z następujących stałych:
  • "PS_SOLID": rysuje ciągłą linię,
  • "PS_DASH": rysuje linię przerywaną (ten styl linii jest prawidłowy tylko wtedy gdy pióro ma szerokość 1),
  • "PS_DOT": rysuje linię złożoną z kropek (ten styl linii jest prawidłowy tylko wtedy gdy pióro ma szerokość 1),
  • "PS_DASHDOT": rysuje linię składająca się na przemian z kresek i kropek (ten styl linii jest prawidłowy tylko wtedy gdy pióro ma szerokość 1), ,
  • "PS_DASHDOTDOT": rysuje linię składająca się na przemian z kresek i dwóch kropek  (ten styl linii jest prawidłowy tylko wtedy gdy pióro ma szerokość 1),
  • "PS_NULL": pióro nic nie rysuje,
  • "PS_INSIDEFRAME": pióro rysuje ciągłą linię jednak w przeciwieństwie do "PS_SOLID" punkty określające linię leżą na krawędzi pióra, a nie w jego środku więc rysowany obiekt nigdy nie wystaje poza opisujący prostokąt.
Innym sposobem rysowania jest pędzel, w ramach którego definiujemy obiekt klasy CBrush posiadający konstruktor jednoargumentowy i dwuargumentowy. W pierwszy przypadku podajemy tylko kolor pędzla natomiast przy drugim podajemy typ kreskowania:
  • "HS_HORIZONTAL": kreskowanie poziome,
  • "HS_VERTICAL": kreskowanie pionowe,
  • "HS_BDIAGONAL": kreskowanie w dół od lewej do prawej pod kątem 45 stopni,
  • "HS_FDIAGONAL": kreskowanie w górę od lewej do prawej pod kątem 45 stopni,
  • "HS_CROSS": kreskowanie poziome i pionowe,
  • "HS_DIAGCROSS": kreskowanie pod kątek 45 stopni.
Gdy rysujemy jakiś kształt robimy to w konkretnym widoku naszego dokumentu. Sprowadza się to do tego, że klasa widoku jest oczywistym miejscem dla procedur obsługi komunikatów myszy, które najważniejsze zostały wyszczególnione poniżej:
  • "WM_LBUTTONDOWN": komunikat powstaje przy naciśnięciu lewego przycisku myszy,
  • "WM_LBUTTONUP": komunikat powstaje przy zwolnieniu lewego przycisku myszy,
  • "WM_MOUSEMOVE": komunikat powstaje przy przemieszczaniu myszy.
Do procedury obsługi komunikatu przesyłane są dwa argumenty:
  • liczba znaczników stanu wskazujących czy dane klawisze są wciśnięte:
    • "MK_CONTROL": klawisz "Ctrl",
    • "MK_LBUTTON": lewy przycisk myszy,
    • "MK_MBUTTON": środkowy przycisk myszy,
    • "MK_RBUTTON": prawy przycisk myszy,
    • "MK_SHIFT": klawisz "Shift",
  • obiekt CPoint definiujący pozycję kursora w momencie naciśnięcia lewego przycisku myszy.
Funkcja SetROP2 ustawia tryb rysowania dla wszystkich kolejnych operacji wyjścia w kontekście urządzenia powiązanych z obiektem typu CDC. Tryb rysowania określa jak połączyć kolor pióra użytego do rysowania z kolorem tła aby ustalić kolor wyświetlanego obiektu. Tryb rysowania określamy jednym argumentem funkcji o jednej z następujących wartości:
  • "R2_BLACK": wszystko jest rysowane na czarno,
  • "R2_WHITE": wszystko jest rysowane na biało,
  • "R2_NOP": operacje rysowania nie mają efektu,
  • "R2_NOT": rysowanie przebiega zawsze w kolorze przeciwnym do wyświetlanego już na ekranie co zapewnia, że wyjście będzie zawsze widoczne,
  • "R2_COPYPEN": rysowanie w kolorze pióra (domyślny),
  • "R2_NOTCOPYPEN": rysowanie w kolorze przeciwnym do koloru pióra,
  • "R2_MERGEPENNOT": rysowanie w kolorze powstałym z alternatywy bitowej koloru pióra i koloru przeciwnego do koloru tła,
  • "R2_MASKPENNOT":  rysowanie w kolorze powstałym z koniunkcji bitowej koloru pióra i koloru przeciwnego do koloru tła,
  • "R2_MERGENOTPEN": rysowanie w kolorze powstałym z alternatywy bitowej koloru tła i koloru przeciwnego do koloru pióra,
  • "R2_MASKNOTPEN": rysowanie w kolorze powstałym z koniunkcji bitowej koloru tła i koloru przeciwnego do koloru tła,
  • "R2_MERGEPEN": rysowanie w kolorze powstałym z alternatywy bitowej koloru tła i koloru pióra,
  • "R2_NOTMERGEPEN": rysuje w kolorze przeciwnym do "R2_MERGEPEN",
  • "R2_MASKPEN": rysowanie w kolorze powstałym z koniunkcji bitowej koloru tła i koloru pióra,
  • "R2_NOTMASKPEN": rysowanie w kolorze przeciwnym do koloru "R2_MASKPEN",
  • "R2_XORPEN": rysowanie w kolorze powstałym z bitowej alternatywy wykluczającej koloru pióra i koloru tła,
  • "R2_NOTXORPEN": rysowanie w kolorze przeciwnym do koloru "R2_XORPEN".
Podczas pracy często musimy obsługiwać kolekcje danych nie znając z góry liczby elementów ani nawet ich typu. MFC dostarcza grupę klas kolekcji do obsługi takiego problemu. Kolekcja jest zbiorem dowolnej liczby danych zorganizowanych w określony sposób. MFC obsługuje trzy rodzaje kolekcji różniące się sposobem organizacji danych. Sposób organizacji kolekcji nazywa się jej kształtem. Istnieją trzy typy organizacji lub kształtu:
  • tablica (klasa szablonu CArray): uporządkowany układ elementów, z którego każdy element może zostać pobrany z wykorzystaniem indeksu będącego liczbą całkowitą,
  • lista (klasa szablonu CList): kolekcja uporządkowanych danych gdzie z każdym elementem powiązane są dwa wskaźniki, które wskazują na poprzedni i następny element na liście,
  • mapa (klasa szablonu CMap): nieuporządkowana kolekcja danych gdzie każdemu elementowi przyporządkowany jest klucz używany do odzyskania elementu z mapy.
Szablony klas kolekcji wskaźników z kontrolą typów przechowują wskaźniki do obiektów, a nie obiekty jako takie. Służy do tego klasa szablonu CTypedPtrList z następującymi funkcjami składowymi:
  • GetHead: zwraca wskaźnik do początku listy,
  • GetTails: zwraca wskaźnik do stopki listy,
  • RemoveHead: usuwa pierwszy wskaźnik z listy,
  • RemoveTail: usuwa ostatni wskaźnik z listy,
  • GetNext: zwraca wskaźnik znajdujący się na pozycji określonej zmienną typu POSITION, która jest przesyłana jako referencja (wartość zmiennej jest aktualizowana aby wskazywała kolejny element listy),
  • GetPrev: zwraca wskaźnik znajdujący się na pozycji określonej zmienną typu POSITION, która jest przesyłana jako referencja (wartość zmiennej jest aktualizowana aby wskazywała poprzedni element listy),
  • GetAt: zwraca wskaźnik przechowywany na pozycji wskazywanej przez zmienną typu POSITION, która jest przesyłana jako argument,
  • AddHead: dodaje na początku listy wskaźnik przesyłany jako argument,
  • AddTail: dodaje na końcu listy wskaźnik przesyłany jako argument,
  • RemoveAll: usuwa wszystkie elementy z listy,
  • GetHeadPosition: zwraca pozycję elementu z początku listy,
  • GetTailPosition: zwraca pozycję elementu z końca listy,
  • RemoveAt: usuwa wskaźnik z pozycji listy,
  • InsertBefore: wstawia nowy wskaźnik określony przez drugi argument przed pozycją określoną przez pierwszy argument,
  • InsertAfter:  wstawia nowy wskaźnik określony przez drugi argument za pozycją określoną przez pierwszy argument, 
  • Find: wyszukuje na liście wskaźnik, który jest taki sam jak wskaźnik określony przez argument,
  • FindIndex: zwraca pozycję wskaźnika na liście określoną przesłanym jako argument indeksem będącym liczbą całkowitą,
  • GetCount: zwraca liczbę elementów na liście,
  • IsEmpty: zwraca prawdę jeżeli na liście nie ma żadnych elementów, a w przeciwnym razie fałsz.
Każdy widok dokumentu działa niezależnie od innych i nie ma między nimi komunikacji. Aby każdy widok, który doda element do dokumentu informował o tym pozostałe widoki tak aby i one mogły podjąć odpowiednie działania należy użyć funkcji UpdateAllViews z klasy dokumentu. Jej prototyp wygląda następująco: "void UpdateAllViews(CView * pSender, LPARAM lHint = OL, CObject * pHint = NULL);" gdzie:
  • "pSender" to wskaźnik do bieżącego widoku (powstrzymuje on wywołanie funkcji składowej OnUpdate w widoku),
  • "lHint" jest zmienną typu LAPARAM, który ma 32 bity w systemie Windows i może zostać użyty do przesłania informacji o obszarze, który ma zostać uaktualniony w obszarze klienta,
  • "pHint" jest wskaźnikiem do obiektu mogącego dostarczyć informacji o fragmencie obszaru, który ma zostać zaktualizowany w obszarze klienta.
Nowa klasa widoku musi coś wiedzieć o obszarze, w którym rysujemy (np. jego jego rozmiar i to jak daleko widok został przewinięty za pomocą paska przewijania). Te informacje muszą zostać dostarczone przed pierwszym narysowaniem widoku. Można wstawić odpowiedni kod do funkcji OnInitialUpdate w klasie widoku. Wymagane informacje można dostarczyć korzystając z funkcji SetScrollSizes o następującym prototypie: "void SetScrollSizes(int MapMode, SIZE Total, const SIZE & Page = sizeDefault, const SIZE & Line = sizeDefault);" gdzie:
  • "MapMode" może mieć następujące wartości:
    • "MM_TEXT",
    • "MM_LOENGLISH",
    • "LO_METRIC",
    • "MM_TWIPS",
    • "MM_HEINGLISH",
    • "MM_HIMETRIC",
  • "Total" to całkowity obszar rysowania,
  • "Page" definiuje odległość w poziomie i w pionie o jaką przewinąć stronę,
  • "Line" definiuje odległość w poziomie i w pionie o jak przewinąć linie.
Aby wyświetlić menu kontekstowe należy użyć funkcji TrackPopupMenu z klasy CMenu. Jej pierwszy argument to suma bitowa dwóch wartości. Lewa może posiadać następujące opcje:
  • "TPM_CENTERALIGN": wyśrodkowuje menu w poziomie względem współrzędnej x podanej jako drugi argument funkcji,
  • "TPM_LEFTALIGN": umieszcza menu tak, że jego lewa strona jest wyrównana względem współrzędnej z podanej jako drugi argument funkcji,
  • "TPM_RIGHALIGN": umieszcza menu tak, że jego prawa strona jest wyrównana względem współrzędnej x podanej jako drugi argument funkcji,
Prawa natomiast to wybór spośród:
  • "TPM_LEFTBUTTON": menu kontekstowe śledzi lewy przycisk myszy,
  • "TPM_RIGHTBUTTON": menu kontekstowe śledzi prawy przycisk myszy.
Większość programów dla systemu Windows używa okien dialogowych do obsługi części danych wejściowych. Wybieramy opcję z menu i pojawia nam się okno dialogowe z różnymi kontrolkami, w których podajemy informacje. Większość kontrolek należy do jednej z przedstawionych niżej kategorii:
  • kontrolki statyczne: używane są dostarczania tytułów lub informacji opisowych,
  • przyciski: dostarczają mechanizm wprowadzania danych jednym kliknięciem,
  • paski przewijania: zwykle używane do przewijania tekstu lub obrazów,
  • pola list: zawierają listę dostępnych możliwości wyboru,
  • kontrolki edycji: pozwalają wprowadzić lub edytować wyświetlany tekst,
  • listy kombinowane: przedstawiają listę dostępnych opcji, które można wybrać oraz dają możliwość samodzielnego wprowadzania tekstu.
Skalowanie w systemie Windows zwykle wiąże się z wykorzystaniem jednego ze skalowalnych trybów mapowania:
  • "MM_ISOTROPIC": w tym trybie Windows wymusza aby współczynnik skali dla osi x i y były równe, 
  • "MM_ANISOTROPIC": niezależne skalowanie osi x i y.
Sposób w jaki logiczne współrzędne są zamieniane na współrzędne urządzenia jest zależny od następujących parametrów:
  • "Window Origin": logiczne współrzędne lewego górnego rogu okna ustawiane przez wywołanie funkcji SetWindowOrg klasy CDC,
  • "Window Entent": rozmiar okna określony we współrzędnych logicznych przez funkcję SetWindowExt klasy CDC,
  • "Viewport Origin": współrzędne lewego górnego rogu okna we współrzędnych urządzenia (pikselach) ustawiane przez funkcję SetViewportOrg klasy CDC,
  • "Viewport Entent": rozmiar okna we współrzędnych urządzenia (pikselach) ustawiany przez funkcję SetViewportExt klasy CDC.
Czasem zachodzi potrzeba wyświetlania na bieżąco jakichś informacji w oknie aplikacji. Można to zrobić na pasku stanu, który domyślnie pojawia się na dole okna. Pasek ten posiada segmenty zwane polami. Do domyślnie dostarczonego przez kreatora aplikacji paska stanu można pisać uzyskując dostęp do zmiennej "m_wndStatusBar" obiektu CMainFrame dla aplikacji. Składowa "m_wndStatusBar" w CMainFrame jest egzemplarzem klasy CStatusBar. Możemy użyć tej klasy do zaimplementowania własnych pasków stanu. Definiuje ona pasek sterowania z wieloma polami, w których można wyświetlać informacje. Obiekty typu CStatusBar dostarczają ten sam zestaw funkcji co wspólne paski stanu systemu Windows poprzez funkcję składową GetStatusBarCtrl. Dla każdej ze wspólnych kontrolek systemu Windows istnieje klasa MFC, która ją kapsułkuje (ta dla wspólnej kontrolki paska stanu to CStatusBarCtrl). Aby ustawić początkowy tekst paska stanu używamy funkcji SetText należącej do klasy CStatusBarCtrl. Pierwszy jej argument to łańcuch tekstu, która ma zostać napisany, drugi to indeks części, która ma zawierać łańcuch, a trzeci może być jedną z poniższych stałych:
  • 0: tekst posiada ramkę, która jest zagłębiona w pasku zadań,
  • "SET_NOBORDERS": tekst jest pisany bez obramowania,
  • "SET_OWNERDRAW": tekst jest rysowany przez okno macierzyste,
  • "SET_POPUP": tekst ma obramowanie, które wygląda jakby wystawało z paska zadań.
Jeżeli chodzi o serializację dokumentu to kod za to odpowiedzialny został zawarty w klasie CMyDoc i obejmuje:
  • makrodefinicję "DECLARE_DYNCREATE", która umożliwia dynamiczne tworzenie obiektów klasy CMyDoc przez platformę aplikacji podczas procesu serializacji wejścia,
  • funkcję składową Serialize, która jest funkcją wirtualną i jest wywoływana w celu przeprowadzenia operacji serializacji wejścia i wyjścia na danych składowych klasy (każda serializowalna klasa musi ją zawierać),
  • domyślny konstruktor klasy wykorzystywany przez platformę do składania obiektu podczas czytania z pliku, a poskładany obiekt jest następnie wypełniany danymi z pliku w celu ustawienia wartości danych składowych obiektu.
Jeżeli chodzi o drukowanie dokumentu to ono sterowane przez bieżący widok. Oto logika tego procesu:
  • funkcja OnPreparePrinting (składowa widoku) oblicza liczbę stron i wywołuje funkcję DoPreparePrinting,
  • funkcja OnBeginPrinting (składowa widoku) alokuje zasoby Graphical Device Interface,
  • funkcja StartDoc z klasy CDC,
  • funkcja OnPrepareDC (składowa widoku) zmienia początek układu współrzędnych wziernika i ustawia atrybuty kontekstu urządzenia,
  • rozpoczęcie pętli, która wykonuje się dopóki są jeszcze jakieś strony,
  • funkcja StartPage klasy CDC,
  • funkcja OnPrint (składowa widoku) drukuje nagłówki, stopki oraz bieżącą stronę,
  • funkcja EndPage klasy CDC,
  • koniec pętli,
  • funkcja EndDoc klasy CDC,
  • funkcja OnEndPrinting (składowa widoku) zwalniająca zasoby Graphical User Interface.
Aby wypisać nazwę pliku dokument stosujemy funkcję TextOut klasy CDC. Dodatkowo możemy określić położenie tekstu względem prostokąta otaczającego za pomocą SetTextAlign i jej następujących wartości argumentów:
  • "TA_LEFT",
  • "TA_RIGHT",
  • "TA_CENTER",
  • "TA_TOP",
  • "TA_BOTTOM",
  • "TA_BASELINE": wyrównuje linię odniesienia czcionki użytej dla tekstu z punktem określającym pozycję tekstu.

Obiekt klasy CPrintInfo odgrywa podstawową rolę w procesie drukowania. Oto jej dane składowe:
  • "m_PD": wskaźnik do obiektu CPrintDialog, który wyświetla okno dialogowe drukowania,
  • "m_bDirect": jest ustawiana na "TRUE" przez platformę jeżeli operacja drukowania ma pominąć okno dialogowe drukowania (w przeciwnym razie ma wartość "FALSE"),
  • "m_bPreview": składowa typu BOOL, której wartość to "TRUE" jeżeli wybrano "Print Preview" z menu "File" (w przeciwnym razie "FALSE"),
  • "m_bContinuePrinting": składowa typu BOOL jest ustawiona na "TRUE" jeżeli platforma kontynuuje pętlę drukowania przedstawioną na schemacie, a "FALSE" jeżeli pętla jest skończona,
  • "m_CurPage": wartość typu UINT przechowująca numer bieżącej strony,
  • "m_nNumPreviewPages": wartość typu UINT określająca liczbę stron wyświetlanych w oknie podglądu wydruku,
  • "m_lpUserData": jest okna typu LPVOID i przechowuje wskaźnik do obiektu, który tworzysz,
  • SetMinPage: funkcja ustawiająca numer pierwszej strony dokumentu,
  • SetMaxPage: funkcja ustawiająca numer ostatniej strony dokumentu,
  • GetMinPage: zwraca numer pierwszej strony dokumentu,
  • GetMaxPage: zwraca numer ostatniej strony dokumentu,
  • GetFromPage: zwraca numer pierwszej strony dokumentu, który ma zostać wydrukowany,
  • GetToPage: zwraca numer ostatniej strony dokumentu, który ma zostać wydrukowany.
Aby utworzyć w Visual Studio bibliotekę rozszerzającą DLL w celu dodania zestawu klas do MFC należy:
  • otworzyć okno tworzenia nowego projektu,
  • wybrać jako szablon "MFC", a następnie "MFC DLL",
  • w polu "Name:" podać nazwę biblioteki (w naszym przypadku będzie to "ExtDLLMy"),
  • kliknąć "OK",
  • w sekcji "Application Setting" zaznaczyć "MFC extension DLL",
  • kliknąć "Finish".
Kreator wygeneruje dla nas potrzebne pliki jednak dwa z nich są kluczowe dla implementacji naszej DLL, a mianowicie:
  • "ExtDLLMy.cpp": zawiera funkcję DllMain i jest głównym plikiem źródłowym biblioteki,
  • "ExtDLLMy.def": informacje z tego pliku są używane podczas kompilacji (zawiera on nazwę DLL, a także można do niego dodać definicję tych elementów DLL, które mają być dostępne dla programów korzystających z biblioteki).
Źródło: Horton I., Visual Studio 2005. Od podstaw, Helion SA, 2007