AddJob + SetPrinter: возможно ли установить dmCopies и получить эффект?

Что мне нужно, это повторно распечатать буферный файл (не задание *) снова, установив новое количество копий.

На данный момент были предприняты следующие попытки:

  • OpenPrinter, AddJob, SetJob (с JOB_INFO_2-> pDevMode)
  • OpenPrinter, SetPrinter, DocumentProperties, AddJob, SetJob
  • OpenPrinter, StartDocPrinter, StartPagePrinter, WritePrinter

Многочисленные комбинации ClosePrinter и несколько обходных путей для части SetPrinter..DocumentProperties — безуспешно.

Смена принтеров (HP на Brother), перезапуск спулера и ПК — безрезультатно.

В списке заданий на печать видно, что задано количество копий. Однако, то, что я получаю из принтера, является одной копией.

Также, pDevMode->dmFields устанавливается с |= DM_COPIES во всех соответствующих случаях.

Итак, есть ли эффективный способ установить количество копий, возможно, другие параметры (сопоставить) и распечатать необработанный документ PCL / PS, не обращаясь к GDI или не печатая задание много раз?

#include "006_pclblacky_t.h"#define PNAME L"HP"
t_006pclblacky::t_006pclblacky()
{
settings.color.set = false;
settings.copies.set = false;
settings.ori.set = false;
settings.paper.set = false;
}t_006pclblacky::~t_006pclblacky()
{
}

int t_006pclblacky::Run()
{
int rc = 0;

rc = subtest_001();
if (rc != 0) return rc;

return 0;

}

void t_006pclblacky::defaults() {
}

void t_006pclblacky::GetJobInfo(int JobId)
{
HANDLE ph;
DOC_INFO_1 di1;
DWORD dwRead, dwWritten;
DWORD x,y,z;
int rc;
PRINTER_DEFAULTSW Defaults = { NULL, NULL, PRINTER_ALL_ACCESS};
OpenPrinter(PNAME, &ph, &Defaults);try {
rc = GetJob(ph, JobId, 1, NULL, 0, &x);
if (rc != 122 && x < 1) {
assert(122 == 0);
}
} catch (...) {
assert(1 == 0);
}

JOB_INFO_1 *jg1 = (JOB_INFO_1*)malloc(x);
try {
GetJob(ph, JobId, 1, (LPBYTE)jg1, x, &y);
} catch (...) {
assert(1 == 0);
}

jg1->TotalPages = 2;rc = SetJob(ph, JobId, 1, (LPBYTE)jg1, JOB_CONTROL_PAUSE);
assert (rc > 0);
rc = GetLastError();

try {
if (GetJob(ph, JobId, 2, NULL, 0, &x) != 122 && x < 1) {
assert(122 == 0);
}
} catch (...) {
assert(1 == 0);
}
//jg1->PagesPrinted = 1;

JOB_INFO_2 *jg2 = (JOB_INFO_2*)malloc(x);
try {
GetJob(ph, JobId, 2, (LPBYTE)jg2, x, &y);
} catch (...) {
assert(1 == 0);
}
}void t_006pclblacky::SendFileToPrinter(LPCWSTR fileName, LPWSTR docName)
{

HANDLE ph;
DOC_INFO_1 di1;
DWORD dwRead, dwWritten;std::ifstream file(fileName, ios::in | ios::binary | ios::ate);
std::ifstream::pos_type fileSize;
char* fileContents;
int rc;
PRINTER_DEFAULTSW Defaults = { NULL, NULL, PRINTER_ALL_ACCESS};
LPDEVMODE devmOld = NULL;
OpenPrinter(PNAME, &ph, &Defaults);

di1.pDatatype = L"RAW"; // IsV4Driver("Printer Name") ? "XPS_PASS" : "RAW";
di1.pDocName = docName;
di1.pOutputFile = NULL;

fileSize = file.tellg();
if (fileSize < 1) {
return;
}

fileContents = new char[fileSize];
file.seekg(0, ios::beg);
if (!file.read(fileContents, fileSize))
{
assert(0 == 1);
}

dwRead = fileSize;

if (!settings.ori.set && !settings.color.set && !settings.copies.set && !settings.paper.set) {
StartDocPrinter(ph, 1, (LPBYTE)&di1);

StartPagePrinter(ph);

if (file.is_open())
{
WritePrinter(ph, fileContents, dwRead, &dwWritten);
file.close();
}
else {
assert(0 == 1);
}

EndPagePrinter(ph);

EndDocPrinter(ph);
} else {
devmOld = GetPrinterParams(ph);
ClosePrinter(ph);
Defaults.pDevMode = devmOld;
OpenPrinter(PNAME, &ph, &Defaults);
//ClosePrinter(ph);
//OpenPrinter(PNAME, &ph, &Defaults);
SetPrinterParams(ph);
//ClosePrinter(ph);
//OpenPrinter(PNAME, &ph, &Defaults);

int tsz = sizeof(ADDJOB_INFO_1)+MAX_PATH+1;
ADDJOB_INFO_1 *aji = (ADDJOB_INFO_1*)malloc(tsz);
DWORD d = 0;
rc = AddJob(ph, 1, (LPBYTE)aji, tsz, &d);
if (rc == 0) {
rc = GetLastError();
}
assert (aji->JobId != 0);

DWORD x,y,z;

try {
rc = GetJob(ph, aji->JobId, 1, NULL, 0, &x);
if (rc != 122 && x < 1) {
assert(122 == 0);
}
} catch (...) {
assert(1 == 0);
}

JOB_INFO_1 *jg1 = (JOB_INFO_1*)malloc(x);
try {
GetJob(ph, aji->JobId, 1, (LPBYTE)jg1, x, &y);
} catch (...) {
assert(1 == 0);
}

/*JOB_INFO_1 *ji1 = (JOB_INFO_1*)malloc(sizeof(JOB_INFO_1));
ji1->pDatatype = L"RAW";
ji1->pPrinterName = jg1->pPrinterName;
ji1->TotalPages = 2; // test
ji1->pDocument = jg1->pDocument;
ji1->pMachineName = jg1->pMachineName;
ji1->pUserName = jg1->pUserName;*/
jg1->TotalPages = 1;
jg1->pDocument = docName;rc = SetJob(ph, aji->JobId, 1, (LPBYTE)jg1, JOB_CONTROL_PAUSE);
assert (rc > 0);
rc = GetLastError();

try {
if (GetJob(ph, aji->JobId, 2, NULL, 0, &x) != 122 && x < 1) {
assert(122 == 0);
}
} catch (...) {
assert(1 == 0);
}
jg1->PagesPrinted = 2;
jg1->TotalPages = 2;

JOB_INFO_2 *jg2 = (JOB_INFO_2*)malloc(x);
try {
GetJob(ph, aji->JobId, 2, (LPBYTE)jg2, x, &y);
} catch (...) {
assert(1 == 0);
}
/*JOB_INFO_2 *ji2 = (JOB_INFO_2*)malloc(sizeof(JOB_INFO_2));
ji2->pDevMode = (PDEVMODE)malloc(sizeof(DEVMODE));
ji2->pDevMode->dmPaperSize = settings.paper.val;
ji2->pDatatype = L"RAW";
ji2->pPrinterName = jg2->pPrinterName;
ji2->TotalPages = 2;
*/

DWORD dmf = jg2->pDevMode->dmFields;
dmf = DM_COLLATE;if (settings.copies.set) {
if (! jg2->pDevMode->dmFields & DM_COPIES) {
jg2->pDevMode->dmFields |= DM_COPIES;
}
jg2->pDevMode->dmCopies = settings.copies.val;
}
if (settings.color.set) {
jg2->pDevMode->dmColor = settings.color.val;
jg2->pDevMode->dmFields |= DM_COLOR;
}
if (settings.ori.set) {
jg2->pDevMode->dmOrientation = settings.ori.val;
jg2->pDevMode->dmFields |= DM_ORIENTATION;
}
if (settings.paper.set) {
jg2->pDevMode->dmPaperSize = settings.paper.val;
jg2->pDevMode->dmFields |= DM_PAPERSIZE;
}
jg2->TotalPages = 2;
jg2->PagesPrinted = 2;
// Çàïèñàòü ôàéë çàäàíèÿ
std::ofstream file2(aji->Path, ios::out | ios::binary | ios::ate);
file2.write(fileContents, fileSize);
file2.flush();
file2.close();

rc = SetJob(ph, aji->JobId, 2, (LPBYTE)jg2, JOB_CONTROL_RESTART);
assert(rc > 0);
rc = GetLastError();
GetJob(ph, aji->JobId, 2, (LPBYTE)jg2, x, &y);

ScheduleJob(ph, aji->JobId);
}

if (devmOld != NULL) {
ClosePrinter(ph);
OpenPrinter(PNAME, &ph, &Defaults);
RestorePrinterParams(ph, devmOld);
}

ClosePrinter(ph);
}

int t_006pclblacky::subtest_001()
{
defaults();
SetCopies(2);
SetOrientation(2);
SendFileToPrinter(L"test.pcl", L"test.pcl");
}

return rc;
}

t_006pclblacky* t_006pclblacky::SetOrientation(int i)
{
this->settings.ori.set = true;
this->settings.ori.val = i;
return this;
}
t_006pclblacky* t_006pclblacky::SetColor(int i)
{
this->settings.color.set = true;
this->settings.color.val = i;
return this;
}
t_006pclblacky* t_006pclblacky::SetCopies(int i)
{
this->settings.copies.set = true;
this->settings.copies.val = i;
return this;
}

t_006pclblacky* t_006pclblacky::SetPaperSize(int i)
{
this->settings.paper.set = true;
this->settings.paper.val = i;
return this;
}

void t_006pclblacky::SetPrinterParams(HANDLE ph)
{ // http://www.rsdn.ru/forum/dotnet/4070489.flat
// http://www.codeproject.com/Articles/132365/Configuring-Printer-Settings-Programmatically

DWORD dwNeeded, dwNeeded2;
int rc = GetPrinter(ph, 2, 0, 0, &dwNeeded);
if (rc != 0 || (rc == 0 && dwNeeded > 0 && dwNeeded < 10240 /* TODO magic? */)) {
PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR,dwNeeded);
GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
// check that the driver supports the changes

int x = DocumentProperties(NULL, ph, PNAME, NULL, pi2->pDevMode, DM_OUT_BUFFER);
//        LPDEVMODE y = (LPDEVMODE)malloc(x);
//
//        rc = DocumentProperties(NULL, ph, PNAME, NULL, y, DM_OUT_BUFFER);

AffectDevMode(pi2->pDevMode);
//pi2->pDevMode = y;
pi2->pSecurityDescriptor = 0;

::DocumentProperties (NULL, ph, PNAME, NULL, pi2->pDevMode, DM_IN_BUFFER);
rc = SetPrinter(ph, 2, (LPBYTE)pi2, 0);
}rc = GetPrinter(ph, 2, 0, 0, &dwNeeded2);
if (rc != 0 || (rc == 0 && dwNeeded2 > 0 && dwNeeded2 < 10240 /* TODO magic? */)) {
PRINTER_INFO_2 *pi3 = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR,dwNeeded2);
GetPrinter(ph, 2, (LPBYTE)pi3, dwNeeded, &dwNeeded);
assert(pi3->pDevMode->dmCopies > 1);
}

}

void t_006pclblacky::RestorePrinterParams(HANDLE ph, LPDEVMODE old)
{
DWORD dwNeeded;
GetPrinter(ph, 2, 0, 0, &dwNeeded);
PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR,dwNeeded);
GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);

if (settings.copies.set) {

pi2->pDevMode->dmCopies = old->dmCopies;
}
if (settings.color.set) {
pi2->pDevMode->dmColor = old->dmColor;
}
if (settings.ori.set) {
pi2->pDevMode->dmOrientation = old->dmOrientation;
}
if (settings.paper.set) {
pi2->pDevMode->dmPaperSize = old->dmPaperSize;
}
//ClosePrinter(ph);
}

void t_006pclblacky::AffectDevMode(LPDEVMODE dm)
{
/* if(dm->dmFields & DM_PAPERSIZE )
{
// define the page size as A3
dm->dmPaperSize = DMPAPER_A3;
// define, which field was changed
dm->dmFields |= DM_PAPERSIZE;
}*/

if (settings.copies.set) {
if (! dm->dmFields & DM_COPIES) {
dm->dmFields |= DM_COPIES;
}
dm->dmCopies = settings.copies.val;
}
if (settings.color.set) {
dm->dmColor = settings.color.val;
dm->dmFields |= DM_COLOR;
}
if (settings.ori.set) {
dm->dmOrientation = settings.ori.val;
dm->dmFields |= DM_ORIENTATION;
}
if (settings.paper.set) {
dm->dmPaperSize = settings.paper.val;
dm->dmFields |= DM_PAPERSIZE;
}}

LPDEVMODE t_006pclblacky::GetPrinterParams(HANDLE ph)
{
LPDEVMODE out;
DWORD dwNeeded;
GetPrinter(ph, 2, 0, 0, &dwNeeded);
PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR,dwNeeded);
GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);

DWORD lNeeded = pi2->pDevMode->dmSize + pi2->pDevMode->dmDriverExtra;
out = (LPDEVMODEW) malloc(lNeeded);
memcpy(out, pi2->pDevMode, lNeeded);

//        ClosePrinter(ph);

return out;
}

1

Решение

Одна фундаментальная ошибка, которую вы делаете, сбивает с толку TotalPages в JOB_INFO_1 структура с количеством копий для печати. TotalPages количество страниц в задании на печать, а не количество копий для печати. Так, например, если вы печатаете 10-страничный документ, вы должны ожидать увидеть 10 в этом поле.

На самом деле, вы можете многое забыть SetJob как способ достижения этого. Хотя кажется, что счетчик копий должен быть элементом задания на печать, это не так. Это элемент документа, который был напечатан и указан в DEVMODE перешел к DocumentProperties, Изменение количества копий после факта может быть достигнуто только путем изменения dmCopies в DEVMODE, который хранится в файле спула. Одним из вариантов будет анализ файла спула и изменение там значения. Вы можете найти формат файла спула Вот.

Но то, как вы пытаетесь сделать это с помощью StartDocPrinter и т. д. также должно работать. Я считаю, что у вас должна быть ошибка в вашем SetPrinterParams функция или одна из функций, которые она вызывает. Войдите в этот код в отладчике и убедитесь, что dmCopies это значение, которое вы хотите перед вызовом DocumentPropertiesи убедитесь, что ни одна из функций Win32 не работает.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]