При работе с принтерами Epson TM 30 (и другими POS-принтерами) на рулонной бумаге 80 мм разработчики часто сталкиваются с проблемой: несмотря на правильные настройки в системе Windows, при открытии диалога печати из Delphi по умолчанию выбирается формат A4 вместо нужного "бесконечного рулона 80 мм".
Как отмечает пользователь в вопросе, даже после установки правильного размера бумаги в настройках принтера Windows, при каждом запуске процедуры печати размер снова сбрасывается на A4.
Решение проблемы
1. Проверка и установка драйверов
Перед программным решением убедитесь, что: - Установлены официальные драйверы Epson TM 30 (не универсальные драйверы Windows) - В настройках принтера в Windows выбран правильный размер бумаги - Отключено автоматическое управление принтерами в Windows
2. Получение списка доступных размеров бумаги
Для работы с размерами бумаги в Delphi можно использовать WinAPI функцию DeviceCapabilities. Вот пример функции, которая возвращает список доступных форматов бумаги:
type
TPrinterValueNamePair = record
Name: string;
Value: SmallInt;
end;
TPrinterValueNamePairs = array of TPrinterValueNamePair;
function GetPaperSizes: TPrinterValueNamePairs;
var
device, driver, port: array[0..255] of char;
hDMode: THandle;
hPrinter: THandle;
Len: Integer;
PaperNames: array of array[0..63] of char;
PaperNumbers: array of word;
I: Integer;
begin
SetLength(Result, 0);
Printer.PrinterIndex := Printer.PrinterIndex;
Printer.GetPrinter(device, driver, port, hDMode);
if OpenPrinter(device, hPrinter, nil) then
try
// Получаем названия форматов бумаги
Len := DeviceCapabilities(device, port, DC_PAPERNAMES, nil, nil);
if Len > 0 then
begin
SetLength(PaperNames, Len);
DeviceCapabilities(device, port, DC_PAPERNAMES, @PaperNames[0], nil);
end;
// Получаем номера форматов бумаги
Len := DeviceCapabilities(device, port, DC_PAPERS, nil, nil);
if Len > 0 then
begin
SetLength(PaperNumbers, Len);
DeviceCapabilities(device, port, DC_PAPERS, @PaperNumbers[0], nil);
end;
// Формируем результат
SetLength(Result, Length(PaperNumbers));
for I := 0 to High(PaperNumbers) do
begin
Result[I].Value := PaperNumbers[I];
if I < Length(PaperNames) then
Result[I].Name := PaperNames[I]
else
Result[I].Name := '[' + IntToStr(PaperNumbers[I]) + ']';
end;
finally
ClosePrinter(hPrinter);
end;
end;
3. Установка нужного размера бумаги
Для установки конкретного размера бумаги можно использовать следующую процедуру:
procedure SetPrinterPaperSize(APaperSize: SmallInt);
var
device, driver, port: array[0..255] of char;
hDMode: THandle;
pDMode: PDEVMODE;
begin
Printer.PrinterIndex := Printer.PrinterIndex;
Printer.GetPrinter(device, driver, port, hDMode);
if hDMode <> 0 then
begin
pDMode := GlobalLock(hDMode);
if Assigned(pDMode) then
try
pDMode^.dmPaperSize := APaperSize;
pDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE;
finally
GlobalUnlock(hDMode);
end;
end;
// Обновляем состояние принтера
Printer.Copies := Printer.Copies;
end;
4. Определение текущего размера бумаги
Чтобы узнать текущий установленный размер бумаги:
function GetCurrentPaperSize: SmallInt;
var
device, driver, port: array[0..255] of char;
hDMode: THandle;
pDMode: PDEVMODE;
begin
Result := 0;
Printer.PrinterIndex := Printer.PrinterIndex;
Printer.GetPrinter(device, driver, port, hDMode);
if hDMode <> 0 then
begin
pDMode := GlobalLock(hDMode);
if Assigned(pDMode) then
try
Result := pDMode^.dmPaperSize;
finally
GlobalUnlock(hDMode);
end;
end;
end;
5. Поиск нужного формата бумаги
Для POS-принтеров Epson TM 30 обычно используются следующие константы: - DMPAP_ROLL_80 (80 мм рулонная бумага) - DMPAP_ROLL_58 (58 мм рулонная бумага)
Однако эти константы могут отличаться в зависимости от драйвера. Лучший способ - перечислить все доступные форматы и найти нужный по имени:
function FindPaperSizeByName(const AName: string): SmallInt;
var
PaperSizes: TPrinterValueNamePairs;
I: Integer;
begin
Result := 0; // По умолчанию
PaperSizes := GetPaperSizes;
for I := 0 to High(PaperSizes) do
begin
if Pos(AName, PaperSizes[I].Name) > 0 then
begin
Result := PaperSizes[I].Value;
Break;
end;
end;
end;
Пример использования:
procedure TForm1.ButtonPrintClick(Sender: TObject);
var
PaperSize: SmallInt;
begin
// Находим и устанавливаем 80 мм рулонную бумагу
PaperSize := FindPaperSizeByName('80mm');
if PaperSize > 0 then
SetPrinterPaperSize(PaperSize)
else
ShowMessage('Не удалось найти размер бумаги 80mm');
// Далее ваша логика печати
Printer.BeginDoc;
try
Printer.Canvas.TextOut(10, 10, 'Тест печати на Epson TM-30');
finally
Printer.EndDoc;
end;
end;
Альтернативное решение: прямой вывод на принтер
Для POS-принтеров часто более надежным решением является прямой вывод команд ESC/POS, минуя драйвер Windows:
procedure DirectPrintToEpsonTM30;
var
hPrinter: THandle;
DocInfo: TDocInfo1;
BytesWritten: DWORD;
Data: AnsiString;
begin
// Открываем принтер по имени
if OpenPrinter('Epson TM-T30', hPrinter, nil) then
try
// Начинаем документ
FillChar(DocInfo, SizeOf(DocInfo), 0);
DocInfo.pDocName := 'POS Print';
DocInfo.pOutputFile := nil;
DocInfo.pDatatype := 'RAW';
StartDocPrinter(hPrinter, 1, @DocInfo);
StartPagePrinter(hPrinter);
try
// ESC/POS команды для инициализации, выбора режима и печати текста
Data := #27'@' + // Инициализация принтера
'Test print on Epson TM-T30'#10#13 +
#29'V'#66#0; // Частичный отрез
WritePrinter(hPrinter, @Data[1], Length(Data), BytesWritten);
finally
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
end;
finally
ClosePrinter(hPrinter);
end
else
RaiseLastOSError;
end;
Заключение
Проблема с автоматическим сбросом размера бумаги в Epson TM-30 при печати из Delphi решается: 1. Установкой правильных драйверов 2. Программной установкой размера бумаги перед печатью 3. Либо использованием прямого вывода ESC/POS команд
Представленные примеры кода позволяют: - Получить список доступных размеров бумаги - Установить нужный размер программно - Определить текущий размер бумаги - Осуществить прямой вывод на принтер
Для POS-систем рекомендуется использовать прямое управление принтером через ESC/POS команды, так как это обеспечивает более предсказуемое поведение и не зависит от настроек драйвера Windows.
Решение проблемы программной установки размера бумаги для принтера Epson TM 30 в Delphi с примерами кода.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.