Dokumenty wielostronicowe
W tym artykule opisano protokół drukowania systemu Windows i wyjaśniono, jak drukować dokumenty zawierające więcej niż jedną stronę. W tym artykule omówiono następujące tematy:
Protokół drukowania
Aby wydrukować dokument wielostronicowy, struktura i widok wchodzą w interakcje w następujący sposób. Najpierw platforma wyświetla okno dialogowe Drukowanie, tworzy kontekst urządzenia dla drukarki i wywołuje funkcję składową StartDoc obiektu CDC. Następnie dla każdej strony dokumentu struktura wywołuje funkcję CDC
składową StartPage obiektu, instruuje obiekt widoku, aby wydrukował stronę i wywołuje funkcję składową EndPage. Jeśli tryb drukarki należy zmienić przed uruchomieniem określonej strony, widok wywołuje polecenie ResetDC, który aktualizuje strukturę DEVMODE zawierającą informacje o nowym trybie drukarki. Po wydrukowaniu całego dokumentu struktura wywołuje funkcję składową EndDoc .
Zastępowanie funkcji klas widoku
Klasa CView definiuje kilka funkcji składowych, które są wywoływane przez platformę podczas drukowania. Przesłaniając te funkcje w klasie widoków, należy podać połączenia między logiką drukowania platformy a logiką drukowania klasy widoków. W poniższej tabeli wymieniono te funkcje składowe.
Funkcje zastępowalne obiektu CView do drukowania
Nazwisko | Przyczyna zastąpienia |
---|---|
Onprepareprinting | Aby wstawić wartości w oknie dialogowym Drukowanie, szczególnie długość dokumentu |
OnBeginPrinting | Aby przydzielić czcionki lub inne zasoby GDI |
Onpreparedc | Aby dostosować atrybuty kontekstu urządzenia dla danej strony lub przeprowadzić stronicowanie w czasie drukowania |
Onprint | Aby wydrukować daną stronę |
OnEndPrinting | Aby cofnąć przydział zasobów GDI |
Można również wykonywać przetwarzanie związane z drukowaniem w innych funkcjach, ale te funkcje są tymi, które napędzają proces drukowania.
Na poniższej ilustracji przedstawiono kroki związane z procesem drukowania i pokazano, gdzie są wywoływane poszczególne CView
funkcje składowe drukowania. W pozostałej części tego artykułu bardziej szczegółowo opisano większość tych kroków. Dodatkowe części procesu drukowania opisano w artykule Przydzielanie zasobów GDI.
Pętla drukowania
Dzielenie na strony
Struktura przechowuje wiele informacji o zadaniu drukowania w strukturze CPrintInfo . Kilka wartości w sekcji CPrintInfo
dotyczy stronicowania. Te wartości są dostępne, jak pokazano w poniższej tabeli.
Informacje o numerze strony przechowywane w CPrintInfo
Zmienna składowa lub nazwy funkcji |
Numer strony, do których odwołuje się odwołanie |
---|---|
GetMinPage /SetMinPage |
Pierwsza strona dokumentu |
GetMaxPage /SetMaxPage |
Ostatnia strona dokumentu |
GetFromPage |
Pierwsza strona do wydrukowania |
GetToPage |
Ostatnia strona do wydrukowania |
m_nCurPage |
Strona aktualnie drukowana |
Numery stron zaczynają się od 1, czyli pierwsza strona jest numerowana 1, a nie 0. Aby uzyskać więcej informacji na temat tych i innych członków CPrintInfo, zobacz dokumentację MFC.
Na początku procesu drukowania struktura wywołuje funkcję składową OnPreparePrinting widoku, przekazując wskaźnik do CPrintInfo
struktury. Kreator aplikacji udostępnia implementację OnPreparePrinting
, która wywołuje funkcję DoPreparePrinting, inną funkcję składową CView
klasy . DoPreparePrinting
to funkcja, która wyświetla okno dialogowe Drukowanie i tworzy kontekst urządzenia drukarki.
W tym momencie aplikacja nie wie, ile stron znajduje się w dokumencie. Używa ona wartości domyślnych 1 i 0xFFFF dla liczb pierwszej i ostatniej strony dokumentu. Jeśli wiesz, ile stron zawiera dokument, przesłoń OnPreparePrinting
i wywołaj metodę [SetMaxPage]---brokenlink--(reference/cprintinfo-class.md#setmaxpage) dla CPrintInfo
struktury przed wysłaniem jej do DoPreparePrinting
. Pozwala to określić długość dokumentu.
DoPreparePrinting
następnie wyświetla okno dialogowe Drukowanie. Po powrocie CPrintInfo
struktura zawiera wartości określone przez użytkownika. Jeśli użytkownik chce wydrukować tylko wybrany zakres stron, może określić numery stron początkowych i końcowych w oknie dialogowym Drukowanie. Struktura pobiera te wartości przy użyciu GetFromPage
funkcji i GetToPage
CPrintInfo. Jeśli użytkownik nie określi zakresu stron, platforma wywołuje GetMinPage
strukturę i GetMaxPage
używa wartości zwróconych w celu wydrukowania całego dokumentu.
Dla każdej strony dokumentu, która ma zostać wydrukowana, struktura wywołuje dwie funkcje składowe w klasie widoków, OnPrepareDC i OnPrint, a następnie przekazuje do każdej funkcji dwa parametry: wskaźnik do obiektu CDC i wskaźnik do CPrintInfo
struktury. Za każdym razem, gdy wywołania OnPrepareDC
struktury i OnPrint
, przekazuje inną wartość w m_nCurPage składowej CPrintInfo
struktury. W ten sposób struktura informuje widok, która strona powinna zostać wydrukowana.
Funkcja składowa OnPrepareDC jest również używana do wyświetlania ekranu. Powoduje to dostosowanie kontekstu urządzenia przed rozpoczęciem rysowania. OnPrepareDC
pełni podobną rolę w drukowaniu, ale istnieje kilka różnic: najpierw CDC
obiekt reprezentuje kontekst urządzenia drukarki zamiast kontekstu urządzenia ekranu, a drugi obiekt CPrintInfo
jest przekazywany jako drugi parametr. (Ten parametr to Wartość NULL , gdy OnPrepareDC
jest wywoływana dla wyświetlania ekranu). Zastąpij OnPrepareDC
, aby wprowadzić zmiany w kontekście urządzenia na podstawie tego, która strona jest drukowana. Możesz na przykład przenieść źródło widoku i region wycinków, aby upewnić się, że odpowiednia część dokumentu zostanie wydrukowana.
Funkcja składowa OnPrint wykonuje rzeczywiste drukowanie strony. W artykule How Default Printing Is Done (Jak drukowanie domyślne jest wykonywane ) pokazano, jak struktura wywołuje metodę OnDraw z kontekstem urządzenia drukarki do drukowania. Dokładniej mówiąc, struktura wywołuje OnPrint
CPrintInfo
strukturę i kontekst urządzenia oraz OnPrint
przekazuje kontekst urządzenia do OnDraw
elementu . Zastąpij, aby wykonać dowolne renderowanie OnPrint
, które powinno być wykonywane tylko podczas drukowania, a nie do wyświetlania ekranu. Aby na przykład wydrukować nagłówki lub stopki (zobacz artykuł Nagłówki i stopki , aby uzyskać więcej informacji). Następnie wywołaj metodę OnDraw
z przesłonięcia , OnPrint
aby wykonać renderowanie wspólne dla wyświetlania i drukowania ekranu.
Fakt, że OnDraw
renderowanie zarówno dla wyświetlania ekranu, jak i drukowania oznacza, że aplikacja jest WYSIWYG: "To, co widzisz, to, co otrzymujesz". Załóżmy jednak, że nie piszesz aplikacji WYSIWYG. Rozważmy na przykład edytor tekstów, który używa czcionki pogrubionej do drukowania, ale wyświetla kody sterujące wskazujące pogrubiony tekst na ekranie. W takiej sytuacji należy używać OnDraw
wyłącznie do wyświetlania ekranu. Gdy zastąpisz OnPrint
metodę , zastąp wywołanie wywołaniem OnDraw
oddzielnej funkcji rysunku. Ta funkcja rysuje dokument tak, jak pojawia się na papierze, przy użyciu atrybutów, które nie są wyświetlane na ekranie.
Strony drukarki a strony dokumentów
W przypadku odwoływania się do numerów stron czasami konieczne jest rozróżnienie między koncepcją strony drukarki a koncepcją strony dokumentu. Z punktu widzenia drukarki strona jest jednym arkuszem papieru. Jednak jeden arkusz papieru nie musi być równy jednej stronie dokumentu. Jeśli na przykład drukujesz biuletyn, w którym arkusze mają być składane, jeden arkusz papieru może zawierać zarówno pierwsze, jak i ostatnie strony dokumentu. Podobnie, jeśli drukujesz arkusz kalkulacyjny, dokument nie składa się w ogóle ze stron. Zamiast tego jeden arkusz papieru może zawierać wiersze od 1 do 20, kolumn od 6 do 10.
Wszystkie numery stron w strukturze CPrintInfo odwołują się do stron drukarek. Struktura wywołuje i OnPrepareDC
OnPrint
raz dla każdego arkusza papieru, który przejdzie przez drukarkę. Po zastąpieniu funkcji OnPreparePrinting w celu określenia długości dokumentu należy użyć stron drukarki. Jeśli istnieje korespondencja jeden do jednego (oznacza to, że jedna strona drukarki jest równa jednej stronie dokumentu), jest to łatwe. Jeśli z drugiej strony strony dokumentów i strony drukarki nie odpowiadają bezpośrednio, należy je przetłumaczyć. Rozważ na przykład drukowanie arkusza kalkulacyjnego. Podczas zastępowania OnPreparePrinting
należy obliczyć, ile arkuszy papieru będzie wymaganych do wydrukowania całego arkusza kalkulacyjnego, a następnie użyć tej wartości podczas wywoływania SetMaxPage
funkcji składowej CPrintInfo
. Podobnie podczas zastępowania OnPrepareDC
należy przetłumaczyć m_nCurPage na zakres wierszy i kolumn, które będą wyświetlane w danym arkuszu, a następnie odpowiednio dostosować źródło widoku.
Stronicowanie w czasie drukowania
W niektórych sytuacjach klasa widoku może nie wiedzieć z wyprzedzeniem, jak długo dokument ma być wydrukowany. Załóżmy na przykład, że aplikacja nie jest WYSIWYG, więc długość dokumentu na ekranie nie odpowiada jego długości podczas drukowania.
Powoduje to problem podczas zastępowania funkcji OnPreparePrinting dla klasy widoku: nie można przekazać wartości do SetMaxPage
funkcji struktury CPrintInfo , ponieważ nie znasz długości dokumentu. Jeśli użytkownik nie określi numeru strony do zatrzymania korzystania z okna dialogowego Drukowanie, platforma nie wie, kiedy zatrzymać pętlę drukowania. Jedynym sposobem określenia, kiedy zatrzymać pętlę drukowania, jest wydrukowanie dokumentu i sprawdzenie, kiedy się kończy. Klasa widoku musi sprawdzić koniec dokumentu podczas jego drukowania, a następnie poinformować strukturę po osiągnięciu końca.
Struktura opiera się na funkcji OnPrepareDC klasy widoku, aby poinformować ją, kiedy ją zatrzymać. Po każdym wywołaniu metody OnPrepareDC
platforma sprawdza element członkowski CPrintInfo
struktury o nazwie m_bContinuePrinting. Jego wartość domyślna to TRUE. Tak długo, jak to pozostanie, struktura kontynuuje pętlę drukowania. Jeśli jest ustawiona wartość FALSE, platforma zostanie zatrzymana. Aby wykonać stronicowanie w czasie drukowania, zastąpij OnPrepareDC
, aby sprawdzić, czy koniec dokumentu został osiągnięty, i ustaw wartość m_bContinuePrinting na FALSE , gdy ma.
Domyślna implementacja zestawów OnPrepareDC
m_bContinuePrinting wartość FALSE , jeśli bieżąca strona jest większa niż 1. Oznacza to, że jeśli długość dokumentu nie została określona, struktura zakłada, że dokument jest długi. Jedną z konsekwencji jest to, że należy zachować ostrożność, jeśli wywołasz wersję klasy bazowej klasy OnPrepareDC
. Nie należy zakładać, że m_bContinuePrinting będzie mieć wartość TRUE po wywołaniu wersji klasy bazowej.