#include <iostream> |
#include "wx/wx.h" |
#include "wx/print.h" |
#include "wx/printdlg.h" |
#include <cmath> |
|
static const int brush_size = 3; |
|
/** |
* Shows a basic example of how to print stuff in wx. |
*/ |
class QuickPrint : public wxPrintout |
{ |
wxPageSetupDialogData m_page_setup; |
|
/** the type of paper (letter, A4, etc...) */ |
wxPaperSize m_paper_type; |
|
/** horizontal or vertical */ |
int m_orient; |
|
// Or, if you use wxWidgets 2.9+ : |
// wxPrintOrientation m_orient; |
|
/** number of pages we want to print. here it's static, but in a real example you will often |
* want to calculate dynamically once you know the size of the printable area from page setup |
*/ |
int m_page_amount; |
|
/** margins, in millimeters */ |
int m_margin_left, m_margin_right, m_margin_top, m_margin_bottom; |
|
/** we'll use this to determine the coordinate system; it describes the number of units per |
* centimeter (i.e. how fine the coordinate system is) |
*/ |
float m_units_per_cm; |
|
/** will contain the dimensions of the coordinate system, once it's calculated. |
* in the printing callback, you can then draw from (0, 0) to (m_coord_system_width, m_coord_system_height), |
* which will be the area covering the paper minus the margins |
*/ |
int m_coord_system_width, m_coord_system_height; |
|
public : |
|
/** |
* @param page_amount number of pages we want to print. Here it's static because it's just a test, but in |
* real code you will often want to calculate dynamically once you know the size of the |
* printable area from page setup |
* @param title name of the print job / of the printed document |
* @param units_per_cem we'll use this to determine the coordinate system; it describes the number of units |
* per centimeter (i.e. how fine the coordinate system is) |
*/ |
QuickPrint( int page_amount, wxString title, float units_per_cm) : wxPrintout( title ) |
{ |
m_page_amount = page_amount; |
|
m_orient = wxPORTRAIT; // wxPORTRAIT, wxLANDSCAPE |
m_paper_type = wxPAPER_LETTER; |
m_margin_left = 16; |
m_margin_right = 16; |
m_margin_top = 32; |
m_margin_bottom = 32; |
|
m_units_per_cm = units_per_cm; |
} |
|
|
/** shows the page setup dialog, OR sets up defaults */ |
bool performPageSetup( const bool showPageSetupDialog) |
{ |
// don't show page setup dialog, use default values |
wxPrintData printdata; |
printdata.SetPrintMode( wxPRINT_MODE_PRINTER ); |
printdata.SetOrientation( m_orient ); |
printdata.SetNoCopies(1); |
C printdata.SetPaperId( m_paper_type ); |
|
m_page_setup = wxPageSetupDialogData(printdata); |
m_page_setup.SetMarginTopLeft (wxPoint(m_margin_left, m_margin_top)); |
m_page_setup.SetMarginBottomRight(wxPoint(m_margin_right, m_margin_bottom)); |
|
if (showPageSetupDialog) |
{ |
wxPageSetupDialog dialog( NULL, &m_page_setup ); |
if (dialog.ShowModal() == wxID_OK) |
{ |
|
m_page_setup = dialog.GetPageSetupData(); |
m_orient = m_page_setup.GetPrintData().GetOrientation(); |
m_paper_type = m_page_setup.GetPrintData().GetPaperId(); |
|
wxPoint marginTopLeft = m_page_setup.GetMarginTopLeft(); |
wxPoint marginBottomRight = m_page_setup.GetMarginBottomRight(); |
m_margin_left = marginTopLeft.x; |
m_margin_right = marginBottomRight.x; |
m_margin_top = marginTopLeft.y; |
m_margin_bottom = marginBottomRight.y; |
} |
else |
{ |
std::cout << "user canceled at first dialog" << std::endl; |
return false ; |
} |
} |
return true ; |
} |
|
/** Called when printing starts */ |
void OnBeginPrinting() |
{ |
// set-up coordinate system however we want, we'll use it when drawing |
|
// take paper size and margin sizes into account when setting up coordinate system |
// so that units are "square" (1 unit x is a wide as 1 unit y is high) |
// (actually, if we don't make it square, on some platforms wx will even resize your |
// margins to make it so) |
wxSize paperSize = m_page_setup.GetPaperSize(); // in millimeters |
|
// still in millimeters |
float large_side = std::max(paperSize.GetWidth(), paperSize.GetHeight()); |
float small_side = std::min(paperSize.GetWidth(), paperSize.GetHeight()); |
|
float large_side_cm = large_side / 10.0f; // in centimeters |
float small_side_cm = small_side / 10.0f; // in centimeters |
|
if (m_orient == wxPORTRAIT) |
{ |
float ratio = float (large_side - m_margin_top - m_margin_bottom) / |
float (small_side - m_margin_left - m_margin_right); |
|
m_coord_system_width = ( int )((small_side_cm - m_margin_left/10.f - |
m_margin_right/10.0f)*m_units_per_cm); |
m_coord_system_height = m_coord_system_width*ratio; |
} |
else |
{ |
float ratio = float (large_side - m_margin_left - m_margin_right) / |
float (small_side - m_margin_top - m_margin_bottom); |
|
m_coord_system_height = ( int )((small_side_cm - m_margin_top/10.0f - |
m_margin_bottom/10.0f)* m_units_per_cm); |
m_coord_system_width = m_coord_system_height*ratio; |
|
} |
|
} |
|
/** returns the data obtained from the page setup dialog (or the defaults, |
* if dialog was not shown) */ |
wxPrintData getPrintData() |
{ |
return m_page_setup.GetPrintData(); |
} |
|
/** Called when starting to print a document */ |
bool OnBeginDocument( int startPage, int endPage) |
{ |
std::cout << "beginning to print document, from page " << startPage |
<< " to " << endPage << std::endl; |
return wxPrintout::OnBeginDocument(startPage, endPage); |
} |
|
/** wx will call this to know how many pages can be printed */ |
void GetPageInfo( int *minPage, int *maxPage, int *pageSelFrom, int *pageSelTo) |
{ |
*minPage = 1; |
*maxPage = m_page_amount; |
|
*pageSelFrom = 1; |
*pageSelTo = m_page_amount; |
} |
|
/** called by wx to know what pages this document has */ |
bool HasPage( int pageNum) |
{ |
// wx will call this to know how many pages can be printed |
return pageNum >= 1 && pageNum <= m_page_amount; |
} |
|
|
/** called by wx everytime it's time to render a specific page onto the |
* printing device context */ |
bool OnPrintPage( int pageNum) |
{ |
std::cout << "printing page " << pageNum << std::endl; |
|
// ---- setup DC with coordinate system ---- |
FitThisSizeToPageMargins(wxSize(m_coord_system_width, m_coord_system_height), m_page_setup); |
|
wxRect fitRect = GetLogicalPageMarginsRect(m_page_setup); |
|
wxCoord xoff = (fitRect.width - m_coord_system_width) / 2; |
wxCoord yoff = (fitRect.height - m_coord_system_height) / 2; |
OffsetLogicalOrigin(xoff, yoff); |
|
wxDC* ptr = GetDC(); |
if (ptr==NULL || !ptr->IsOk()) |
{ |
std::cout << "DC is not Ok, interrupting printing" << std::endl; |
return false ; |
} |
wxDC& dc = *ptr; |
|
// ---- A couple helper variables to help us during draw within paper area ----- |
const int x0 = 0; |
const int y0 = 0; |
const int width = m_coord_system_width; |
const int height = m_coord_system_height; |
const int x1 = x0 + width; |
const int y1 = y0 + height; |
|
const int center_x = x0 + width/2; |
const int center_y = y0 + height/2; |
|
std::cout << "printable area : (" << x0 << ", " << y0 << ") to (" |
<< x1 << ", " << y1 << ")" << std::endl; |
|
// ---- Draw to the print DC ---- |
dc.Clear(); |
|
dc.SetPen( wxPen( wxColour(0,0,0), brush_size ) ); |
dc.SetBrush( *wxTRANSPARENT_BRUSH ); |
|
// draw a rectangle to show its bounds. |
dc.DrawRectangle(x0, y0, width, height); |
|
// draw wxWidgets logo |
dc.SetBrush( *wxRED_BRUSH ); |
dc.DrawRectangle(center_x-45-38, center_y, 76, 76); |
dc.SetBrush( *wxBLUE_BRUSH ); |
dc.DrawRectangle(center_x-38, center_y-45, 76, 76); |
dc.SetBrush( wxBrush( wxColor(255,244,0) ) ); |
dc.DrawRectangle(center_x+45-38, center_y-10, 76, 76); |
|
// draw page number label |
wxString label( wxT( "This is page #" ) ); |
label << pageNum; |
dc.SetTextBackground( wxColour(255,255,0) ); |
dc.SetTextForeground( wxColour(0,0,0) ); |
dc.DrawText( label, x0 + width/5, y0 + height - 50 ); |
|
return true ; |
} |
|
/** Called when printing is done. I have nothing to do in this case |
* in this example. */ |
void OnEndPrinting() |
{ |
} |
}; |
|
// ------------------------------------------------------------------------------------- |
// HOW TO INVOKE THIS TEST |
// ------------------------------------------------------------------------------------- |
|
class MyApp: public wxApp |
{ |
public : |
virtual bool OnInit(); |
}; |
|
|
IMPLEMENT_APP(MyApp) |
|
|
bool MyApp::OnInit() |
{ |
QuickPrint* myprint = new QuickPrint( 5 /* 5 pages */ , |
wxT( "wxPrint test" ), |
30 /* 30 units per centimeter */ ); |
if (!myprint->performPageSetup( true )) |
{ |
// user cancelled |
exit (0); |
} |
|
wxPrintDialogData data(myprint->getPrintData()); |
wxPrinter printer(&data); |
const bool success = printer.Print(NULL, myprint, true /* show dialog */ ); |
|
delete myprint; |
|
if (!success) |
{ |
std::cerr << "Failed!!\n" ; |
return false ; |
} |
exit (0); |
return true ; |
} |