Вызов WinAPI DeviceCapabilities(DC_ENUMRESOLUTIONS) для Epson P50 всегда сообщает об ошибке

Я столкнулся с некоторым странным поведением - кажется, невозможно перечислить разрешения для струйных принтеров Epson в Windows. в частности, этот код всегда сообщает об ошибке:

int r, err;
char szBuffer[0x4000];
String prnName = "EPSON P50 Series";
String portName = "USB002";

r = DeviceCapabilities(prnName.c_str(), portName.c_str(), DC_ENUMRESOLUTIONS, NULL, NULL);
err = GetLastError();
printf("\n 1.DevCap.result = %d, err = %d", r, err);

r = DeviceCapabilities(prnName.c_str(), portName.c_str(), DC_ENUMRESOLUTIONS, szBuffer, NULL);
err = GetLastError();
printf("\n 2.DevCap.result = %d, err = %d", r, err);

В выводе вижу следующее:

1.DevCap.result = -1, err = 0
2.DevCap.result = -1, err = 13

Примечание. Ошибка Windows 13 — ERROR_INVALID_DATA.

Не могли бы вы помочь мне понять - как правильно это интерпретировать? Означает ли это, что драйверы для струйных принтеров Epson не предоставляют никакой информации о поддерживаемых разрешениях печати? Или действительно переданы какие-то недопустимые параметры? Если да, то какой это может быть?

Заранее спасибо.

PS. Обратите внимание на следующее:

1) Имена принтеров и портов правильные. Они получаются с помощью EnumPrinters() вызова WinAPI. В этом примере кода я вырезал весь ненужный код, поэтому оставил только те функции, которые не работают.

2) Сам принтер работает нормально, я могу печатать на нем документы и фотографии.

3) Также я добавил принтер "Epson Stylus 300", который настроен на использование порта "ФАЙЛ:" для печати. И что интересно - вызов DeviceCapabilities(DC_ENUMRESOLUTIONS) для такого принтера тоже выдает ошибку № 13. Поэтому я склоняюсь к тому, что все струйные принтеры Epson не предоставляют никакой информации о разрешении печати...

4) Все остальные вызовы функции DeviceCapabilities() (для DC_PAPERS, DC_PAPERSIZE, DC_PAPERNAMES и т. д.) нормально работают для этих принтеров (Epson P50 и Epson Stylus 300). Итак, имя принтера и имя порта правильные, проблема существует только для вызова DeviceCapabilities(DC_ENUMRESOLUTIONS).


person dmitry_bond    schedule 21.01.2016    source источник
comment
Это должно быть прямо вперед. Скорее всего эти два принтера не поддерживают флаг DC_ENUMRESOLUTIONS. Установите принтер другой фирмы, возможно, он будет работать.   -  person Barmak Shemirani    schedule 21.01.2016
comment
Да, я знаю, что это работает для других принтеров. Это программное обеспечение работало в течение многих лет, только теперь, когда я пытаюсь печатать на Epson, у меня возникает эта проблема. Я просто немного озадачен тем, что принтер не предоставляет список поддерживаемых разрешений, и что это значит для меня? Могу ли я указать разрешение = 12345 и ожидать правильную распечатку?   -  person dmitry_bond    schedule 21.01.2016


Ответы (2)


Кажется, это ошибка с этими принтерами Epson. Однако значения разрешения зависят от устройства, и вам все равно это не нужно.

Вы можете получить разрешение принтера через DEVMODE и просто сообщить об этом пользователю:

PRINTDLG pdlg = { sizeof PRINTDLG };
pdlg.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
PrintDlg(&pdlg);

DEVMODE* dm = (DEVMODE*)::GlobalLock(pdlg.hDevMode);
cout << "dm->dmDeviceName: " << dm->dmDeviceName << endl;

if (dm->dmFields & DM_PRINTQUALITY)
{
    cout << "dm->dmPrintQuality: " << dm->dmPrintQuality << endl;
}

::GlobalUnlock(pdlg.hDevMode);

dmPrintQuality — это либо разрешение принтера, либо одно из следующих значений, не зависящих от устройства:

#define DMRES_DRAFT         (-1)
#define DMRES_LOW           (-2)
#define DMRES_MEDIUM        (-3)
#define DMRES_HIGH          (-4)

Если пользователь хочет изменить это значение, лучше предоставить доступ к собственному диалоговому окну настройки принтера.

person Barmak Shemirani    schedule 21.01.2016

Я подтвердил проблему с EPSON Stylus Photo RX595 Series.

Бармак Шенмирани прав, что поле dmPrintQuality поля DEVMODE будет указывать одну из отрицательных констант, чтобы дать приблизительное представление о разрешении, или положительное значение в пикселях на дюйм для горизонтального разрешения. В последнем случае вы можете получить вертикальное разрешение из поля dmYResolution файла DEVMODE.

Если вы использовали EnumPrinters с уровнем 2 (PRINTER_INFO_2) для получения имени и порта, то у вас уже есть копия стандартного DEVMODE.

Кажется разумной эвристикой предположить, что любой принтер, который выходит из строя DC_ENUMRESOLUTIONS, имеет только одно разрешение, и это разрешение по умолчанию DEVMODE. Вы можете попробовать открыть диалоговое окно печати и настроить различные ручки качества, которые он предлагает, чтобы увидеть, отличается ли разрешение в результирующем DEVMODE, но я сомневаюсь, что оно изменится.

В случае моего принтера кажется, что разрешение 360360 пикселей на дюйм, указанное в DEVMODE, является абстрактным значением, поскольку в спецификациях принтера указано «57601440 оптимизированных точек на дюйм». Предположительно драйвер сглаживает все эти точки для достижения эффективной плотности 360360 пикселей.

Чтобы убедиться, что это не просто ошибка кодирования с моей стороны, я также запустил его для своего лазерного принтера (Brother), и он сообщил о двух разрешениях: 600 600 и 300 300.

person Adrian McCarthy    schedule 24.01.2016
comment
Мне нужно знать разрешение для пересчета изображения штрих-кода, чтобы напечатать его в правильном размере. Но как я вижу - я могу указать почти любое разрешение - например, 300 или 600 - кажется, это нормально работает для моего Epson P50. Конечно, у меня нет цели постоянно печатать штрих-коды на P50, мне нужно было только какое-то реальное оборудование для тестирования нашего программного обеспечения. P50 был единственным вариантом рядом со мной... - person dmitry_bond; 27.01.2016
comment
Принтеры с высоким разрешением, вероятно, хорошо справятся с источником любого приемлемого разрешения. - person Adrian McCarthy; 27.01.2016