C++调用USB小票打印机 第一种办法 无驱动

这种办法是抄于CSDN的,可以无驱动打印,但是有缺点的就是如果电脑连接了多台USB打印机,这种办法不行

 

 //链接打印机
int InitPort(PrintDevice &device)
{
    hPort = CreateFile(device.Port.c_str(), GENERIC_READ | GENERIC_WRITE,
        0, NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL, NULL);

    if (hPort == INVALID_HANDLE_VALUE)
    {   // 打开端口失败
        return false;
    }
    else
    {

        printf("InitPort Hello\r\n");

        //设置端口缓冲
        SetupComm(hPort, 1024, 1024);

        // 设定通讯端口超时参数
        COMMTIMEOUTS tmouts;
        tmouts.ReadIntervalTimeout = 100;
        tmouts.ReadTotalTimeoutMultiplier = 100;
        tmouts.ReadTotalTimeoutConstant = 100;
        tmouts.WriteTotalTimeoutConstant = 100;
        tmouts.WriteTotalTimeoutMultiplier = 100;
        SetCommTimeouts(hPort, &tmouts);

        //设定通讯端口通讯参数
        DCB dcb;
        BOOL bol = TRUE;

        //dcb.DCBlength = sizeof(dcb);
        bol = GetCommState(hPort, &dcb);
        dcb.BaudRate = device.BawdRate;
        dcb.ByteSize = device.DataBits;
        dcb.StopBits = device.StopBits;
        dcb.Parity = device.Parity;

        bol = SetCommState(hPort, &dcb); //配置串口
        // 清除通讯端口缓存
        PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);

        // 初始化重叠IO对象
        OVERLAPPED m_OverlappedRead;
        OVERLAPPED m_OverlappedWrite;
        HANDLE m_hStopCommEvent;
        HANDLE m_hDataReady;
        memset(&m_OverlappedRead, 0, sizeof(OVERLAPPED));
        m_OverlappedRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        memset(&m_OverlappedWrite, 0, sizeof(OVERLAPPED));
        m_OverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

        // 初始化事件对象
        m_hStopCommEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hDataReady = CreateEvent(NULL, FALSE, FALSE, NULL);

        //初始化打印ESC @
        DWORD iBytesLength;
        char chInitCode[] = "\x0D\x1B\x40";
        if (!WriteFile(hPort, chInitCode, (DWORD)3L, &iBytesLength, NULL))
            return false;
    }

    return true;
}

int   WriteData(string meg)
{
    DWORD dwWrite;
    return WriteFile(hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
}

//打印数据,meg打印字符串,bBold=true粗体,nZoom=2大一号字体, nHAil=2居中对齐,nHAil=3右对齐。部分打印机可能中文字体设置无效,请加上FS !命令设置中文字体。
bool OnWriteData(string meg, bool bBold, bool bDTall, bool bDWide, int nHAil)
{
    char s[120] = "";
    memset(s, 0, 120);

    long nMode = 0;
    DWORD iBytesLength;

    if (bBold)
        nMode += 8;

    if (bDTall)
        nMode += 16;

    if (bDWide)
        nMode += 32;

    if (nMode > 0)
    {
        //sprintf(s, "\x1B\x21%c", nMode);
        sprintf_s(s, sizeof(s), "\x1B\x21%c", nMode);
        if (strlen(s) < 3)
        {
            iBytesLength = 0;
            WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);
        }
        else
            WriteData(s);
    }

    switch (nHAil)
    {
    case 1:
        break;
    case 2:
        strcat_s(s, strlen("\x1B\x61\x01") + 1, "\x1B\x61\x01");
        WriteData(s);
        break;
    case 3:
        strcat_s(s, strlen("\x1B\x61\x02") + 1, "\x1B\x61\x02");
        WriteData(s);
        break;
    default:
        break;
    }

    WriteData(meg);

    iBytesLength = 0;
    strcpy_s(s, strlen("\x1B\x21\x00") + 1, "\x1B\x21\x00");
    WriteFile(hPort, s, (DWORD)3L, &iBytesLength, NULL);

    return true;
};


//获取CreateFile的USB端口号


// 根据GUID获得设备路径
// lpGuid: GUID指针
// pszDevicePath: 设备路径指针的指针,用于返回找到的路径
// 返回: 成功得到的设备路径个数,可能不止1个
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
{
    HDEVINFO hDevInfoSet;
    SP_DEVINFO_DATA spDevInfoData;
    SP_DEVICE_INTERFACE_DATA ifData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
    int nCount;
    int nTotle;
    BOOL bResult;

    char* strUSBPrint = "USB 打印支持";

    // 取得一个该GUID相关的设备信息集句柄
    hDevInfoSet = ::SetupDiGetClassDevs(lpGuid,     // class GUID
        NULL,                    // 无关键字
        NULL,                    // 不指定父窗口句柄
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);    // 目前存在的设备

    // 失败...
    if (hDevInfoSet == INVALID_HANDLE_VALUE)
    {
        return 0;
    }

    // 申请设备接口数据空间
    pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);

    pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    nTotle = -1;
    nCount = 0;
    bResult = TRUE;

    // 设备序号=0,1,2... 逐一测试设备接口,到失败为止
    while (bResult)
    {
        nTotle++;
        spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        // 枚举符合该GUID的设备接口
        bResult = ::SetupDiEnumDeviceInfo(
            hDevInfoSet,     // 设备信息集句柄
            (ULONG)nTotle,   // 设备信息集里的设备序号
            &spDevInfoData);        // 设备接口信息

        if (bResult)
        {
            DWORD DataT;
            TCHAR buf[MAX_PATH];
            DWORD nSize = 0;

            // get Friendly Name or Device Description
            if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
                SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
            }
            else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
                SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
            }
            else {
                lstrcpy(buf, _T("Unknown"));
            }

            //是否是要找的设备类型
            if (strcmp(buf, strUSBPrint) != 0)
                continue;

            ifData.cbSize = sizeof(ifData);

            // 枚舉符合該GUID的設備接口
            bResult = ::SetupDiEnumDeviceInterfaces(
                hDevInfoSet,     // 設備信息集句柄
                NULL,            // 不需額外的設備描述
                lpGuid,          // GUID
                (ULONG)nTotle,   // 設備信息集里的設備序號
                &ifData);        // 設備接口信息

            if (bResult)
            {
                // 取得该设备接口的细节(设备路径)
                bResult = SetupDiGetInterfaceDeviceDetail(
                    hDevInfoSet,    // 设备信息集句柄
                    &ifData,        // 设备接口信息
                    pDetail,        // 设备接口细节(设备路径)
                    INTERFACE_DETAIL_SIZE,    // 输出缓冲区大小
                    NULL,           // 不需计算输出缓冲区大小(直接用设定值)
                    NULL);          // 不需额外的设备描述

                if (bResult)
                {
                    // 复制设备路径到输出缓冲区
                    ::strcpy_s(pszDevicePath[nCount], 256, pDetail->DevicePath);
                    // 调整计数值
                    nCount++;
                }
            }
        }
    }

    // 释放设备接口数据空间
    ::GlobalFree(pDetail);

    // 关闭设备信息集句柄
    ::SetupDiDestroyDeviceInfoList(hDevInfoSet);

    return nCount;
}

posted on 2021-01-08 14:54  redmondfans  阅读(940)  评论(0编辑  收藏  举报