windows下 打印机打印操作类 VS2015

#include "stdafx.h"
#include "CPrinter.h"


BOOL CPrinter::GetPrinterDevice(LPTSTR pszPrinterName, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
{
    // if NULL is passed, then assume we are setting app object's
    // devmode and devnames
    if (phDevMode == NULL || phDevNames == NULL)
        return FALSE;

    // Open printer
    HANDLE hPrinter;
    if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
        return FALSE;

    // obtain PRINTER_INFO_2 structure and close printer
    DWORD dwBytesReturned, dwBytesNeeded;
    GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
    PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR,
        dwBytesNeeded);
    if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded,
        &dwBytesReturned) == 0) {
        GlobalFree(p2);
        ClosePrinter(hPrinter);
        return FALSE;
    }
    ClosePrinter(hPrinter);

    // Allocate a global handle for DEVMODE
    HGLOBAL  hDevMode = GlobalAlloc(GHND, sizeof(*p2->pDevMode) +
        p2->pDevMode->dmDriverExtra);
    ASSERT(hDevMode);
    DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);
    ASSERT(pDevMode);

    // copy DEVMODE data from PRINTER_INFO_2::pDevMode
    memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode) +
        p2->pDevMode->dmDriverExtra);
    GlobalUnlock(hDevMode);

    // Compute size of DEVNAMES structure from PRINTER_INFO_2's data
    DWORD drvNameLen = lstrlen(p2->pDriverName) + 1;  // driver name
    DWORD ptrNameLen = lstrlen(p2->pPrinterName) + 1; // printer name
    DWORD porNameLen = lstrlen(p2->pPortName) + 1;    // port name

                                                      // Allocate a global handle big enough to hold DEVNAMES.
    HGLOBAL hDevNames = GlobalAlloc(GHND,
        sizeof(DEVNAMES) +
        (drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR));
    ASSERT(hDevNames);
    DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);
    ASSERT(pDevNames);

    // Copy the DEVNAMES information from PRINTER_INFO_2
    // tcOffset = TCHAR Offset into structure
    int tcOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
    ASSERT(sizeof(DEVNAMES) == tcOffset*sizeof(TCHAR));

    pDevNames->wDriverOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pDriverName,
        drvNameLen*sizeof(TCHAR));
    tcOffset += drvNameLen;

    pDevNames->wDeviceOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPrinterName,
        ptrNameLen*sizeof(TCHAR));
    tcOffset += ptrNameLen;

    pDevNames->wOutputOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPortName,
        porNameLen*sizeof(TCHAR));
    pDevNames->wDefault = 0;

    GlobalUnlock(hDevNames);
    GlobalFree(p2);   // free PRINTER_INFO_2

                      // set the new hDevMode and hDevNames
    *phDevMode = hDevMode;
    *phDevNames = hDevNames;
    return TRUE;
}


/*
    首先打印准备工作,获取到设备的操作句柄

*/

BOOL CPrinter::PrintStr(CString strMessage,BOOL IsCut,int PrnNum )
{
#ifdef DEBUG
    log.Logf("%s","开始打印");
#endif
    TCHAR  cutStr[4] = { 0x1D,0x53 ,0x31 };

    if (!GetPrinterDevice(m_strPrintDevice.GetBuffer(0), &m_hDevNames, &m_hDevMode))
    {
        AfxMessageBox(_T("GetPrinterDevice Called Failed!"));
        return false;
    }
    else
    {
        AfxGetApp()->SelectPrinter(m_hDevMode, m_hDevNames);
    }
    m_strPrintDevice.ReleaseBuffer();
    CPrintDialog printerDlg(FALSE);
    printerDlg.m_pd.hDevMode = m_hDevMode;
    printerDlg.m_pd.hDevNames = m_hDevNames;
 
    CDC dc;
    
    if (printerDlg.CreatePrinterDC() == NULL)
    {
        AfxMessageBox(_T("CreatePrinterDC 失败"));
        return false;
    }
    
    dc.Attach(printerDlg.m_pd.hDC);

    DOCINFO di;                                                                             //下面的内容网上很多,就不解释了  
    di.cbSize = sizeof(DOCINFO);
    di.lpszDocName = _T("有驱打印测试");
    di.lpszDatatype = NULL;
    di.lpszOutput = NULL;
    di.fwType = 0;

    CRect recPrint(0, 0, dc.GetDeviceCaps(LOGPIXELSX), dc.GetDeviceCaps(LOGPIXELSY));
    dc.DPtoLP(&recPrint);
    dc.SetWindowOrg(0, 0);

    CFont newFont;
    //VERIFY(newFont.CreatePointFont(50, _T("宋体"), &dc));
    VERIFY(newFont.CreatePointFont(_ttoi(m_fontsize), m_fontname, &dc));
    CFont* oldFont = dc.SelectObject(&newFont);

    dc.SetTextAlign(TA_TOP | TA_LEFT);

    CString strPrint;
    int nIndex = 0;
    int x = 0;
    int y = 50;
    CSize textSize;
    textSize = dc.GetTextExtent(_T("00"), 2);

    dc.StartDocW(&di);
    dc.StartPage();
    dc.SetMapMode(MM_TEXT);
    
       //根据当前字体的宽、高,后面以此高度为行高  
    
        while (((nIndex = strMessage.Find(_T("
"))) > -1))                  //将IDC_EDIT1编辑框中内容打印,支持换行,一次换行等于'
',所以在开头strMessage += _T("
")  
        {
            strPrint = strMessage.Left(nIndex);
            strMessage = strMessage.Mid(nIndex + 2);

            dc.TextOutW(x, y, strPrint);

            y += textSize.cy;                                               //下移一行,行高为字体高度  
        }
        if (m_cut==L"1")
        {
            y += 20;
            dc.TextOutW(x, y, cutStr);
        }
        else
        {
            y += 20;
            dc.TextOutW(x,y,_T(""));
        }

    

    dc.SelectObject(oldFont);
    newFont.DeleteObject();
    dc.EndPage();
    dc.EndDoc();

    DeleteDC(dc.Detach());

    return true;
}
原文地址:https://www.cnblogs.com/lobsterIT/p/5654414.html