home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / samples / printing / printing.cpp < prev    next >
C/C++ Source or Header  |  2002-12-16  |  18KB  |  567 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        printing.cpp
  3. // Purpose:     Printing demo for wxWindows
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     1995
  7. // RCS-ID:      $Id: printing.cpp,v 1.29.2.2 2002/12/15 17:25:22 MBN Exp $
  8. // Copyright:   (c) Julian Smart
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13. #pragma implementation
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx/wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22.  
  23. #ifndef WX_PRECOMP
  24. #include "wx/wx.h"
  25. #endif
  26.  
  27. #if !wxUSE_PRINTING_ARCHITECTURE
  28. #error You must set wxUSE_PRINTING_ARCHITECTURE to 1 in setup.h to compile this demo.
  29. #endif
  30.  
  31. // Set this to 1 if you want to test PostScript printing under MSW.
  32. // However, you'll also need to edit src/msw/makefile.nt.
  33. #define wxTEST_POSTSCRIPT_IN_MSW 0
  34.  
  35. #include <ctype.h>
  36. #include "wx/metafile.h"
  37. #include "wx/print.h"
  38. #include "wx/printdlg.h"
  39.  
  40. #include "wx/accel.h"
  41.  
  42. #if wxTEST_POSTSCRIPT_IN_MSW
  43. #include "wx/generic/printps.h"
  44. #include "wx/generic/prntdlgg.h"
  45. #endif
  46.  
  47. #include "printing.h"
  48.  
  49. #ifndef __WXMSW__
  50. #include "mondrian.xpm"
  51. #endif
  52.  
  53. // Declare a frame
  54. MyFrame   *frame = (MyFrame *) NULL;
  55. // int orientation = wxPORTRAIT;
  56.  
  57. // Global print data, to remember settings during the session
  58. wxPrintData *g_printData = (wxPrintData*) NULL ;
  59.  
  60. // Global page setup data
  61. wxPageSetupData* g_pageSetupData = (wxPageSetupData*) NULL;
  62.  
  63. // Main proc
  64. IMPLEMENT_APP(MyApp)
  65.  
  66. // Writes a header on a page. Margin units are in millimetres.
  67. bool WritePageHeader(wxPrintout *printout, wxDC *dc, wxChar *text, float mmToLogical);
  68.  
  69. MyApp::MyApp()
  70. {
  71. }
  72.  
  73. // The `main program' equivalent, creating the windows and returning the
  74. // main frame
  75. bool MyApp::OnInit(void)
  76. {
  77.     m_testFont = new wxFont(10, wxSWISS, wxNORMAL, wxNORMAL);
  78.     
  79.     g_printData = new wxPrintData;
  80.     g_pageSetupData = new wxPageSetupDialogData;
  81.     
  82.     // Create the main frame window
  83.     frame = new MyFrame((wxFrame *) NULL, _T("wxWindows Printing Demo"), wxPoint(0, 0), wxSize(400, 400));
  84.     
  85.     // Give it a status line
  86.     frame->CreateStatusBar(2);
  87.     
  88.     // Load icon and bitmap
  89.     frame->SetIcon( wxICON( mondrian) );
  90.     
  91.     // Make a menubar
  92.     wxMenu *file_menu = new wxMenu;
  93.     
  94.     file_menu->Append(WXPRINT_PRINT, _T("&Print..."),              _T("Print"));
  95.     file_menu->Append(WXPRINT_PRINT_SETUP, _T("Print &Setup..."),              _T("Setup printer properties"));
  96.     file_menu->Append(WXPRINT_PAGE_SETUP, _T("Page Set&up..."),              _T("Page setup"));
  97.     file_menu->Append(WXPRINT_PREVIEW, _T("Print Pre&view"),              _T("Preview"));
  98.     
  99. #if wxUSE_ACCEL
  100.     // Accelerators
  101.     wxAcceleratorEntry entries[1];
  102.     entries[0].Set(wxACCEL_CTRL, (int) 'V', WXPRINT_PREVIEW);
  103.     wxAcceleratorTable accel(1, entries);
  104.     frame->SetAcceleratorTable(accel);
  105. #endif
  106.  
  107. #if defined(__WXMSW__) && wxTEST_POSTSCRIPT_IN_MSW
  108.     file_menu->AppendSeparator();
  109.     file_menu->Append(WXPRINT_PRINT_PS, _T("Print PostScript..."),              _T("Print (PostScript)"));
  110.     file_menu->Append(WXPRINT_PRINT_SETUP_PS, _T("Print Setup PostScript..."),              _T("Setup printer properties (PostScript)"));
  111.     file_menu->Append(WXPRINT_PAGE_SETUP_PS, _T("Page Setup PostScript..."),              _T("Page setup (PostScript)"));
  112.     file_menu->Append(WXPRINT_PREVIEW_PS, _T("Print Preview PostScript"),              _T("Preview (PostScript)"));
  113. #endif
  114.     file_menu->AppendSeparator();
  115.     file_menu->Append(WXPRINT_QUIT, _T("E&xit"),                _T("Exit program"));
  116.     
  117.     wxMenu *help_menu = new wxMenu;
  118.     help_menu->Append(WXPRINT_ABOUT, _T("&About"),              _T("About this demo"));
  119.     
  120.     wxMenuBar *menu_bar = new wxMenuBar;
  121.     
  122.     menu_bar->Append(file_menu, _T("&File"));
  123.     menu_bar->Append(help_menu, _T("&Help"));
  124.     
  125.     // Associate the menu bar with the frame
  126.     frame->SetMenuBar(menu_bar);
  127.     
  128.     MyCanvas *canvas = new MyCanvas(frame, wxPoint(0, 0), wxSize(100, 100), wxRETAINED|wxHSCROLL|wxVSCROLL);
  129.     
  130.     // Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction
  131.     canvas->SetScrollbars(20, 20, 50, 50);
  132.     
  133.     frame->canvas = canvas;
  134.     
  135.     frame->Centre(wxBOTH);
  136.     frame->Show(TRUE);
  137.     
  138.     frame->SetStatusText(_T("Printing demo"));
  139.     
  140.     SetTopWindow(frame);
  141.     
  142.     return TRUE;
  143. }
  144.  
  145. int MyApp::OnExit()
  146. {
  147.     delete wxGetApp().m_testFont;
  148.     delete g_printData;
  149.     delete g_pageSetupData;
  150.     return 1;
  151. }
  152.  
  153. BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  154. EVT_MENU(WXPRINT_QUIT, MyFrame::OnExit)
  155. EVT_MENU(WXPRINT_PRINT, MyFrame::OnPrint)
  156. EVT_MENU(WXPRINT_PREVIEW, MyFrame::OnPrintPreview)
  157. EVT_MENU(WXPRINT_PRINT_SETUP, MyFrame::OnPrintSetup)
  158. EVT_MENU(WXPRINT_PAGE_SETUP, MyFrame::OnPageSetup)
  159. EVT_MENU(WXPRINT_ABOUT, MyFrame::OnPrintAbout)
  160. #if defined(__WXMSW__) && wxTEST_POSTSCRIPT_IN_MSW
  161. EVT_MENU(WXPRINT_PRINT_PS, MyFrame::OnPrintPS)
  162. EVT_MENU(WXPRINT_PREVIEW_PS, MyFrame::OnPrintPreviewPS)
  163. EVT_MENU(WXPRINT_PRINT_SETUP_PS, MyFrame::OnPrintSetupPS)
  164. EVT_MENU(WXPRINT_PAGE_SETUP_PS, MyFrame::OnPageSetupPS)
  165. #endif
  166. END_EVENT_TABLE()
  167.  
  168. // Define my frame constructor
  169. MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
  170. wxFrame(frame, -1, title, pos, size)
  171. {
  172.     canvas = (MyCanvas *) NULL;
  173. }
  174.  
  175. void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
  176. {
  177.     Close(TRUE);
  178. }
  179.  
  180. void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
  181. {
  182.     wxPrintDialogData printDialogData(* g_printData);
  183.  
  184.     wxPrinter printer(& printDialogData);
  185.     MyPrintout printout(_T("My printout"));
  186.     if (!printer.Print(this, &printout, TRUE))
  187.     {
  188.         if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
  189.             wxMessageBox(_T("There was a problem printing.\nPerhaps your current printer is not set correctly?"), _T("Printing"), wxOK);
  190.         else
  191.             wxMessageBox(_T("You canceled printing"), _T("Printing"), wxOK);
  192.     }
  193.     else
  194.     {
  195.         (*g_printData) = printer.GetPrintDialogData().GetPrintData();
  196.     }
  197. }
  198.  
  199. void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
  200. {
  201.     // Pass two printout objects: for preview, and possible printing.
  202.     wxPrintDialogData printDialogData(* g_printData);
  203.     wxPrintPreview *preview = new wxPrintPreview(new MyPrintout, new MyPrintout, & printDialogData);
  204.     if (!preview->Ok())
  205.     {
  206.         delete preview;
  207.         wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
  208.         return;
  209.     }
  210.     
  211.     wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
  212.     frame->Centre(wxBOTH);
  213.     frame->Initialize();
  214.     frame->Show(TRUE);
  215. }
  216.  
  217. void MyFrame::OnPrintSetup(wxCommandEvent& WXUNUSED(event))
  218. {
  219.     wxPrintDialogData printDialogData(* g_printData);
  220.     wxPrintDialog printerDialog(this, & printDialogData);
  221.     
  222.     printerDialog.GetPrintDialogData().SetSetupDialog(TRUE);
  223.     printerDialog.ShowModal();
  224.  
  225.     (*g_printData) = printerDialog.GetPrintDialogData().GetPrintData();
  226. }
  227.  
  228. void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
  229. {
  230.     (*g_pageSetupData) = * g_printData;
  231.  
  232.     wxPageSetupDialog pageSetupDialog(this, g_pageSetupData);
  233.     pageSetupDialog.ShowModal();
  234.     
  235.     (*g_printData) = pageSetupDialog.GetPageSetupData().GetPrintData();
  236.     (*g_pageSetupData) = pageSetupDialog.GetPageSetupData();
  237. }
  238.  
  239. #if defined(__WXMSW__) && wxTEST_POSTSCRIPT_IN_MSW
  240. void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
  241. {
  242.     wxPostScriptPrinter printer(g_printData);
  243.     MyPrintout printout(_T("My printout"));
  244.     printer.Print(this, &printout, TRUE);
  245.  
  246.     (*g_printData) = printer.GetPrintData();
  247. }
  248.  
  249. void MyFrame::OnPrintPreviewPS(wxCommandEvent& WXUNUSED(event))
  250. {
  251.     // Pass two printout objects: for preview, and possible printing.
  252.     wxPrintDialogData printDialogData(* g_printData);
  253.     wxPrintPreview *preview = new wxPrintPreview(new MyPrintout, new MyPrintout, & printDialogData);
  254.     wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
  255.     frame->Centre(wxBOTH);
  256.     frame->Initialize();
  257.     frame->Show(TRUE);
  258. }
  259.  
  260. void MyFrame::OnPrintSetupPS(wxCommandEvent& WXUNUSED(event))
  261. {
  262.     wxPrintDialogData printDialogData(* g_printData);
  263.     wxGenericPrintDialog printerDialog(this, & printDialogData);
  264.  
  265.     printerDialog.GetPrintDialogData().SetSetupDialog(TRUE);
  266.     printerDialog.ShowModal();
  267.  
  268.     (*g_printData) = printerDialog.GetPrintDialogData().GetPrintData();
  269. }
  270.  
  271. void MyFrame::OnPageSetupPS(wxCommandEvent& WXUNUSED(event))
  272. {
  273.     (*g_pageSetupData) = * g_printData;
  274.  
  275.     wxGenericPageSetupDialog pageSetupDialog(this, g_pageSetupData);
  276.     pageSetupDialog.ShowModal();
  277.  
  278.     (*g_printData) = pageSetupDialog.GetPageSetupData().GetPrintData();
  279.     (*g_pageSetupData) = pageSetupDialog.GetPageSetupData();
  280. }
  281. #endif
  282.  
  283.  
  284. void MyFrame::OnPrintAbout(wxCommandEvent& WXUNUSED(event))
  285. {
  286.     (void)wxMessageBox(_T("wxWindows printing demo\nAuthor: Julian Smart"),
  287.         _T("About wxWindows printing demo"), wxOK|wxCENTRE);
  288. }
  289.  
  290. void MyFrame::Draw(wxDC& dc)
  291. {
  292.     dc.SetBackground(*wxWHITE_BRUSH);
  293.     dc.Clear();
  294.     dc.SetFont(* wxGetApp().m_testFont);
  295.     
  296.     dc.SetBackgroundMode(wxTRANSPARENT);
  297.     
  298.     dc.SetBrush(* wxCYAN_BRUSH);
  299.     dc.SetPen(* wxRED_PEN);
  300.     
  301.     dc.DrawRectangle(0, 30, 200, 100);
  302.     
  303.     dc.DrawText( wxT("Rectangle 200 by 100"), 40, 40);
  304.     
  305.     dc.DrawEllipse(50, 140, 100, 50);
  306.     
  307.     dc.DrawText( wxT("Test message: this is in 10 point text"), 10, 180);
  308.     
  309. #if wxUSE_UNICODE
  310.     char *test = "Greek (╬ò╬╗╬╗╬╖╬╜╬╣╬║╬¼) ╬ô╬╡╬╣╬¼ ╧â╬▒╧é -- Hebrew    ╫⌐╫£╫ò╫¥ -- Japanese (µùѵ£¼Φ¬₧)";
  311.     wxString tmp = wxConvUTF8.cMB2WC( test );
  312.     dc.DrawText( tmp, 10, 200 ); 
  313. #endif
  314.     
  315.     dc.SetPen(* wxBLACK_PEN);
  316.     dc.DrawLine(0, 0, 200, 200);
  317.     dc.DrawLine(200, 0, 0, 200);
  318.     
  319.     wxIcon my_icon = wxICON(mondrian) ;
  320.     
  321.     dc.DrawIcon( my_icon, 100, 100);
  322. }
  323.  
  324. void MyFrame::OnSize(wxSizeEvent& event )
  325. {
  326.     wxFrame::OnSize(event);
  327. }
  328.  
  329. BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  330. EVT_MOUSE_EVENTS(MyCanvas::OnEvent)
  331. END_EVENT_TABLE()
  332.  
  333. // Define a constructor for my canvas
  334. MyCanvas::MyCanvas(wxFrame *frame, const wxPoint& pos, const wxSize& size, long style):
  335.     wxScrolledWindow(frame, -1, pos, size, style)
  336. {
  337.     SetBackgroundColour(* wxWHITE);
  338. }
  339.  
  340. MyCanvas::~MyCanvas(void)
  341. {
  342. }
  343.  
  344. // Define the repainting behaviour
  345. void MyCanvas::OnDraw(wxDC& dc)
  346. {
  347.     frame->Draw(dc);
  348. }
  349.  
  350. void MyCanvas::OnEvent(wxMouseEvent& WXUNUSED(event))
  351. {
  352. }
  353.  
  354. bool MyPrintout::OnPrintPage(int page)
  355. {
  356.     wxDC *dc = GetDC();
  357.     if (dc)
  358.     {
  359.         if (page == 1)
  360.             DrawPageOne(dc);
  361.         else if (page == 2)
  362.             DrawPageTwo(dc);
  363.         
  364.         dc->SetDeviceOrigin(0, 0);
  365.         dc->SetUserScale(1.0, 1.0);
  366.         
  367.         wxChar buf[200];
  368.         wxSprintf(buf, wxT("PAGE %d"), page);
  369.         // dc->DrawText(buf, 10, 10);
  370.         
  371.         return TRUE;
  372.     }
  373.     else
  374.         return FALSE;
  375. }
  376.  
  377. bool MyPrintout::OnBeginDocument(int startPage, int endPage)
  378. {
  379.     if (!wxPrintout::OnBeginDocument(startPage, endPage))
  380.         return FALSE;
  381.     
  382.     return TRUE;
  383. }
  384.  
  385. void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
  386. {
  387.     *minPage = 1;
  388.     *maxPage = 2;
  389.     *selPageFrom = 1;
  390.     *selPageTo = 2;
  391. }
  392.  
  393. bool MyPrintout::HasPage(int pageNum)
  394. {
  395.     return (pageNum == 1 || pageNum == 2);
  396. }
  397.  
  398. void MyPrintout::DrawPageOne(wxDC *dc)
  399. {
  400. /* You might use THIS code if you were scaling
  401. * graphics of known size to fit on the page.
  402.     */
  403.     int w, h;
  404.     
  405.     // We know the graphic is 200x200. If we didn't know this,
  406.     // we'd need to calculate it.
  407.     float maxX = 200;
  408.     float maxY = 200;
  409.     
  410.     // Let's have at least 50 device units margin
  411.     float marginX = 50;
  412.     float marginY = 50;
  413.     
  414.     // Add the margin to the graphic size
  415.     maxX += (2*marginX);
  416.     maxY += (2*marginY);
  417.     
  418.     // Get the size of the DC in pixels
  419.     dc->GetSize(&w, &h);
  420.     
  421.     // Calculate a suitable scaling factor
  422.     float scaleX=(float)(w/maxX);
  423.     float scaleY=(float)(h/maxY);
  424.     
  425.     // Use x or y scaling factor, whichever fits on the DC
  426.     float actualScale = wxMin(scaleX,scaleY);
  427.     
  428.     // Calculate the position on the DC for centring the graphic
  429.     float posX = (float)((w - (200*actualScale))/2.0);
  430.     float posY = (float)((h - (200*actualScale))/2.0);
  431.     
  432.     // Set the scale and origin
  433.     dc->SetUserScale(actualScale, actualScale);
  434.     dc->SetDeviceOrigin( (long)posX, (long)posY );
  435.     //dc->SetUserScale(1.0, 1.0);
  436.     
  437.     frame->Draw(*dc);
  438. }
  439.  
  440. void MyPrintout::DrawPageTwo(wxDC *dc)
  441. {
  442. /* You might use THIS code to set the printer DC to ROUGHLY reflect
  443. * the screen text size. This page also draws lines of actual length 5cm
  444. * on the page.
  445.     */
  446.     // Get the logical pixels per inch of screen and printer
  447.     int ppiScreenX, ppiScreenY;
  448.     GetPPIScreen(&ppiScreenX, &ppiScreenY);
  449.     int ppiPrinterX, ppiPrinterY;
  450.     GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
  451.     
  452.     // This scales the DC so that the printout roughly represents the
  453.     // the screen scaling. The text point size _should_ be the right size
  454.     // but in fact is too small for some reason. This is a detail that will
  455.     // need to be addressed at some point but can be fudged for the
  456.     // moment.
  457.     float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
  458.     
  459.     // Now we have to check in case our real page size is reduced
  460.     // (e.g. because we're drawing to a print preview memory DC)
  461.     int pageWidth, pageHeight;
  462.     int w, h;
  463.     dc->GetSize(&w, &h);
  464.     GetPageSizePixels(&pageWidth, &pageHeight);
  465.     
  466.     // If printer pageWidth == current DC width, then this doesn't
  467.     // change. But w might be the preview bitmap width, so scale down.
  468.     float overallScale = scale * (float)(w/(float)pageWidth);
  469.     dc->SetUserScale(overallScale, overallScale);
  470.     
  471.     // Calculate conversion factor for converting millimetres into
  472.     // logical units.
  473.     // There are approx. 25.1 mm to the inch. There are ppi
  474.     // device units to the inch. Therefore 1 mm corresponds to
  475.     // ppi/25.1 device units. We also divide by the
  476.     // screen-to-printer scaling factor, because we need to
  477.     // unscale to pass logical units to DrawLine.
  478.     
  479.     // Draw 50 mm by 50 mm L shape
  480.     float logUnitsFactor = (float)(ppiPrinterX/(scale*25.1));
  481.     float logUnits = (float)(50*logUnitsFactor);
  482.     dc->SetPen(* wxBLACK_PEN);
  483.     dc->DrawLine(50, 250, (long)(50.0 + logUnits), 250);
  484.     dc->DrawLine(50, 250, 50, (long)(250.0 + logUnits));
  485.     
  486.     dc->SetFont(* wxGetApp().m_testFont);
  487.     dc->SetBackgroundMode(wxTRANSPARENT);
  488.     
  489.     
  490.     { // GetTextExtent demo:
  491.         wxString words[7] = {_T("This "), _T("is "), _T("GetTextExtent "), _T("testing "), _T("string. "), _T("Enjoy "), _T("it!")};
  492.         long w, h;
  493.         long x = 200, y= 250;
  494.         wxFont fnt(15, wxSWISS, wxNORMAL, wxNORMAL);
  495.         
  496.         dc->SetFont(fnt);
  497.         for (int i = 0; i < 7; i++) {
  498.             dc->GetTextExtent(words[i], &w, &h);
  499.             dc->DrawRectangle(x, y, w, h);
  500.             dc->DrawText(words[i], x, y);
  501.             x += w;
  502.         }
  503.         dc->SetFont(* wxGetApp().m_testFont);
  504.     }
  505.     
  506.     dc->DrawText(_T("Some test text"), 200, 300 );
  507.  
  508.     // TESTING
  509.     
  510.     int leftMargin = 20;
  511.     int rightMargin = 20;
  512.     int topMargin = 20;
  513.     int bottomMargin = 20;
  514.     
  515.     int pageWidthMM, pageHeightMM;
  516.     GetPageSizeMM(&pageWidthMM, &pageHeightMM);
  517.     
  518.     float leftMarginLogical = (float)(logUnitsFactor*leftMargin);
  519.     float topMarginLogical = (float)(logUnitsFactor*topMargin);
  520.     float bottomMarginLogical = (float)(logUnitsFactor*(pageHeightMM - bottomMargin));
  521.     float rightMarginLogical = (float)(logUnitsFactor*(pageWidthMM - rightMargin));
  522.     
  523.     dc->SetPen(* wxRED_PEN);
  524.     dc->DrawLine( (long)leftMarginLogical, (long)topMarginLogical, 
  525.         (long)rightMarginLogical, (long)topMarginLogical);
  526.     dc->DrawLine( (long)leftMarginLogical, (long)bottomMarginLogical, 
  527.         (long)rightMarginLogical,  (long)bottomMarginLogical);
  528.     
  529.     WritePageHeader(this, dc, _T("A header"), logUnitsFactor);
  530. }
  531.  
  532. // Writes a header on a page. Margin units are in millimetres.
  533. bool WritePageHeader(wxPrintout *printout, wxDC *dc, wxChar *text, float mmToLogical)
  534. {
  535. /*
  536. static wxFont *headerFont = (wxFont *) NULL;
  537. if (!headerFont)
  538. {
  539. headerFont = wxTheFontList->FindOrCreateFont(16, wxSWISS, wxNORMAL, wxBOLD);
  540. }
  541. dc->SetFont(headerFont);
  542.     */
  543.     
  544.     int pageWidthMM, pageHeightMM;
  545.     
  546.     printout->GetPageSizeMM(&pageWidthMM, &pageHeightMM);
  547.     
  548.     int leftMargin = 10;
  549.     int topMargin = 10;
  550.     int rightMargin = 10;
  551.     
  552.     float leftMarginLogical = (float)(mmToLogical*leftMargin);
  553.     float topMarginLogical = (float)(mmToLogical*topMargin);
  554.     float rightMarginLogical = (float)(mmToLogical*(pageWidthMM - rightMargin));
  555.     
  556.     long xExtent, yExtent;
  557.     dc->GetTextExtent(text, &xExtent, &yExtent);
  558.     float xPos = (float)(((((pageWidthMM - leftMargin - rightMargin)/2.0)+leftMargin)*mmToLogical) - (xExtent/2.0));
  559.     dc->DrawText(text, (long)xPos, (long)topMarginLogical);
  560.     
  561.     dc->SetPen(* wxBLACK_PEN);
  562.     dc->DrawLine( (long)leftMarginLogical, (long)(topMarginLogical+yExtent), 
  563.         (long)rightMarginLogical, (long)topMarginLogical+yExtent );
  564.     
  565.     return TRUE;
  566. }
  567.