Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qprintdialog_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtPrintSupport/qtprintsupportglobal.h>
6
7#include "qprintdialog.h"
8
9#include <qwidget.h>
10#include <qapplication.h>
11#include <qmessagebox.h>
12#include <private/qapplication_p.h>
13
15#include <private/qprintengine_win_p.h>
16#include "../kernel/qprinter_p.h"
17
18#if !defined(PD_NOCURRENTPAGE)
19#define PD_NOCURRENTPAGE 0x00800000
20#define PD_RESULT_PRINT 1
21#define PD_RESULT_APPLY 2
22#define START_PAGE_GENERAL 0XFFFFFFFF
23#endif
24
26
27using namespace Qt::StringLiterals;
28
29//extern void qt_win_eatMouseMove();
30
32{
33 Q_DECLARE_PUBLIC(QPrintDialog)
34public:
36 : engine(0), ep(0)
37 {
38 }
39
41
44};
45
46static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWindow *parentWindow,
47 QPrintDialog *pdlg,
48 QPrintDialogPrivate *d, HGLOBAL *tempDevNames)
49{
50 DEVMODE *devMode = d->ep->devMode;
51
52 if (devMode) {
53 int size = sizeof(DEVMODE) + devMode->dmDriverExtra;
54 pd->hDevMode = GlobalAlloc(GHND, size);
55 {
56 void *dest = GlobalLock(pd->hDevMode);
57 memcpy(dest, devMode, size);
58 GlobalUnlock(pd->hDevMode);
59 }
60 } else {
61 pd->hDevMode = NULL;
62 }
63 pd->hDevNames = tempDevNames;
64
65 pd->Flags = PD_RETURNDC;
66 pd->Flags |= PD_USEDEVMODECOPIESANDCOLLATE;
67
68 if (!pdlg->testOption(QPrintDialog::PrintSelection))
69 pd->Flags |= PD_NOSELECTION;
70 if (pdlg->testOption(QPrintDialog::PrintPageRange)) {
71 pd->nMinPage = pdlg->minPage();
72 pd->nMaxPage = pdlg->maxPage();
73 }
74
75 if (!pdlg->testOption(QPrintDialog::PrintToFile))
76 pd->Flags |= PD_DISABLEPRINTTOFILE;
77
78 if (pdlg->testOption(QPrintDialog::PrintSelection) && pdlg->printRange() == QPrintDialog::Selection)
79 pd->Flags |= PD_SELECTION;
80 else if (pdlg->testOption(QPrintDialog::PrintPageRange) && pdlg->printRange() == QPrintDialog::PageRange)
81 pd->Flags |= PD_PAGENUMS;
82 else if (pdlg->testOption(QPrintDialog::PrintCurrentPage) && pdlg->printRange() == QPrintDialog::CurrentPage)
83 pd->Flags |= PD_CURRENTPAGE;
84 else
85 pd->Flags |= PD_ALLPAGES;
86
87 // As stated by MSDN, to enable collate option when minpage==maxpage==0
88 // set the PD_NOPAGENUMS flag
89 if (pd->nMinPage==0 && pd->nMaxPage==0)
90 pd->Flags |= PD_NOPAGENUMS;
91
92 // Disable Current Page option if not required as default is Enabled
93 if (!pdlg->testOption(QPrintDialog::PrintCurrentPage))
94 pd->Flags |= PD_NOCURRENTPAGE;
95
96 // Default to showing the General tab first
97 pd->nStartPage = START_PAGE_GENERAL;
98
99 // We don't support more than one page range in the QPrinter API yet.
100 pd->nPageRanges = 1;
101 pd->nMaxPageRanges = 1;
102
103 if (d->ep->printToFile)
104 pd->Flags |= PD_PRINTTOFILE;
105
106 WId wId = parentWindow ? parentWindow->winId() : 0;
107 //QTBUG-118899 PrintDlg needs valid window handle in hwndOwner
108 //So in case there is no valid handle in the application,
109 //use the desktop as valid handle.
110 pd->hwndOwner = wId != 0 ? HWND(wId) : GetDesktopWindow();
111 pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
112 pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
113 pd->nCopies = d->printer->copyCount();
114}
115
116static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)
117{
118 if (pd->Flags & PD_SELECTION) {
119 pdlg->setPrintRange(QPrintDialog::Selection);
120 pdlg->printer()->setPageRanges(QPageRanges());
121 } else if (pd->Flags & PD_PAGENUMS) {
122 pdlg->setPrintRange(QPrintDialog::PageRange);
123 pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);
124 } else if (pd->Flags & PD_CURRENTPAGE) {
125 pdlg->setPrintRange(QPrintDialog::CurrentPage);
126 pdlg->printer()->setPageRanges(QPageRanges());
127 } else { // PD_ALLPAGES
128 pdlg->setPrintRange(QPrintDialog::AllPages);
129 pdlg->printer()->setPageRanges(QPageRanges());
130 }
131
132 d->ep->printToFile = (pd->Flags & PD_PRINTTOFILE) != 0;
133
134 d->engine->setGlobalDevMode(pd->hDevNames, pd->hDevMode);
135
136 if (d->ep->printToFile && d->ep->fileName.isEmpty())
137 d->ep->fileName = "FILE:"_L1;
138 else if (!d->ep->printToFile && d->ep->fileName == "FILE:"_L1)
139 d->ep->fileName.clear();
140}
141
142static bool warnIfNotNative(QPrinter *printer)
143{
144 if (printer->outputFormat() != QPrinter::NativeFormat) {
145 qWarning("QPrintDialog: Cannot be used on non-native printers");
146 return false;
147 }
148 return true;
149}
150
151QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
152 : QAbstractPrintDialog( *(new QPrintDialogPrivate), printer, parent)
153{
154 Q_D(QPrintDialog);
155 if (!warnIfNotNative(d->printer))
156 return;
157 d->engine = static_cast<QWin32PrintEngine *>(d->printer->printEngine());
158 d->ep = static_cast<QWin32PrintEngine *>(d->printer->printEngine())->d_func();
159 setAttribute(Qt::WA_DontShowOnScreen);
160}
161
162QPrintDialog::QPrintDialog(QWidget *parent)
163 : QAbstractPrintDialog( *(new QPrintDialogPrivate), 0, parent)
164{
165 Q_D(QPrintDialog);
166 if (!warnIfNotNative(d->printer))
167 return;
168 d->engine = static_cast<QWin32PrintEngine *>(d->printer->printEngine());
169 d->ep = static_cast<QWin32PrintEngine *>(d->printer->printEngine())->d_func();
170 setAttribute(Qt::WA_DontShowOnScreen);
171}
172
173QPrintDialog::~QPrintDialog()
174{
175}
176
177int QPrintDialog::exec()
178{
179 if (!warnIfNotNative(printer()))
180 return 0;
181
182 Q_D(QPrintDialog);
183 return d->openWindowsPrintDialogModally();
184}
185
186int QPrintDialogPrivate::openWindowsPrintDialogModally()
187{
188 Q_Q(QPrintDialog);
189 QWindow *parentWindow = q->windowHandle() ? q->windowHandle()->transientParent() : nullptr;
190 if (!parentWindow) {
191 QWidget *parent = q->parentWidget();
192 if (parent)
193 parent = parent->window();
194 else
195 parent = QApplication::activeWindow();
196
197 // If there is no window, fall back to the print dialog itself
198 if (!parent)
199 parent = q;
200
201 parentWindow = parent->windowHandle();
202 }
203
204 q->QDialog::setVisible(true);
205
206 HGLOBAL *tempDevNames = engine->createGlobalDevNames();
207
208 bool done;
209 bool result;
210 bool doPrinting;
211
212 PRINTPAGERANGE pageRange;
213 PRINTDLGEX pd;
214 memset(&pd, 0, sizeof(PRINTDLGEX));
215 pd.lStructSize = sizeof(PRINTDLGEX);
216 pd.lpPageRanges = &pageRange;
217 qt_win_setup_PRINTDLGEX(&pd, parentWindow, q, this, tempDevNames);
218
219 do {
220 done = true;
221 doPrinting = false;
222 result = (PrintDlgEx(&pd) == S_OK);
223 if (result && (pd.dwResultAction == PD_RESULT_PRINT
224 || pd.dwResultAction == PD_RESULT_APPLY))
225 {
226 doPrinting = (pd.dwResultAction == PD_RESULT_PRINT);
227 if ((pd.Flags & PD_PAGENUMS)
228 && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage))
229 {
230 pd.lpPageRanges[0].nFromPage = 1;
231 pd.lpPageRanges[0].nToPage = 1;
232 done = false;
233 }
234 if (pd.hDC == 0)
235 result = false;
236 }
237
238 if (!done) {
239 QMessageBox::warning(nullptr,
240 QPrintDialog::tr("Print"),
241 QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."));
242 }
243 } while (!done);
244
245 q->QDialog::setVisible(false);
246
247// qt_win_eatMouseMove();
248
249 // write values back...
250 if (result && (pd.dwResultAction == PD_RESULT_PRINT
251 || pd.dwResultAction == PD_RESULT_APPLY))
252 {
253 qt_win_read_back_PRINTDLGEX(&pd, q, this);
254 // update printer validity
255 printer->d_func()->validPrinter = !printer->printerName().isEmpty();
256 }
257
258 // Cleanup...
259 GlobalFree(tempDevNames);
260
261 q->done(result && doPrinting);
262
263 return result && doPrinting;
264}
265
266void QPrintDialog::setVisible(bool visible)
267{
268 Q_D(QPrintDialog);
269
270 // its always modal, so we cannot hide a native print dialog
271 if (!visible)
272 return;
273
274 if (!warnIfNotNative(d->printer))
275 return;
276
277 (void)d->openWindowsPrintDialogModally();
278 return;
279}
280
281QT_END_NAMESPACE
282
283#include "moc_qprintdialog.cpp"
QWin32PrintEngine * engine
QWin32PrintEnginePrivate * ep
static bool warnIfNotNative(QPrinter *printer)
#define START_PAGE_GENERAL
static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWindow *parentWindow, QPrintDialog *pdlg, QPrintDialogPrivate *d, HGLOBAL *tempDevNames)
#define PD_RESULT_PRINT
#define PD_NOCURRENTPAGE
static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)
#define PD_RESULT_APPLY