Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Печать на чековый принтер


Автор: Jen5on 3.8.2009, 19:50
Такое дело: есть чековый принтер Epson TM220 вродь...
Для теста написал программку вот код

Тут настраиваю и открываю...

Код

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Main.h"
#include <Registry.hpp>

#include <windows.h>
#include <stdio.h>

#define BUFSIZE 4096


//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TMainForm *MainForm;
HANDLE ComPort;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
    : TForm(Owner)
{
        _COMMTIMEOUTS ct;
        DCB* dcb;
        String COMName;
        //Открыть COM порт для печати
        COMName = "COM1";
        //Скорость принтера всегда 9600
//        int BaudRate = 9600;

        dcb = (DCB*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DCB));
        dcb->DCBlength = sizeof(DCB);
        ComPort = CreateFile(COMName.c_str(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
        if (ComPort == INVALID_HANDLE_VALUE)

                throw("Невозможно открыть указанный порт для принтера");
        else {
                if (!BuildCommDCBA("baud=9600 parity=N data=8 stop=1",dcb)) {
                        CloseHandle(ComPort);
                        ComPort = INVALID_HANDLE_VALUE;
                        throw("Невозможно создать структуру DCB");
                }
                else {
                        dcb->BaudRate = CBR_9600;
                        dcb->Parity = ODDPARITY;
                        dcb->fBinary = 1;
                        dcb->fParity = 1;
                        dcb->fOutxCtsFlow = true;
                        dcb->fOutxDsrFlow = true;
                        dcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
                        dcb->fOutX = false;
                        dcb->fInX = false;
                        dcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
                        dcb->StopBits = 0;
                        ct.ReadIntervalTimeout = 100;
                        ct.ReadTotalTimeoutMultiplier = 100;
                        ct.ReadTotalTimeoutConstant = 2000;
                        ct.WriteTotalTimeoutMultiplier = 100;
                        ct.WriteTotalTimeoutConstant = 2000;
                        if (!SetCommState(ComPort,dcb)) {
                                char *lpMsgBuf;
                                FormatMessage(
                                        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                                        NULL,
                                        GetLastError(),
                                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                                        (LPTSTR) &lpMsgBuf, 0, NULL);
                                        // Display the string.
                                        throw(lpMsgBuf);
                                        // MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
                                        // Free the buffer.
//                                        LocalFree(lpMsgBuf);
                        }
                        GetCommState(ComPort,dcb);
                        SetCommTimeouts(ComPort,&ct);
                        MainForm->Caption= "Открыт порт для печати: "+IntToStr(dcb->BaudRate)+"  паритет "+IntToStr(dcb->fParity)+"  стоп "+IntToStr(dcb->StopBits);
                        PurgeComm(ComPort,PURGE_RXABORT|PURGE_TXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR);
                        HeapFree(GetProcessHeap(),0,dcb);
                }
        }
}


Тут подготавливаю для печати данные, а потом печатаю...

Код

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
        //Подготовка и добавление начальных записей в массив строк чека
        Memo1->Lines->Clear();
        Memo1->Lines->Add("");
        Memo1->Lines->Add("Слабко Евгений Владимирович");
        Memo1->Lines->Add("№ пр.: 290140 № таб.: 290140");
        Memo1->Lines->Add("№ цеха: 29 № зак.: 1");
        Memo1->Lines->Add("№ терминала: 1");
        Memo1->Lines->Add("Дата/время: сегодня");
        Memo1->Lines->Add("--------------------------------------");

        //Подготовка и добавление итоговой записи в массив строк чека
        Memo1->Lines->Add("......................................");
        AnsiString ItogoLine="ИТОГО :";
        Memo1->Lines->Add(ItogoLine);
        Memo1->Lines->Add(" ");
        Memo1->Lines->Add("          СПАСИБО ЗА ПОКУПКУ");


        //Добавление заголовка чека во избежание пробелов (принтер обрезает бумагу слишком высоко)
        Memo1->Lines->Add("");
        Memo1->Lines->Add("");
        Memo1->Lines->Add("");
        Memo1->Lines->Add("**************************************");
        Memo1->Lines->Add("*              МАГАЗИН               *");
        Memo1->Lines->Add("**************************************");

        //Печать чека на принтер
        if(CheckBox1->Checked)
                PrintCheck(Memo1);
}


А тут собственно функция для печати....

Код

void TMainForm::PrintCheck(TMemo * SREdit)
{
        //Печать в через COM порт
        AnsiString CheckString;
        for (int i=0; i < SREdit->Lines->Count; i++) {
                CheckString = " " + SREdit->Lines->Strings[i] + "\n";
                if(i==(SREdit->Lines->Count-1))
                        CheckString = CheckString + (char)27 + (char)'m';
                char * OEMString = (char *)new char[CheckString.Length()];
                CharToOemBuff(CheckString.c_str(),OEMString,CheckString.Length());
                DWord bytes_written = 0;
                POverlapped C;
                WriteFile(ComPort,OEMString,CheckString.Length(),&bytes_written,NULL);  
                delete[] OEMString;
        }
}



Вопрос вот вчем:
Когда дело доходит до строки
     WriteFile(ComPort,OEMString,CheckString.Length(),&bytes_written,NULL);  
программа вызывает ошибку...   Access  violation at address 7C89shHG in module "kernel32.dll". Write of address 0000000
а если в последнем блоке программы

Код

                DWord bytes_written = 0;
                POverlapped C;
                WriteFile(ComPort,OEMString,CheckString.Length(),&bytes_written,NULL);  


меняю на 

Код

                DWord bytes_written = 0;
                POverlapped C;
                TOverlapped OverWrite;
                OverWrite.hEvent = CreateEvent(NULL, True, False, NULL);
                WriteFile(ComPort,OEMString,CheckString.Length(),&bytes_written,&OverWrite);



то вообще что-то долго делает и на печать ничего не выдает...
но ошибки тоже не возникает)))
(ну разве что проверить только на последнюю ошибку...)

Подскажите в чем может быть проблема. Может неправильно настроил порт или параметры в вызове WriteFile неправильные.
Кто чем может...

Исходники прилагаются...


Автор: sawfish 4.8.2009, 06:25
Вот несоответствие, которое я вижу.
Функция GetCommState заполняет структуру DCB, после ее изменения (задания своих параметров) применяется SetCommState.
А у Вас сначала идет задание параметров DCB, потом Вы ее применяете функцией SetCommState, а потом зачем-то вызываете ее заполнение (GetCommState). Хотя, вроде, это не должно влиять, т.к. новые настройки Вы не применяете...

А для чего переменная C? По тексту не видно...

По поводу TOverlapped OverWrite. ИМХО, Вам не нужно использовать структуру OVERLAPPED, она для асинхронных операций.

И еще, мне непонятно, зачем Вы копируете из CheckString в OEMString. 
Почему бы не так:
WriteFile(ComPort, CheckString.c_str(), CheckString.Length(), &bytes_written, NULL);  

Автор: sawfish 4.8.2009, 07:03
Да, а где Вы устанавливаете размер буферов приема и передачи (SetupComm)?

Автор: Usper 4.8.2009, 08:13
Откомпилировал приложенный проект, вот что выдалось в порт:

Код

20h ( ), 0Ah (.)
20h ( ), 91h (.), ABh (.), A0h (.), A1h (.), AAh (.), AEh (.), 20h ( ), 85h (.), A2h (.), A3h (.), A5h (.), ADh (.), A8h (.), A9h (.), 20h ( ), 82h (.), ABh (.), A0h (.), A4h (.), A8h (.), ACh (.), A8h (.), E0h (.), AEh (.), A2h (.), A8h (.), E7h (.), 0Ah (.)
20h ( ), FCh (.), 20h ( ), AFh (.), E0h (.), 2Eh (.), 3Ah (:), 20h ( ), 32h (2), 39h (9), 30h (0), 31h (1), 34h (4), 30h (0), 20h ( ), FCh (.), 20h ( ), E2h (.), A0h (.), A1h (.), 2Eh (.), 3Ah (:), 20h ( ), 32h (2), 39h (9), 30h (0), 31h (1), 34h (4), 30h (0), 0Ah (.)
20h ( ), FCh (.), 20h ( ), E6h (.), A5h (.), E5h (.), A0h (.), 3Ah (:), 20h ( ), 32h (2), 39h (9), 20h ( ), FCh (.), 20h ( ), A7h (.), A0h (.), AAh (.), 2Eh (.), 3Ah (:), 20h ( ), 31h (1), 0Ah (.), 20h ( ), FCh (.), 20h ( ), E2h (.), A5h (.), E0h (.), ACh (.), A8h (.), ADh (.), A0h (.), ABh (.), A0h (.), 3Ah (:), 20h ( ), 31h (1), 0Ah (.), 20h ( ), 84h (.), A0h (.), E2h (.), A0h (.), 2Fh (/), A2h (.), E0h (.), A5h (.), ACh (.), EFh (.), 3Ah (:), 20h ( ), E1h (.), A5h (.), A3h (.), AEh (.), A4h (.), ADh (.), EFh (.), 0Ah (.), 20h ( ), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 2Dh (-), 0Ah (.), 20h ( ), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 2Eh (.), 0Ah (.), 20h ( ), 88h (.), 92h (.), 8Eh (.), 83h (.), 8Eh (.), 20h ( ), 3Ah (:), 0Ah (.), 20h ( ), 20h ( ), 0Ah (.), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 91h (.), 8Fh (.), 80h (.), 91h (.), 88h (.), 81h (.), 8Eh (.), 20h ( ), 87h (.), 80h (.), 20h ( ), 8Fh (.), 8Eh (.), 8Ah (.), 93h (.), 8Fh (.), 8Ah (.), 93h (.), 0Ah (.), 20h ( ), 0Ah (.), 20h ( ), 0Ah (.), 20h ( ), 0Ah (.), 20h ( ), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 0Ah (.), 20h ( ), 2Ah (*), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 8Ch (.), 80h (.), 83h (.), 80h (.), 87h (.), 88h (.), 8Dh (.), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 20h ( ), 2Ah (*), 0Ah (.), 20h ( ), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 2Ah (*), 0Ah (.), 1Bh (.), 6Dh (m)

То есть в порт что-то передаётся, осталось только выяснить, чего хочет принтер чтобы начать печать.
З.Ы. однако надо учесть, что данные приниал терминал а не принтер.

Автор: mrbrooks 4.8.2009, 08:31
Jen5on, вполне вероятно что помимо самой информации - девайсу надо отправить какие то системные команды. К нему есть SDK или что то типа этого?

Автор: Jen5on 4.8.2009, 08:49
Спасибо большое человеческое за советы mrbrooks и Usper Обязательно посмотрю какие управляющие символы нужны для отправки на печать. smile 

Автор: Jen5on 24.8.2009, 19:35
Все было так банально smile . Я забыл подключить шлейф ком порта smile  smile  smile  smile .

Вот точно рабочий исходник с exe файлом.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)