[C++] c++与wxWidgets实现打印功能 →→→→→进入此内容的聊天室

来自 , 2019-10-13, 写在 C++, 查看 149 次.
URL http://www.code666.cn/view/de03beff
  1. #include <iostream>
  2. #include "wx/wx.h"
  3. #include "wx/print.h"
  4. #include "wx/printdlg.h"
  5. #include <cmath>
  6.  
  7. static const int brush_size = 3;
  8.  
  9. /**
  10.   * Shows a basic example of how to print stuff in wx.
  11.   */
  12. class QuickPrint : public wxPrintout
  13. {
  14.     wxPageSetupDialogData m_page_setup;
  15.  
  16.     /** the type of paper (letter, A4, etc...) */
  17.     wxPaperSize m_paper_type;
  18.  
  19.     /** horizontal or vertical */
  20.     int m_orient;
  21.  
  22.     // Or, if you use wxWidgets 2.9+ :
  23.     // wxPrintOrientation m_orient;
  24.  
  25.     /** number of pages we want to print. here it's static, but in a real example you will often
  26.       * want to calculate dynamically once you know the size of the printable area from page setup
  27.       */
  28.     int m_page_amount;
  29.  
  30.     /** margins, in millimeters */
  31.     int m_margin_left, m_margin_right, m_margin_top, m_margin_bottom;
  32.  
  33.     /** we'll use this to determine the coordinate system; it describes the number of units per
  34.       * centimeter (i.e. how fine the coordinate system is)
  35.       */
  36.     float m_units_per_cm;
  37.  
  38.     /** will contain the dimensions of the coordinate system, once it's calculated.
  39.       * in the printing callback, you can then draw from (0, 0) to (m_coord_system_width, m_coord_system_height),
  40.       * which will be the area covering the paper minus the margins
  41.       */
  42.     int m_coord_system_width, m_coord_system_height;
  43.  
  44. public:
  45.  
  46.     /**
  47.       * @param page_amount    number of pages we want to print. Here it's static because it's just a test, but in
  48.       *                       real code you will often want to calculate dynamically once you know the size of the
  49.       *                       printable area from page setup
  50.       * @param title          name of the print job / of the printed document
  51.       * @param units_per_cem  we'll use this to determine the coordinate system; it describes the number of units
  52.       *                       per centimeter (i.e. how fine the coordinate system is)
  53.       */
  54.     QuickPrint(int page_amount, wxString title, float units_per_cm) : wxPrintout( title )
  55.     {
  56.         m_page_amount = page_amount;
  57.  
  58.         m_orient = wxPORTRAIT; // wxPORTRAIT, wxLANDSCAPE
  59.         m_paper_type = wxPAPER_LETTER;
  60.         m_margin_left   = 16;
  61.         m_margin_right  = 16;
  62.         m_margin_top    = 32;
  63.         m_margin_bottom = 32;
  64.  
  65.         m_units_per_cm   = units_per_cm;
  66.     }
  67.  
  68.  
  69.     /** shows the page setup dialog, OR sets up defaults */
  70.     bool performPageSetup(const bool showPageSetupDialog)
  71.     {
  72.         // don't show page setup dialog, use default values
  73.         wxPrintData printdata;
  74.         printdata.SetPrintMode( wxPRINT_MODE_PRINTER );
  75.         printdata.SetOrientation( m_orient );
  76.         printdata.SetNoCopies(1);
  77. C        printdata.SetPaperId( m_paper_type );
  78.  
  79.         m_page_setup = wxPageSetupDialogData(printdata);
  80.         m_page_setup.SetMarginTopLeft    (wxPoint(m_margin_left,  m_margin_top));
  81.         m_page_setup.SetMarginBottomRight(wxPoint(m_margin_right, m_margin_bottom));
  82.  
  83.         if (showPageSetupDialog)
  84.         {
  85.             wxPageSetupDialog dialog( NULL, &m_page_setup );
  86.             if (dialog.ShowModal() == wxID_OK)
  87.             {
  88.  
  89.                 m_page_setup = dialog.GetPageSetupData();
  90.                 m_orient = m_page_setup.GetPrintData().GetOrientation();
  91.                 m_paper_type = m_page_setup.GetPrintData().GetPaperId();
  92.  
  93.                 wxPoint marginTopLeft = m_page_setup.GetMarginTopLeft();
  94.                 wxPoint marginBottomRight = m_page_setup.GetMarginBottomRight();
  95.                 m_margin_left   = marginTopLeft.x;
  96.                 m_margin_right  = marginBottomRight.x;
  97.                 m_margin_top    = marginTopLeft.y;
  98.                 m_margin_bottom = marginBottomRight.y;
  99.             }
  100.             else
  101.             {
  102.                 std::cout << "user canceled at first dialog" << std::endl;
  103.                 return false;
  104.             }
  105.         }
  106.         return true;
  107.     }
  108.  
  109.     /** Called when printing starts */
  110.     void OnBeginPrinting()
  111.     {
  112.         // set-up coordinate system however we want, we'll use it when drawing
  113.  
  114.         // take paper size and margin sizes into account when setting up coordinate system
  115.         // so that units are "square" (1 unit x is a wide as 1 unit y is high)
  116.         // (actually, if we don't make it square, on some platforms wx will even resize your
  117.         //  margins to make it so)
  118.         wxSize paperSize = m_page_setup.GetPaperSize();  // in millimeters
  119.  
  120.         // still in millimeters
  121.         float large_side = std::max(paperSize.GetWidth(), paperSize.GetHeight());
  122.         float small_side = std::min(paperSize.GetWidth(), paperSize.GetHeight());
  123.  
  124.         float large_side_cm = large_side / 10.0f;  // in centimeters
  125.         float small_side_cm = small_side / 10.0f;  // in centimeters
  126.  
  127.         if (m_orient == wxPORTRAIT)
  128.         {
  129.             float ratio = float(large_side - m_margin_top  - m_margin_bottom) /
  130.                           float(small_side - m_margin_left - m_margin_right);
  131.  
  132.             m_coord_system_width  = (int)((small_side_cm - m_margin_left/10.f -
  133.                                            m_margin_right/10.0f)*m_units_per_cm);
  134.             m_coord_system_height = m_coord_system_width*ratio;
  135.         }
  136.         else
  137.         {
  138.             float ratio = float(large_side - m_margin_left - m_margin_right) /
  139.                           float(small_side - m_margin_top  - m_margin_bottom);
  140.  
  141.             m_coord_system_height = (int)((small_side_cm - m_margin_top/10.0f -
  142.                                            m_margin_bottom/10.0f)* m_units_per_cm);
  143.             m_coord_system_width  = m_coord_system_height*ratio;
  144.  
  145.         }
  146.  
  147.     }
  148.  
  149.     /** returns the data obtained from the page setup dialog (or the defaults,
  150.      * if dialog was not shown) */
  151.     wxPrintData getPrintData()
  152.     {
  153.         return m_page_setup.GetPrintData();
  154.     }
  155.  
  156.     /** Called when starting to print a document */
  157.     bool OnBeginDocument(int startPage, int endPage)
  158.     {
  159.         std::cout << "beginning to print document, from page " << startPage
  160.                   << " to " << endPage << std::endl;
  161.         return wxPrintout::OnBeginDocument(startPage, endPage);
  162.     }
  163.  
  164.     /** wx will call this to know how many pages can be printed */
  165.     void GetPageInfo(int *minPage, int *maxPage, int *pageSelFrom, int *pageSelTo)
  166.     {
  167.         *minPage = 1;
  168.         *maxPage = m_page_amount;
  169.  
  170.         *pageSelFrom = 1;
  171.         *pageSelTo = m_page_amount;
  172.     }
  173.  
  174.     /** called by wx to know what pages this document has */
  175.     bool HasPage(int pageNum)
  176.     {
  177.         // wx will call this to know how many pages can be printed
  178.         return pageNum >= 1 && pageNum <= m_page_amount;
  179.     }
  180.  
  181.  
  182.     /** called by wx everytime it's time to render a specific page onto the
  183.      * printing device context */
  184.     bool OnPrintPage(int pageNum)
  185.     {
  186.         std::cout << "printing page " << pageNum << std::endl;
  187.  
  188.         // ---- setup DC with coordinate system ----
  189.         FitThisSizeToPageMargins(wxSize(m_coord_system_width, m_coord_system_height), m_page_setup);
  190.  
  191.         wxRect fitRect = GetLogicalPageMarginsRect(m_page_setup);
  192.  
  193.         wxCoord xoff = (fitRect.width - m_coord_system_width) / 2;
  194.         wxCoord yoff = (fitRect.height - m_coord_system_height) / 2;
  195.         OffsetLogicalOrigin(xoff, yoff);
  196.  
  197.         wxDC* ptr = GetDC();
  198.         if (ptr==NULL || !ptr->IsOk())
  199.         {
  200.             std::cout << "DC is not Ok, interrupting printing" << std::endl;
  201.             return false;
  202.         }
  203.         wxDC& dc = *ptr;
  204.  
  205.         // ---- A couple helper variables to help us during draw within paper area -----
  206.         const int x0 = 0;
  207.         const int y0 = 0;
  208.         const int width = m_coord_system_width;
  209.         const int height = m_coord_system_height;
  210.         const int x1 = x0 + width;
  211.         const int y1 = y0 + height;
  212.  
  213.         const int center_x = x0 + width/2;
  214.         const int center_y = y0 + height/2;
  215.  
  216.         std::cout << "printable area : (" << x0 << ", " << y0 << ") to ("
  217.         << x1 << ", " << y1 << ")" << std::endl;
  218.  
  219.         // ---- Draw to the print DC ----
  220.         dc.Clear();
  221.  
  222.         dc.SetPen(  wxPen( wxColour(0,0,0), brush_size ) );
  223.         dc.SetBrush( *wxTRANSPARENT_BRUSH );
  224.  
  225.         // draw a rectangle to show its bounds.
  226.         dc.DrawRectangle(x0, y0, width, height);
  227.  
  228.         // draw wxWidgets logo
  229.         dc.SetBrush( *wxRED_BRUSH );
  230.         dc.DrawRectangle(center_x-45-38, center_y, 76, 76);
  231.         dc.SetBrush( *wxBLUE_BRUSH );
  232.         dc.DrawRectangle(center_x-38, center_y-45, 76, 76);
  233.         dc.SetBrush( wxBrush( wxColor(255,244,0) ) );
  234.         dc.DrawRectangle(center_x+45-38, center_y-10, 76, 76);
  235.  
  236.         // draw page number label
  237.         wxString label( wxT("This is page #") );
  238.         label << pageNum;
  239.         dc.SetTextBackground( wxColour(255,255,0) );
  240.         dc.SetTextForeground( wxColour(0,0,0) );
  241.         dc.DrawText( label, x0 + width/5, y0 + height - 50 );
  242.  
  243.         return true;
  244.     }  
  245.  
  246.     /** Called when printing is done. I have nothing to do in this case
  247.      * in this example. */
  248.     void OnEndPrinting()
  249.     {
  250.     }
  251. };
  252.  
  253. // -------------------------------------------------------------------------------------
  254. //                                HOW TO INVOKE THIS TEST
  255. // -------------------------------------------------------------------------------------
  256.  
  257. class MyApp: public wxApp
  258. {
  259. public:
  260.     virtual bool OnInit();
  261. };
  262.  
  263.  
  264. IMPLEMENT_APP(MyApp)
  265.  
  266.  
  267. bool MyApp::OnInit()
  268. {
  269.     QuickPrint*  myprint = new QuickPrint( 5 /* 5 pages */,
  270.                                            wxT("wxPrint test"),
  271.                                            30 /* 30 units per centimeter */ );
  272.     if (!myprint->performPageSetup(true))
  273.     {
  274.         // user cancelled
  275.         exit(0);
  276.     }
  277.  
  278.     wxPrintDialogData data(myprint->getPrintData());
  279.     wxPrinter printer(&data);
  280.     const bool success = printer.Print(NULL, myprint, true /* show dialog */);
  281.  
  282.     delete myprint;
  283.  
  284.     if (!success)
  285.     {
  286.         std::cerr << "Failed!!\n";
  287.         return false;
  288.     }
  289.     exit(0);
  290.     return true;
  291. }
  292.  

回复 "c++与wxWidgets实现打印功能"

这儿你可以回复上面这条便签

captcha