33 LPWSTR printerIdUtf16 =
const_cast<LPWSTR>(
reinterpret_cast<LPCWSTR>(printerId.utf16()));
35 LONG dmSize = DocumentProperties(
nullptr, hPrinter, printerIdUtf16,
nullptr,
nullptr, 0);
38 LPDEVMODE pDevMode =
reinterpret_cast<LPDEVMODE>(malloc(dmSize));
40 LONG result = DocumentProperties(
nullptr, hPrinter, printerIdUtf16, pDevMode,
nullptr, DM_OUT_BUFFER);
54QWindowsPrintDevice::QWindowsPrintDevice(
const QString &id)
55 : QPlatformPrintDevice(id),
59 if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) {
60 if (OpenPrinter(
const_cast<LPWSTR>(wcharId()), &m_hPrinter,
nullptr)) {
62 GetPrinter(m_hPrinter, 2, 0, 0, &needed);
63 QScopedArrayPointer<BYTE> buffer(
new BYTE[needed]);
64 if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) {
65 PPRINTER_INFO_2 info =
reinterpret_cast<PPRINTER_INFO_2>(buffer.data());
66 m_name = QString::fromWCharArray(info->pPrinterName);
67 m_location = QString::fromWCharArray(info->pLocation);
68 m_makeAndModel = QString::fromWCharArray(info->pDriverName);
69 m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK;
71 QWindowsPrinterInfo m_info;
73 m_info.m_name = m_name;
74 m_info.m_location = m_location;
75 m_info.m_makeAndModel = m_makeAndModel;
76 m_info.m_isRemote = m_isRemote;
77 m_infoIndex = windowsDeviceLookup()->indexOf(m_info);
78 if (m_infoIndex != -1) {
79 m_info = windowsDeviceLookup()->at(m_infoIndex);
80 m_havePageSizes = m_info.m_havePageSizes;
81 m_pageSizes = m_info.m_pageSizes;
82 m_haveResolutions = m_info.m_haveResolutions;
83 m_resolutions = m_info.m_resolutions;
84 m_haveCopies = m_info.m_haveCopies;
85 m_supportsMultipleCopies = m_info.m_supportsMultipleCopies;
86 m_supportsCollateCopies = m_info.m_supportsCollateCopies;
87 m_haveMinMaxPageSizes = m_info.m_haveMinMaxPageSizes;
88 m_minimumPhysicalPageSize = m_info.m_minimumPhysicalPageSize;
89 m_maximumPhysicalPageSize = m_info.m_maximumPhysicalPageSize;
90 m_supportsCustomPageSizes = m_info.m_supportsCustomPageSizes;
91 m_haveInputSlots = m_info.m_haveInputSlots;
92 m_inputSlots = m_info.m_inputSlots;
93 m_haveOutputBins = m_info.m_haveOutputBins;
94 m_outputBins = m_info.m_outputBins;
95 m_haveDuplexModes = m_info.m_haveDuplexModes;
96 m_duplexModes = m_info.m_duplexModes;
97 m_haveColorModes = m_info.m_haveColorModes;
98 m_colorModes = m_info.m_colorModes;
99 m_infoIndex = windowsDeviceLookup()->indexOf(m_info);
101 windowsDeviceLookup()->append(m_info);
102 m_infoIndex = windowsDeviceLookup()->count() - 1;
123QPrint::DeviceState QWindowsPrintDevice::state()
const
126 GetPrinter(m_hPrinter, 6, 0, 0, &needed);
127 QScopedArrayPointer<BYTE> buffer(
new BYTE[needed]);
129 if (GetPrinter(m_hPrinter, 6, buffer.data(), needed, &needed)) {
130 PPRINTER_INFO_6 info =
reinterpret_cast<PPRINTER_INFO_6>(buffer.data());
132 if (info->dwStatus == 0
133 || (info->dwStatus & PRINTER_STATUS_WAITING) == PRINTER_STATUS_WAITING
134 || (info->dwStatus & PRINTER_STATUS_POWER_SAVE) == PRINTER_STATUS_POWER_SAVE) {
136 }
else if ((info->dwStatus & PRINTER_STATUS_PRINTING) == PRINTER_STATUS_PRINTING
137 || (info->dwStatus & PRINTER_STATUS_BUSY) == PRINTER_STATUS_BUSY
138 || (info->dwStatus & PRINTER_STATUS_INITIALIZING) == PRINTER_STATUS_INITIALIZING
139 || (info->dwStatus & PRINTER_STATUS_IO_ACTIVE) == PRINTER_STATUS_IO_ACTIVE
140 || (info->dwStatus & PRINTER_STATUS_PROCESSING) == PRINTER_STATUS_PROCESSING
141 || (info->dwStatus & PRINTER_STATUS_WARMING_UP) == PRINTER_STATUS_WARMING_UP) {
142 return QPrint::Active;
146 return QPrint::Error;
149void QWindowsPrintDevice::loadPageSizes()
const
152 const int paperCount = DeviceCapabilities(wcharId(),
nullptr, DC_PAPERNAMES,
nullptr,
nullptr);
154 && DeviceCapabilities(wcharId(),
nullptr, DC_PAPERSIZE,
nullptr,
nullptr) == paperCount
155 && DeviceCapabilities(wcharId(),
nullptr, DC_PAPERS,
nullptr,
nullptr) == paperCount) {
157 QScopedArrayPointer<
wchar_t> paperNames(
new wchar_t[paperCount*64]);
158 QScopedArrayPointer<POINT> winSizes(
new POINT[paperCount]);
159 QScopedArrayPointer<
wchar_t> papers(
new wchar_t[paperCount]);
162 if (DeviceCapabilities(wcharId(),
nullptr, DC_PAPERNAMES, paperNames.data(),
nullptr) == paperCount
163 && DeviceCapabilities(wcharId(),
nullptr, DC_PAPERSIZE,
164 reinterpret_cast<
wchar_t *>(winSizes.data()),
nullptr) == paperCount
165 && DeviceCapabilities(wcharId(),
nullptr, DC_PAPERS, papers.data(),
nullptr) == paperCount) {
168 const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
169 for (
int i = 0; i <
int(paperCount); ++i) {
170 QSize size = QSize(qRound((winSizes[i].x / 10.0) * multiplier), qRound((winSizes[i].y / 10.0) * multiplier));
171 wchar_t *paper = paperNames.data() + (i * 64);
172 QString name = QString::fromWCharArray(paper, qwcsnlen(paper, 64));
173 m_pageSizes.append(createPageSize(papers[i], size, name));
179 m_havePageSizes =
true;
180 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
181 info[m_infoIndex].m_havePageSizes =
true;
182 info[m_infoIndex].m_pageSizes = m_pageSizes;
210QMarginsF QWindowsPrintDevice::printableMargins(
const QPageSize &pageSize,
211 QPageLayout::Orientation orientation,
212 int resolution)
const
216 QMarginsF margins = QMarginsF(0, 0, 0, 0);
218 GetPrinter(m_hPrinter, 2, 0, 0, &needed);
219 QScopedArrayPointer<BYTE> buffer(
new BYTE[needed]);
220 if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) {
221 PPRINTER_INFO_2 info =
reinterpret_cast<PPRINTER_INFO_2>(buffer.data());
222 LPDEVMODE devMode = info->pDevMode;
223 bool separateDevMode =
false;
226 devMode = getDevmode(m_hPrinter, m_id);
229 separateDevMode =
true;
232 HDC pDC = CreateDC(
nullptr, wcharId(),
nullptr, devMode);
233 if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) {
234 devMode->dmPaperSize = 0;
235 devMode->dmPaperWidth = pageSize.size(QPageSize::Millimeter).width() * 10.0;
236 devMode->dmPaperLength = pageSize.size(QPageSize::Millimeter).height() * 10.0;
238 devMode->dmPaperSize = pageSize.windowsId();
240 devMode->dmPrintQuality = resolution;
241 devMode->dmOrientation = orientation == QPageLayout::Portrait ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
242 ResetDC(pDC, devMode);
243 const int dpiWidth = GetDeviceCaps(pDC, LOGPIXELSX);
244 const int dpiHeight = GetDeviceCaps(pDC, LOGPIXELSY);
245 const qreal wMult = 72.0 / dpiWidth;
246 const qreal hMult = 72.0 / dpiHeight;
247 const qreal physicalWidth = GetDeviceCaps(pDC, PHYSICALWIDTH) * wMult;
248 const qreal physicalHeight = GetDeviceCaps(pDC, PHYSICALHEIGHT) * hMult;
249 const qreal printableWidth = GetDeviceCaps(pDC, HORZRES) * wMult;
250 const qreal printableHeight = GetDeviceCaps(pDC, VERTRES) * hMult;
251 const qreal leftMargin = GetDeviceCaps(pDC, PHYSICALOFFSETX)* wMult;
252 const qreal topMargin = GetDeviceCaps(pDC, PHYSICALOFFSETY) * hMult;
253 const qreal rightMargin = physicalWidth - leftMargin - printableWidth;
254 const qreal bottomMargin = physicalHeight - topMargin - printableHeight;
255 margins = QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin);
263void QWindowsPrintDevice::loadResolutions()
const
265 const int resCount = DeviceCapabilities(wcharId(),
nullptr, DC_ENUMRESOLUTIONS,
nullptr,
nullptr);
267 QScopedArrayPointer<LONG> resolutions(
new LONG[resCount*2]);
269 if (DeviceCapabilities(wcharId(),
nullptr, DC_ENUMRESOLUTIONS,
270 reinterpret_cast<LPWSTR>(resolutions.data()),
nullptr) == resCount) {
271 for (
int i = 0; i <
int(resCount * 2); i += 2)
272 m_resolutions.append(resolutions[i+1]);
275 m_haveResolutions =
true;
276 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
277 info[m_infoIndex].m_haveResolutions =
true;
278 info[m_infoIndex].m_resolutions = m_resolutions;
281int QWindowsPrintDevice::defaultResolution()
const
285 if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
287 if (pDevMode->dmFields & DM_YRESOLUTION) {
288 if (pDevMode->dmPrintQuality > 0)
289 resolution = pDevMode->dmPrintQuality;
291 resolution = pDevMode->dmYResolution;
299void QWindowsPrintDevice::loadInputSlots()
const
301 const auto printerId = wcharId();
302 const int binCount = DeviceCapabilities(printerId,
nullptr, DC_BINS,
nullptr,
nullptr);
304 && DeviceCapabilities(printerId,
nullptr, DC_BINNAMES,
nullptr,
nullptr) == binCount) {
306 QScopedArrayPointer<WORD> bins(
new WORD[binCount]);
307 QScopedArrayPointer<
wchar_t> binNames(
new wchar_t[binCount*24]);
310 if (DeviceCapabilities(printerId,
nullptr, DC_BINS,
311 reinterpret_cast<LPWSTR>(bins.data()),
nullptr) == binCount
312 && DeviceCapabilities(printerId,
nullptr, DC_BINNAMES, binNames.data(),
313 nullptr) == binCount) {
315 for (
int i = 0; i <
int(binCount); ++i) {
316 wchar_t *binName = binNames.data() + (i * 24);
317 QString name = QString::fromWCharArray(binName, qwcsnlen(binName, 24));
318 m_inputSlots.append(QPrintUtils::paperBinToInputSlot(bins[i], name));
324 m_haveInputSlots =
true;
325 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
326 info[m_infoIndex].m_haveInputSlots =
true;
327 info[m_infoIndex].m_inputSlots = m_inputSlots;
330QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot()
const
332 QPrint::InputSlot inputSlot = QPlatformPrintDevice::defaultInputSlot();
334 if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
336 if (pDevMode->dmFields & DM_DEFAULTSOURCE) {
337 QPrint::InputSlot tempSlot =
338 QPrintUtils::paperBinToInputSlot(pDevMode->dmDefaultSource, QString());
339 const auto inputSlots = supportedInputSlots();
340 for (
const QPrint::InputSlot &slot : inputSlots) {
341 if (slot.key == tempSlot.key) {
362void QWindowsPrintDevice::loadDuplexModes()
const
364 m_duplexModes.append(QPrint::DuplexNone);
365 DWORD duplex = DeviceCapabilities(wcharId(),
nullptr, DC_DUPLEX,
nullptr,
nullptr);
366 if (
int(duplex) == 1) {
368 m_duplexModes.append(QPrint::DuplexAuto);
369 m_duplexModes.append(QPrint::DuplexLongSide);
370 m_duplexModes.append(QPrint::DuplexShortSide);
372 m_haveDuplexModes =
true;
373 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
374 info[m_infoIndex].m_haveDuplexModes =
true;
375 info[m_infoIndex].m_duplexModes = m_duplexModes;
378QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode()
const
380 QPrint::DuplexMode duplexMode = QPrint::DuplexNone;
382 if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
384 if (pDevMode->dmFields & DM_DUPLEX) {
385 if (pDevMode->dmDuplex == DMDUP_VERTICAL)
386 duplexMode = QPrint::DuplexLongSide;
387 else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL)
388 duplexMode = QPrint::DuplexShortSide;
396void QWindowsPrintDevice::loadColorModes()
const
398 m_colorModes.append(QPrint::GrayScale);
399 DWORD color = DeviceCapabilities(wcharId(),
nullptr, DC_COLORDEVICE,
nullptr,
nullptr);
401 m_colorModes.append(QPrint::Color);
402 m_haveColorModes =
true;
403 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
404 info[m_infoIndex].m_haveColorModes =
true;
405 info[m_infoIndex].m_colorModes = m_colorModes;
408QPrint::ColorMode QWindowsPrintDevice::defaultColorMode()
const
410 if (!m_haveColorModes)
412 if (!m_colorModes.contains(QPrint::Color))
413 return QPrint::GrayScale;
415 QPrint::ColorMode colorMode = QPrint::GrayScale;
417 if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
419 if (pDevMode->dmFields & DM_COLOR && pDevMode->dmColor == DMCOLOR_COLOR)
420 colorMode = QPrint::Color;
427QStringList QWindowsPrintDevice::availablePrintDeviceIds()
432 if ((!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
nullptr, 4, 0, 0, &needed, &returned)
433 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
437 QScopedArrayPointer<BYTE> buffer(
new BYTE[needed]);
438 if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
nullptr, 4, buffer.data(), needed, &needed, &returned))
440 PPRINTER_INFO_4 infoList =
reinterpret_cast<PPRINTER_INFO_4>(buffer.data());
441 for (uint i = 0; i < returned; ++i)
442 list.append(QString::fromWCharArray(infoList[i].pPrinterName));
457void QWindowsPrintDevice::loadCopiesSupport()
const
459 auto printerId = wcharId();
460 m_supportsMultipleCopies = (DeviceCapabilities(printerId,
nullptr, DC_COPIES,
nullptr,
nullptr) > 1);
461 m_supportsCollateCopies = DeviceCapabilities(printerId,
nullptr,
DC_COLLATE,
nullptr,
nullptr);
463 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
464 info[m_infoIndex].m_haveCopies =
true;
465 info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies;
466 info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies;
504void QWindowsPrintDevice::loadMinMaxPageSizes()
const
507 const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
508 auto printerId = wcharId();
509 DWORD min = DeviceCapabilities(printerId,
nullptr, DC_MINEXTENT,
nullptr,
nullptr);
510 m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier);
511 DWORD max = DeviceCapabilities(printerId,
nullptr, DC_MAXEXTENT,
nullptr,
nullptr);
512 m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier);
513 m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0);
514 m_haveMinMaxPageSizes =
true;
515 QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
516 info[m_infoIndex].m_haveCopies =
true;
517 info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies;
518 info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies;