1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        samples/printing.cpp
3 // Purpose:     Printing demo for wxWidgets
4 // Author:      Julian Smart
5 // Modified by: Francesco Montorsi
6 // Created:     1995
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13 
14 #ifdef __BORLANDC__
15     #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19     #include "wx/wx.h"
20     #include "wx/log.h"
21 #endif
22 
23 #if !wxUSE_PRINTING_ARCHITECTURE
24     #error "You must set wxUSE_PRINTING_ARCHITECTURE to 1 in setup.h, and recompile the library."
25 #endif
26 
27 #include <ctype.h>
28 #include "wx/metafile.h"
29 #include "wx/print.h"
30 #include "wx/printdlg.h"
31 #include "wx/image.h"
32 #include "wx/accel.h"
33 
34 #if wxUSE_POSTSCRIPT
35     #include "wx/generic/printps.h"
36     #include "wx/generic/prntdlgg.h"
37 #endif
38 
39 #if wxUSE_GRAPHICS_CONTEXT
40     #include "wx/graphics.h"
41 #endif
42 
43 #ifdef __WXMAC__
44     #include "wx/osx/printdlg.h"
45 #endif
46 
47 #include "printing.h"
48 
49 #ifndef wxHAS_IMAGES_IN_RESOURCES
50     #include "../sample.xpm"
51 #endif
52 
53 // Global print data, to remember settings during the session
54 wxPrintData *g_printData = NULL;
55 
56 // Global page setup data
57 wxPageSetupDialogData* g_pageSetupData = NULL;
58 
59 
60 
61 // ----------------------------------------------------------------------------
62 // MyApp
63 // ----------------------------------------------------------------------------
64 
IMPLEMENT_APP(MyApp)65 IMPLEMENT_APP(MyApp)
66 
67 bool MyApp::OnInit(void)
68 {
69     if ( !wxApp::OnInit() )
70         return false;
71 
72     wxInitAllImageHandlers();
73 
74 
75     // init global objects
76     // -------------------
77 
78     g_printData = new wxPrintData;
79 
80     // You could set an initial paper size here
81 #if 0
82     g_printData->SetPaperId(wxPAPER_LETTER); // for Americans
83     g_printData->SetPaperId(wxPAPER_A4);    // for everyone else
84 #endif
85 
86     g_pageSetupData = new wxPageSetupDialogData;
87 
88     // copy over initial paper size from print record
89     (*g_pageSetupData) = *g_printData;
90 
91     // Set some initial page margins in mm.
92     g_pageSetupData->SetMarginTopLeft(wxPoint(15, 15));
93     g_pageSetupData->SetMarginBottomRight(wxPoint(15, 15));
94 
95 
96     // init local GUI objects
97     // ----------------------
98 
99 #if 0
100     wxImage image( wxT("test.jpg") );
101     image.SetAlpha();
102     int i,j;
103     for (i = 0; i < image.GetWidth(); i++)
104        for (j = 0; j < image.GetHeight(); j++)
105           image.SetAlpha( i, j, 50 );
106     m_bitmap = image;
107 #endif
108     m_angle = 30;
109     m_testFont.Create(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
110 
111 
112     // Create the main frame window
113     // ----------------------------
114 
115     MyFrame* frame = new MyFrame((wxFrame *) NULL, wxT("wxWidgets Printing Demo"),
116                                  wxPoint(0, 0), wxSize(400, 400));
117 
118     frame->Centre(wxBOTH);
119     frame->Show();
120 
121     return true;
122 }
123 
OnExit()124 int MyApp::OnExit()
125 {
126     delete g_printData;
127     delete g_pageSetupData;
128 
129     return wxApp::OnExit();
130 }
131 
Draw(wxDC & dc)132 void MyApp::Draw(wxDC&dc)
133 {
134     // This routine just draws a bunch of random stuff on the screen so that we
135     // can check that different types of object are being drawn consistently
136     // between the screen image, the print preview image (at various zoom
137     // levels), and the printed page.
138     dc.SetBackground(*wxWHITE_BRUSH);
139     // dc.Clear();
140     dc.SetFont(m_testFont);
141 
142     // dc.SetBackgroundMode(wxTRANSPARENT);
143 
144     dc.SetPen(*wxBLACK_PEN);
145     dc.SetBrush(*wxLIGHT_GREY_BRUSH);
146 
147     dc.DrawRectangle(0, 0, 230, 350);
148     dc.DrawLine(0, 0, 229, 349);
149     dc.DrawLine(229, 0, 0, 349);
150     dc.SetBrush(*wxTRANSPARENT_BRUSH);
151 
152     dc.SetBrush(*wxCYAN_BRUSH);
153     dc.SetPen(*wxRED_PEN);
154 
155     dc.DrawRoundedRectangle(0, 20, 200, 80, 20);
156 
157     dc.DrawText( wxT("Rectangle 200 by 80"), 40, 40);
158 
159     dc.SetPen( wxPen(*wxBLACK, 0, wxPENSTYLE_DOT_DASH) );
160     dc.DrawEllipse(50, 140, 100, 50);
161     dc.SetPen(*wxRED_PEN);
162 
163     dc.DrawText( wxT("Test message: this is in 10 point text"), 10, 180);
164 
165 #if wxUSE_UNICODE
166     const char *test = "Hebrew    שלום -- Japanese (日本語)";
167     wxString tmp = wxConvUTF8.cMB2WC( test );
168     dc.DrawText( tmp, 10, 200 );
169 #endif
170 
171     wxPoint points[5];
172     points[0].x = 0;
173     points[0].y = 0;
174     points[1].x = 20;
175     points[1].y = 0;
176     points[2].x = 20;
177     points[2].y = 20;
178     points[3].x = 10;
179     points[3].y = 20;
180     points[4].x = 10;
181     points[4].y = -20;
182     dc.DrawPolygon( 5, points, 20, 250, wxODDEVEN_RULE );
183     dc.DrawPolygon( 5, points, 50, 250, wxWINDING_RULE );
184 
185     dc.DrawArc( 20, 330, 40, 300, 20, 300 );
186     {
187         wxDCBrushChanger changeBrush(dc, *wxTRANSPARENT_BRUSH);
188         dc.DrawArc( 60, 330, 80, 300, 60, 300 );
189     }
190 
191     dc.DrawEllipticArc( 80, 250, 60, 30, 0.0, 270.0 );
192 
193     points[0].x = 150;
194     points[0].y = 250;
195     points[1].x = 180;
196     points[1].y = 250;
197     points[2].x = 180;
198     points[2].y = 220;
199     points[3].x = 200;
200     points[3].y = 220;
201     dc.DrawSpline( 4, points );
202 
203     wxString str;
204     int i = 0;
205     str.Printf( wxT("---- Text at angle %d ----"), i );
206     dc.DrawRotatedText( str, 100, 300, i );
207 
208     i = m_angle;
209     str.Printf( wxT("---- Text at angle %d ----"), i );
210     dc.DrawRotatedText( str, 100, 300, i );
211 
212     wxIcon my_icon = wxICON(sample);
213 
214     dc.DrawIcon( my_icon, 100, 100);
215 
216     if (m_bitmap.IsOk())
217         dc.DrawBitmap( m_bitmap, 10, 10 );
218 
219 #if wxUSE_GRAPHICS_CONTEXT
220     wxGraphicsContext *gc = NULL;
221 
222     wxPrinterDC *printer_dc = wxDynamicCast( &dc, wxPrinterDC );
223     if (printer_dc)
224         gc = wxGraphicsContext::Create( *printer_dc );
225 
226     wxWindowDC *window_dc = wxDynamicCast( &dc, wxWindowDC );
227     if (window_dc)
228         gc = wxGraphicsContext::Create( *window_dc );
229 
230 #ifdef __WXMSW__
231     wxEnhMetaFileDC *emf_dc = wxDynamicCast( &dc, wxEnhMetaFileDC );
232     if (emf_dc)
233         gc = wxGraphicsContext::Create( *emf_dc );
234 #endif
235 
236     if (gc)
237     {
238         // make a path that contains a circle and some lines, centered at 100,100
239         gc->SetPen( *wxRED_PEN );
240 
241         wxGraphicsPath path = gc->CreatePath();
242         path.AddCircle( 50.0, 50.0, 50.0 );
243         path.MoveToPoint(0.0, 50.0);
244         path.AddLineToPoint(100.0, 50.0);
245         path.MoveToPoint(50.0, 0.0);
246         path.AddLineToPoint(50.0, 100.0 );
247         path.CloseSubpath();
248         path.AddRectangle(25.0, 25.0, 50.0, 50.0);
249 
250         gc->StrokePath(path);
251 
252         // draw some text
253         wxString text("Text by wxGraphicsContext");
254         gc->SetFont( m_testFont, *wxBLACK );
255         gc->DrawText(text, 25.0, 60.0);
256 
257         // draw rectangle around the text
258         double w, h, d, el;
259         gc->GetTextExtent(text, &w, &h, &d, &el);
260         gc->SetPen( *wxBLACK_PEN );
261         gc->DrawRectangle(25.0, 60.0, w, h);
262 
263         delete gc;
264     }
265 #endif
266 }
267 
268 
269 // ----------------------------------------------------------------------------
270 // MyFrame
271 // ----------------------------------------------------------------------------
272 
wxBEGIN_EVENT_TABLE(MyFrame,wxFrame)273 wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
274     EVT_MENU(wxID_EXIT, MyFrame::OnExit)
275     EVT_MENU(wxID_PRINT, MyFrame::OnPrint)
276     EVT_MENU(wxID_PREVIEW, MyFrame::OnPrintPreview)
277     EVT_MENU(WXPRINT_PAGE_SETUP, MyFrame::OnPageSetup)
278     EVT_MENU(wxID_ABOUT, MyFrame::OnPrintAbout)
279 #if wxUSE_POSTSCRIPT
280     EVT_MENU(WXPRINT_PRINT_PS, MyFrame::OnPrintPS)
281     EVT_MENU(WXPRINT_PREVIEW_PS, MyFrame::OnPrintPreviewPS)
282     EVT_MENU(WXPRINT_PAGE_SETUP_PS, MyFrame::OnPageSetupPS)
283 #endif
284 #ifdef __WXMAC__
285     EVT_MENU(WXPRINT_PAGE_MARGINS, MyFrame::OnPageMargins)
286 #endif
287     EVT_MENU(WXPRINT_ANGLEUP, MyFrame::OnAngleUp)
288     EVT_MENU(WXPRINT_ANGLEDOWN, MyFrame::OnAngleDown)
289 
290     EVT_MENU_RANGE(WXPRINT_FRAME_MODAL_APP,
291                    WXPRINT_FRAME_MODAL_NON,
292                    MyFrame::OnPreviewFrameModalityKind)
293 wxEND_EVENT_TABLE()
294 
295 MyFrame::MyFrame(wxFrame *frame, const wxString&title, const wxPoint&pos, const wxSize&size)
296         : wxFrame(frame, wxID_ANY, title, pos, size)
297 {
298     m_canvas = NULL;
299     m_previewModality = wxPreviewFrame_AppModal;
300 
301 #if wxUSE_STATUSBAR
302     // Give us a status line
303     CreateStatusBar(2);
304     SetStatusText(wxT("Printing demo"));
305 #endif // wxUSE_STATUSBAR
306 
307     // Load icon and bitmap
308     SetIcon( wxICON( sample) );
309 
310     // Make a menubar
311     wxMenu *file_menu = new wxMenu;
312 
313     file_menu->Append(wxID_PRINT, wxT("&Print..."),                 wxT("Print"));
314     file_menu->Append(WXPRINT_PAGE_SETUP, wxT("Page Set&up..."),    wxT("Page setup"));
315 #ifdef __WXMAC__
316     file_menu->Append(WXPRINT_PAGE_MARGINS, wxT("Page Margins..."), wxT("Page margins"));
317 #endif
318     file_menu->Append(wxID_PREVIEW, wxT("Print Pre&view"),          wxT("Preview"));
319 
320     wxMenu * const menuModalKind = new wxMenu;
321     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_APP, "&App modal");
322     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_WIN, "&Window modal");
323     menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_NON, "&Not modal");
324     file_menu->AppendSubMenu(menuModalKind, "Preview frame &modal kind");
325 #if wxUSE_ACCEL
326     // Accelerators
327     wxAcceleratorEntry entries[1];
328     entries[0].Set(wxACCEL_CTRL, (int) 'V', wxID_PREVIEW);
329     wxAcceleratorTable accel(1, entries);
330     SetAcceleratorTable(accel);
331 #endif
332 
333 #if wxUSE_POSTSCRIPT
334     file_menu->AppendSeparator();
335     file_menu->Append(WXPRINT_PRINT_PS, wxT("Print PostScript..."),           wxT("Print (PostScript)"));
336     file_menu->Append(WXPRINT_PAGE_SETUP_PS, wxT("Page Setup PostScript..."), wxT("Page setup (PostScript)"));
337     file_menu->Append(WXPRINT_PREVIEW_PS, wxT("Print Preview PostScript"),    wxT("Preview (PostScript)"));
338 #endif
339 
340     file_menu->AppendSeparator();
341     file_menu->Append(WXPRINT_ANGLEUP, wxT("Angle up\tAlt-U"),                wxT("Raise rotated text angle"));
342     file_menu->Append(WXPRINT_ANGLEDOWN, wxT("Angle down\tAlt-D"),            wxT("Lower rotated text angle"));
343     file_menu->AppendSeparator();
344     file_menu->Append(wxID_EXIT, wxT("E&xit"),                                wxT("Exit program"));
345 
346     wxMenu *help_menu = new wxMenu;
347     help_menu->Append(wxID_ABOUT, wxT("&About"),                              wxT("About this demo"));
348 
349     wxMenuBar *menu_bar = new wxMenuBar;
350 
351     menu_bar->Append(file_menu, wxT("&File"));
352     menu_bar->Append(help_menu, wxT("&Help"));
353 
354     // Associate the menu bar with the frame
355     SetMenuBar(menu_bar);
356 
357 
358     // create the canvas
359     // -----------------
360 
361     m_canvas = new MyCanvas(this, wxPoint(0, 0), wxSize(100, 100),
362                             wxRETAINED|wxHSCROLL|wxVSCROLL);
363 
364     // Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction
365     m_canvas->SetScrollbars(20, 20, 50, 50);
366 }
367 
OnExit(wxCommandEvent & WXUNUSED (event))368 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
369 {
370     Close(true /*force closing*/);
371 }
372 
OnPrint(wxCommandEvent & WXUNUSED (event))373 void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
374 {
375     wxPrintDialogData printDialogData(* g_printData);
376 
377     wxPrinter printer(&printDialogData);
378     MyPrintout printout(this, wxT("My printout"));
379     if (!printer.Print(this, &printout, true /*prompt*/))
380     {
381         if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
382         {
383             wxLogError(wxT("There was a problem printing. Perhaps your current printer is not set correctly?"));
384         }
385         else
386         {
387             wxLogMessage(wxT("You canceled printing"));
388         }
389     }
390     else
391     {
392         (*g_printData) = printer.GetPrintDialogData().GetPrintData();
393     }
394 }
395 
OnPrintPreview(wxCommandEvent & WXUNUSED (event))396 void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
397 {
398     // Pass two printout objects: for preview, and possible printing.
399     wxPrintDialogData printDialogData(* g_printData);
400     wxPrintPreview *preview =
401         new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
402     if (!preview->IsOk())
403     {
404         delete preview;
405         wxLogError(wxT("There was a problem previewing.\nPerhaps your current printer is not set correctly?"));
406         return;
407     }
408 
409     wxPreviewFrame *frame =
410         new wxPreviewFrame(preview, this, wxT("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
411     frame->Centre(wxBOTH);
412     frame->InitializeWithModality(m_previewModality);
413     frame->Show();
414 }
415 
OnPageSetup(wxCommandEvent & WXUNUSED (event))416 void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
417 {
418     (*g_pageSetupData) = *g_printData;
419 
420     wxPageSetupDialog pageSetupDialog(this, g_pageSetupData);
421     pageSetupDialog.ShowModal();
422 
423     (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
424     (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
425 }
426 
427 #if wxUSE_POSTSCRIPT
OnPrintPS(wxCommandEvent & WXUNUSED (event))428 void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
429 {
430     wxPrintDialogData printDialogData(* g_printData);
431 
432     wxPostScriptPrinter printer(&printDialogData);
433     MyPrintout printout(this, wxT("My printout"));
434     printer.Print(this, &printout, true/*prompt*/);
435 
436     (*g_printData) = printer.GetPrintDialogData().GetPrintData();
437 }
438 
OnPrintPreviewPS(wxCommandEvent & WXUNUSED (event))439 void MyFrame::OnPrintPreviewPS(wxCommandEvent& WXUNUSED(event))
440 {
441     // Pass two printout objects: for preview, and possible printing.
442     wxPrintDialogData printDialogData(* g_printData);
443     wxPrintPreview *preview = new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
444     wxPreviewFrame *frame =
445         new wxPreviewFrame(preview, this, wxT("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
446     frame->Centre(wxBOTH);
447     frame->Initialize();
448     frame->Show();
449 }
450 
OnPageSetupPS(wxCommandEvent & WXUNUSED (event))451 void MyFrame::OnPageSetupPS(wxCommandEvent& WXUNUSED(event))
452 {
453     (*g_pageSetupData) = * g_printData;
454 
455     wxGenericPageSetupDialog pageSetupDialog(this, g_pageSetupData);
456     pageSetupDialog.ShowModal();
457 
458     (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
459     (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
460 }
461 #endif
462 
463 #ifdef __WXMAC__
OnPageMargins(wxCommandEvent & WXUNUSED (event))464 void MyFrame::OnPageMargins(wxCommandEvent& WXUNUSED(event))
465 {
466     (*g_pageSetupData) = *g_printData;
467 
468     wxMacPageMarginsDialog pageMarginsDialog(this, g_pageSetupData);
469     pageMarginsDialog.ShowModal();
470 
471     (*g_printData) = pageMarginsDialog.GetPageSetupDialogData().GetPrintData();
472     (*g_pageSetupData) = pageMarginsDialog.GetPageSetupDialogData();
473 }
474 #endif
475 
OnPrintAbout(wxCommandEvent & WXUNUSED (event))476 void MyFrame::OnPrintAbout(wxCommandEvent& WXUNUSED(event))
477 {
478     (void)wxMessageBox(wxT("wxWidgets printing demo\nAuthor: Julian Smart"),
479                        wxT("About wxWidgets printing demo"), wxOK|wxCENTRE);
480 }
481 
OnAngleUp(wxCommandEvent & WXUNUSED (event))482 void MyFrame::OnAngleUp(wxCommandEvent& WXUNUSED(event))
483 {
484     wxGetApp().IncrementAngle();
485     m_canvas->Refresh();
486 }
487 
OnAngleDown(wxCommandEvent & WXUNUSED (event))488 void MyFrame::OnAngleDown(wxCommandEvent& WXUNUSED(event))
489 {
490     wxGetApp().DecrementAngle();
491     m_canvas->Refresh();
492 }
493 
OnPreviewFrameModalityKind(wxCommandEvent & event)494 void MyFrame::OnPreviewFrameModalityKind(wxCommandEvent& event)
495 {
496     m_previewModality = static_cast<wxPreviewFrameModalityKind>(
497                             wxPreviewFrame_AppModal +
498                                 (event.GetId() - WXPRINT_FRAME_MODAL_APP));
499 }
500 
501 // ----------------------------------------------------------------------------
502 // MyCanvas
503 // ----------------------------------------------------------------------------
504 
wxBEGIN_EVENT_TABLE(MyCanvas,wxScrolledWindow)505 wxBEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
506   //  EVT_PAINT(MyCanvas::OnPaint)
507 wxEND_EVENT_TABLE()
508 
509 MyCanvas::MyCanvas(wxFrame *frame, const wxPoint&pos, const wxSize&size, long style)
510     : wxScrolledWindow(frame, wxID_ANY, pos, size, style)
511 {
512     SetBackgroundColour(*wxWHITE);
513 }
514 
515 //void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(evt))
OnDraw(wxDC & dc)516 void MyCanvas::OnDraw(wxDC& dc)
517 {
518     //wxPaintDC dc(this);
519     wxGetApp().Draw(dc);
520 }
521 
522 
523 // ----------------------------------------------------------------------------
524 // MyPrintout
525 // ----------------------------------------------------------------------------
526 
OnPrintPage(int page)527 bool MyPrintout::OnPrintPage(int page)
528 {
529     wxDC *dc = GetDC();
530     if (dc)
531     {
532         if (page == 1)
533             DrawPageOne();
534         else if (page == 2)
535             DrawPageTwo();
536 
537         // Draw page numbers at top left corner of printable area, sized so that
538         // screen size of text matches paper size.
539         MapScreenSizeToPage();
540 
541         dc->DrawText(wxString::Format(wxT("PAGE %d"), page), 0, 0);
542 
543         return true;
544     }
545     else
546         return false;
547 }
548 
OnBeginDocument(int startPage,int endPage)549 bool MyPrintout::OnBeginDocument(int startPage, int endPage)
550 {
551     if (!wxPrintout::OnBeginDocument(startPage, endPage))
552         return false;
553 
554     return true;
555 }
556 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)557 void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
558 {
559     *minPage = 1;
560     *maxPage = 2;
561     *selPageFrom = 1;
562     *selPageTo = 2;
563 }
564 
HasPage(int pageNum)565 bool MyPrintout::HasPage(int pageNum)
566 {
567     return (pageNum == 1 || pageNum == 2);
568 }
569 
DrawPageOne()570 void MyPrintout::DrawPageOne()
571 {
572     // You might use THIS code if you were scaling graphics of known size to fit
573     // on the page. The commented-out code illustrates different ways of scaling
574     // the graphics.
575 
576     // We know the graphic is 230x350. If we didn't know this, we'd need to
577     // calculate it.
578     wxCoord maxX = 230;
579     wxCoord maxY = 350;
580 
581     // This sets the user scale and origin of the DC so that the image fits
582     // within the paper rectangle (but the edges could be cut off by printers
583     // that can't print to the edges of the paper -- which is most of them. Use
584     // this if your image already has its own margins.
585 //    FitThisSizeToPaper(wxSize(maxX, maxY));
586 //    wxRect fitRect = GetLogicalPaperRect();
587 
588     // This sets the user scale and origin of the DC so that the image fits
589     // within the page rectangle, which is the printable area on Mac and MSW
590     // and is the entire page on other platforms.
591 //    FitThisSizeToPage(wxSize(maxX, maxY));
592 //    wxRect fitRect = GetLogicalPageRect();
593 
594     // This sets the user scale and origin of the DC so that the image fits
595     // within the page margins as specified by g_PageSetupData, which you can
596     // change (on some platforms, at least) in the Page Setup dialog. Note that
597     // on Mac, the native Page Setup dialog doesn't let you change the margins
598     // of a wxPageSetupDialogData object, so you'll have to write your own dialog or
599     // use the Mac-only wxMacPageMarginsDialog, as we do in this program.
600     FitThisSizeToPageMargins(wxSize(maxX, maxY), *g_pageSetupData);
601     wxRect fitRect = GetLogicalPageMarginsRect(*g_pageSetupData);
602 
603     // This sets the user scale and origin of the DC so that the image appears
604     // on the paper at the same size that it appears on screen (i.e., 10-point
605     // type on screen is 10-point on the printed page) and is positioned in the
606     // top left corner of the page rectangle (just as the screen image appears
607     // in the top left corner of the window).
608 //    MapScreenSizeToPage();
609 //    wxRect fitRect = GetLogicalPageRect();
610 
611     // You could also map the screen image to the entire paper at the same size
612     // as it appears on screen.
613 //    MapScreenSizeToPaper();
614 //    wxRect fitRect = GetLogicalPaperRect();
615 
616     // You might also wish to do you own scaling in order to draw objects at
617     // full native device resolution. In this case, you should do the following.
618     // Note that you can use the GetLogicalXXXRect() commands to obtain the
619     // appropriate rect to scale to.
620 //    MapScreenSizeToDevice();
621 //    wxRect fitRect = GetLogicalPageRect();
622 
623     // Each of the preceding Fit or Map routines positions the origin so that
624     // the drawn image is positioned at the top left corner of the reference
625     // rectangle. You can easily center or right- or bottom-justify the image as
626     // follows.
627 
628     // This offsets the image so that it is centered within the reference
629     // rectangle defined above.
630     wxCoord xoff = (fitRect.width - maxX) / 2;
631     wxCoord yoff = (fitRect.height - maxY) / 2;
632     OffsetLogicalOrigin(xoff, yoff);
633 
634     // This offsets the image so that it is positioned at the bottom right of
635     // the reference rectangle defined above.
636 //    wxCoord xoff = (fitRect.width - maxX);
637 //    wxCoord yoff = (fitRect.height - maxY);
638 //    OffsetLogicalOrigin(xoff, yoff);
639 
640     wxGetApp().Draw(*GetDC());
641 }
642 
DrawPageTwo()643 void MyPrintout::DrawPageTwo()
644 {
645     // You might use THIS code to set the printer DC to ROUGHLY reflect
646     // the screen text size. This page also draws lines of actual length
647     // 5cm on the page.
648 
649     // Compare this to DrawPageOne(), which uses the really convenient routines
650     // from wxPrintout to fit the screen image onto the printed page. This page
651     // illustrates how to do all the scaling calculations yourself, if you're so
652     // inclined.
653 
654     wxDC *dc = GetDC();
655 
656     // Get the logical pixels per inch of screen and printer
657     int ppiScreenX, ppiScreenY;
658     GetPPIScreen(&ppiScreenX, &ppiScreenY);
659     int ppiPrinterX, ppiPrinterY;
660     GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
661 
662     // This scales the DC so that the printout roughly represents the screen
663     // scaling. The text point size _should_ be the right size but in fact is
664     // too small for some reason. This is a detail that will need to be
665     // addressed at some point but can be fudged for the moment.
666     float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
667 
668     // Now we have to check in case our real page size is reduced (e.g. because
669     // we're drawing to a print preview memory DC)
670     int pageWidth, pageHeight;
671     int w, h;
672     dc->GetSize(&w, &h);
673     GetPageSizePixels(&pageWidth, &pageHeight);
674 
675     // If printer pageWidth == current DC width, then this doesn't change. But w
676     // might be the preview bitmap width, so scale down.
677     float overallScale = scale * (float)(w/(float)pageWidth);
678     dc->SetUserScale(overallScale, overallScale);
679 
680     // Calculate conversion factor for converting millimetres into logical
681     // units. There are approx. 25.4 mm to the inch. There are ppi device units
682     // to the inch. Therefore 1 mm corresponds to ppi/25.4 device units. We also
683     // divide by the screen-to-printer scaling factor, because we need to
684     // unscale to pass logical units to DrawLine.
685 
686     // Draw 50 mm by 50 mm L shape
687     float logUnitsFactor = (float)(ppiPrinterX/(scale*25.4));
688     float logUnits = (float)(50*logUnitsFactor);
689     dc->SetPen(* wxBLACK_PEN);
690     dc->DrawLine(50, 250, (long)(50.0 + logUnits), 250);
691     dc->DrawLine(50, 250, 50, (long)(250.0 + logUnits));
692 
693     dc->SetBackgroundMode(wxTRANSPARENT);
694     dc->SetBrush(*wxTRANSPARENT_BRUSH);
695 
696     { // GetTextExtent demo:
697         wxString words[7] = { wxT("This "), wxT("is "), wxT("GetTextExtent "),
698                              wxT("testing "), wxT("string. "), wxT("Enjoy "), wxT("it!") };
699         wxCoord w, h;
700         long x = 200, y= 250;
701         wxFont fnt(15, wxSWISS, wxNORMAL, wxNORMAL);
702 
703         dc->SetFont(fnt);
704 
705         for (int i = 0; i < 7; i++)
706         {
707             wxString word = words[i];
708             word.Remove( word.Len()-1, 1 );
709             dc->GetTextExtent(word, &w, &h);
710             dc->DrawRectangle(x, y, w, h);
711             dc->GetTextExtent(words[i], &w, &h);
712             dc->DrawText(words[i], x, y);
713             x += w;
714         }
715 
716     }
717 
718     dc->SetFont(wxGetApp().GetTestFont());
719 
720     dc->DrawText(wxT("Some test text"), 200, 300 );
721 
722     // TESTING
723 
724     int leftMargin = 20;
725     int rightMargin = 20;
726     int topMargin = 20;
727     int bottomMargin = 20;
728 
729     int pageWidthMM, pageHeightMM;
730     GetPageSizeMM(&pageWidthMM, &pageHeightMM);
731 
732     float leftMarginLogical = (float)(logUnitsFactor*leftMargin);
733     float topMarginLogical = (float)(logUnitsFactor*topMargin);
734     float bottomMarginLogical = (float)(logUnitsFactor*(pageHeightMM - bottomMargin));
735     float rightMarginLogical = (float)(logUnitsFactor*(pageWidthMM - rightMargin));
736 
737     dc->SetPen(* wxRED_PEN);
738     dc->DrawLine( (long)leftMarginLogical, (long)topMarginLogical,
739         (long)rightMarginLogical, (long)topMarginLogical);
740     dc->DrawLine( (long)leftMarginLogical, (long)bottomMarginLogical,
741         (long)rightMarginLogical,  (long)bottomMarginLogical);
742 
743     WritePageHeader(this, dc, wxT("A header"), logUnitsFactor);
744 }
745 
746 // Writes a header on a page. Margin units are in millimetres.
WritePageHeader(wxPrintout * printout,wxDC * dc,const wxString & text,float mmToLogical)747 bool MyPrintout::WritePageHeader(wxPrintout *printout, wxDC *dc, const wxString&text, float mmToLogical)
748 {
749 #if 0
750     static wxFont *headerFont = (wxFont *) NULL;
751     if (!headerFont)
752     {
753         headerFont = wxTheFontList->FindOrCreateFont(16, wxSWISS, wxNORMAL, wxBOLD);
754     }
755     dc->SetFont(headerFont);
756 #endif
757 
758     int pageWidthMM, pageHeightMM;
759 
760     printout->GetPageSizeMM(&pageWidthMM, &pageHeightMM);
761     wxUnusedVar(pageHeightMM);
762 
763     int leftMargin = 10;
764     int topMargin = 10;
765     int rightMargin = 10;
766 
767     float leftMarginLogical = (float)(mmToLogical*leftMargin);
768     float topMarginLogical = (float)(mmToLogical*topMargin);
769     float rightMarginLogical = (float)(mmToLogical*(pageWidthMM - rightMargin));
770 
771     wxCoord xExtent, yExtent;
772     dc->GetTextExtent(text, &xExtent, &yExtent);
773 
774     float xPos = (float)(((((pageWidthMM - leftMargin - rightMargin)/2.0)+leftMargin)*mmToLogical) - (xExtent/2.0));
775     dc->DrawText(text, (long)xPos, (long)topMarginLogical);
776 
777     dc->SetPen(* wxBLACK_PEN);
778     dc->DrawLine( (long)leftMarginLogical, (long)(topMarginLogical+yExtent),
779                   (long)rightMarginLogical, (long)topMarginLogical+yExtent );
780 
781     return true;
782 }
783