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