From e93570f681e1e2de0393682b94c8196df02909b0 Mon Sep 17 00:00:00 2001 From: Stefan Ziegler Date: Mon, 13 Mar 2023 11:47:33 +0100 Subject: [PATCH] Implement support for printing only selected pages in wxMSW While the user could select to print only the selection in the dialog, there was no way for the program to specify which pages were selected, making this choice impossible to handle. Add new IsPageSelected() function which is now used to query which pages are selected and should actually be printed. Update the printing sample to show how this function is used. --- include/wx/prntbase.h | 1 + interface/wx/print.h | 19 +++++++++++++++++++ samples/printing/printing.cpp | 35 +++++++++++++++++++++++++++++++---- samples/printing/printing.h | 12 ++++++++++-- src/common/prntbase.cpp | 5 +++++ src/msw/printwin.cpp | 11 ++++++++++- 6 files changed, 76 insertions(+), 7 deletions(-) diff --git a/include/wx/prntbase.h b/include/wx/prntbase.h index db7d726e1a..018d5eeff6 100644 --- a/include/wx/prntbase.h +++ b/include/wx/prntbase.h @@ -278,6 +278,7 @@ public: virtual bool HasPage(int page); virtual bool OnPrintPage(int page) = 0; virtual void GetPageInfo(int *minPage, int *maxPage, int *pageFrom, int *pageTo); + virtual bool IsPageSelected(int page); virtual wxString GetTitle() const { return m_printoutTitle; } diff --git a/interface/wx/print.h b/interface/wx/print.h index 416fccc9c6..b21b9afb59 100644 --- a/interface/wx/print.h +++ b/interface/wx/print.h @@ -705,6 +705,11 @@ public: and maximum page values that the user can select, and the required page range to be printed. + If the user chose to print only selected pages in the MSW printing + dialog, then @a pageFrom and @a pageTo are used to limit the page range + and IsPageSelected() is called later to query whether the page is + selected and so should be printed. + By default this returns (1, 32000) for the page minimum and maximum values, and (1, 1) for the required page range. @@ -773,6 +778,20 @@ public: */ virtual bool HasPage(int pageNum); + /** + Should be overridden to return @true if this page is selected, or @false + if not. + + This function is called for all the pages in the valid range when the + user chooses "Selection" in the "Page Range" area of the printing + dialog under MSW. It is not currently called under the other platforms. + + The default implementation always returns @false. + + @since 3.3.0 + */ + virtual bool IsPageSelected(int pageNum); + /** Returns @true if the printout is currently being used for previewing. diff --git a/samples/printing/printing.cpp b/samples/printing/printing.cpp index 8222104288..40a48ca526 100644 --- a/samples/printing/printing.cpp +++ b/samples/printing/printing.cpp @@ -356,9 +356,20 @@ void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event)) { wxPrintDialogData printDialogData(* g_printData); + printDialogData.EnableSelection(true); + printDialogData.EnablePageNumbers(true); + printDialogData.SetMinPage(1); + printDialogData.SetMaxPage(2); + printDialogData.SetFromPage(1); + printDialogData.SetToPage(2); + printDialogData.SetAllPages(true); wxPrinter printer(&printDialogData); - MyPrintout printout(this, "My printout"); + + // wxPrinter copies printDialogData internally, so we have to pass this + // instance in order to evaluate users inputs. + MyPrintout printout(this, &printer.GetPrintDialogData(), "My printout"); + if (!printer.Print(this, &printout, true /*prompt*/)) { if (wxPrinter::GetLastError() == wxPRINTER_ERROR) @@ -381,7 +392,7 @@ void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event)) // Pass two printout objects: for preview, and possible printing. wxPrintDialogData printDialogData(* g_printData); wxPrintPreview *preview = - new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData); + new wxPrintPreview(new MyPrintout(this, &printDialogData), new MyPrintout(this, &printDialogData), &printDialogData); if (!preview->IsOk()) { delete preview; @@ -412,7 +423,7 @@ void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event)) wxPrintDialogData printDialogData(* g_printData); wxPostScriptPrinter printer(&printDialogData); - MyPrintout printout(this, "My printout"); + MyPrintout printout(this, &printer.GetPrintDialogData(), "My printout"); printer.Print(this, &printout, true/*prompt*/); (*g_printData) = printer.GetPrintDialogData().GetPrintData(); @@ -422,7 +433,7 @@ void MyFrame::OnPrintPreviewPS(wxCommandEvent& WXUNUSED(event)) { // Pass two printout objects: for preview, and possible printing. wxPrintDialogData printDialogData(* g_printData); - wxPrintPreview *preview = new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData); + wxPrintPreview *preview = new wxPrintPreview(new MyPrintout(this, &printDialogData), new MyPrintout(this, &printDialogData), &printDialogData); wxPreviewFrame *frame = new wxPreviewFrame(preview, this, "Demo Print Preview"); frame->Initialize(); frame->Centre(wxBOTH); @@ -541,6 +552,16 @@ void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int * *maxPage = 2; *selPageFrom = 1; *selPageTo = 2; + + if (m_printDlgData->GetSelection()) + { + // if the user wants to print the selection, we could set the range via + // selPageFrom and selPageTo, but if the pages are not consecutive, we + // set selPageFrom and selPageTo to the maximum range and we use + // IsPageSelected() to tell the printing system which page is selected. + + // in our example below, only page 2 is selected. + } } bool MyPrintout::HasPage(int pageNum) @@ -548,6 +569,12 @@ bool MyPrintout::HasPage(int pageNum) return (pageNum == 1 || pageNum == 2); } +bool MyPrintout::IsPageSelected(int pageNum) +{ + // to demonstrate selection, we just simulate selection of page 2 + return pageNum == 2; +} + void MyPrintout::DrawPageOne() { // You might use THIS code if you were scaling graphics of known size to fit diff --git a/samples/printing/printing.h b/samples/printing/printing.h index fb60bca57b..5e76330332 100644 --- a/samples/printing/printing.h +++ b/samples/printing/printing.h @@ -86,13 +86,20 @@ private: class MyPrintout: public wxPrintout { public: - MyPrintout(MyFrame* frame, const wxString &title = "My printout") - : wxPrintout(title) { m_frame=frame; } + MyPrintout(MyFrame* frame, + wxPrintDialogData* printDlgData, + const wxString& title = "My printout") + : wxPrintout(title) + { + m_frame = frame; + m_printDlgData = printDlgData; + } virtual bool OnPrintPage(int page) override; virtual bool HasPage(int page) override; virtual bool OnBeginDocument(int startPage, int endPage) override; virtual void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) override; + virtual bool IsPageSelected(int pageNum) override; void DrawPageOne(); void DrawPageTwo(); @@ -102,6 +109,7 @@ public: private: MyFrame *m_frame; + wxPrintDialogData* m_printDlgData; }; diff --git a/src/common/prntbase.cpp b/src/common/prntbase.cpp index 3c9f8345c4..564d230c17 100644 --- a/src/common/prntbase.cpp +++ b/src/common/prntbase.cpp @@ -635,6 +635,11 @@ void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toP *toPage = 1; } +bool wxPrintout::IsPageSelected(int WXUNUSED(page)) +{ + return false; +} + bool wxPrintout::SetUp(wxDC& dc) { wxCHECK_MSG( dc.IsOk(), false, "should have a valid DC to set up" ); diff --git a/src/msw/printwin.cpp b/src/msw/printwin.cpp index b3e529bcd5..c9975b9b74 100644 --- a/src/msw/printwin.cpp +++ b/src/msw/printwin.cpp @@ -164,7 +164,12 @@ bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt int minPageNum = minPage, maxPageNum = maxPage; - if ( !(m_printDialogData.GetAllPages() || m_printDialogData.GetSelection()) ) + if ( m_printDialogData.GetSelection() ) + { + minPageNum = fromPage; + maxPageNum = toPage; + } + else if ( !m_printDialogData.GetAllPages() ) { minPageNum = m_printDialogData.GetFromPage(); maxPageNum = m_printDialogData.GetToPage(); @@ -198,6 +203,10 @@ bool wxWindowsPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt pn <= maxPageNum && printout->HasPage(pn); pn++ ) { + // allow non-consecutive selected pages + if ( m_printDialogData.GetSelection() && !printout->IsPageSelected(pn) ) + continue; + win->SetProgress(pn - minPageNum + 1, maxPageNum - minPageNum + 1, copyCount, maxCopyCount);