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("\n"))) > -1))                  //将IDC_EDIT1编辑框中内容打印,支持换行,一次换行等于‘\r\n‘,所以在开头strMessage += _T("\r\n")
        {
            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;
}
时间: 2024-10-11 05:53:26

windows下 打印机打印操作类 VS2015的相关文章

Windows下磁盘分配操作

问题概述:在装系统的时候有时候并不能一下分出完全符合我们使用习惯的分区大小,我们可能需要在后期调整分区大小.以下是有关分区大小调整的操作. 使用工具:Windows磁盘管理工具. 操作步骤: 1.使用组合键win+x,弹出菜单,选中"计算机管理",选择"磁盘管理". 2.这里简要说明一下Windows的分区规则:只有分区相邻右边的可用分区才能被扩展,如上图,可用空间可以被D盘扩展,但是无法被C盘和E盘扩展.网上有人说可以先将D盘先压缩部分空间,然后就可以制作出可用空

Windows下的DOM操作

前言:这学期学Linux之后,发现用命令行的方式来操作电脑还是很好玩的~写这篇随笔来总结下Windows环境下通过DOS来执行命令的操作,希望能帮到您~自己忘记的时候能回来复习emmm 启动DOS环境: 1.快捷键启动:win键+R 在窗口输入cmd回车 2.如果想在某个目录下启动DOS环境,首先进入该目录,然后再搜索框输入cmd,回车. 例如,我想在C:\Users下启动DOS环境 五个命令: 想完成电脑的基本操作,需要了解5个命令(目录创建,目录切换,查看当前目录下文件/文件夹列表,打开指定

Windows下启动和操作MongoDB(CLI)

1.启动mongoDB服务器 找到安装目录bin文件夹下执行下面的命令 # 默认路径(安装路径\data\db),默认端口(27017) mongod.exe # 如果需要改变数据库路径和端口则改为 mongod.exe --dbpath D:\mongodb\data --port 10086 # 修改了启动端口,连接的时候也要指明端口 mongo.exe --port 10086 # 连接从10086端口启动的mongoDB数据库 2.操作数据库 查看所有的数据库 show dbs 查看当前

windows下使用selenium操作浏览器问题记录

问题 :执行程序代码报错: WebDriverException:Message:'geckodriver'executable needs to be in Path 或者 selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH. 解决,geckodriver是一原生态的第三方浏览器,对于selenium3.x版本都会使用geckodriver来驱动

Winform下的数据库操作类

基本和web区别不大,就是连接字符串改改. web的配置文件叫web.config.而Winform的则是app.config <appSettings> <add key="connectionstring" value="server=192.168.0.119;uid=sa;pwd=sa;database=ZhanBan"/> </appSettings> using System; using System.Collect

Http下的各种操作类

1.WebApi系列~通过HttpClient来调用Web Api接口 http://www.cnblogs.com/lori/p/4045413.html 2.C#通过WebClient,HttpWebRequest实现http的post和get方法 来自baidu 文档:http://wenku.baidu.com/link?url=nr7p0kmFbQ_z6pJkzlaRDjPMYT2MwyFizs03DdW1fv8UwXNrWmK_CyOWkojgmtz6SnaXANUx1FTc7-4G

windows下安装python +eclipse pydev 插件

目录: 一. Python简介 二. 安装python 1. 在windows下安装 2. 在Linux下安装 三. 在windows下配置python集成开发环境(IDE) 1. 在Eclipse中安装PyDev插件 2. 配置Python Interpreters 四. 创建Python Project 五. 编写HelloWorld 六. 小结 一. Python简介: Python在Linux.windows.Mac os等操作系统下都有相应的版本,不管在什么操作系统下,它都能够正常工作

windows下python3 使用cx_Oracle,xlrd插件进行excel数据清洗录入

我们在做数据分析,清洗的过程中,很多时候会面对各种各样的数据源,要针对不同的数据源进行清洗,入库的工作.当然python这个语言,我比较喜欢,开发效率高,基本上怎么写都能运行,而且安装配置简单,基本上有网的环境pip install全部都搞定,没网的话,把whl包copy过来一行命令也就解决了(windows下python3.5使用pip离线安装whl包). 本篇博客就针对,在windows平台下使用python3(python2社区将要停止支持,使用3是大势所趋),读取xls,xlsx格式的数

在linux和windows下自动备份数据库

摘要: 详细介绍在windows和linux下自动备份数据库的过程,希望可以让新手立即上手吧! 本文档内容共分为2大部分:linux和windows Linux和windows都分为:准备工作和操作阶段. Linux的详细步骤为:1.准备文件. 2.连接linux 3.实际操作也就是写命令 windows的详细步骤为:1.准备文件. 2.编辑任务和计划程序. 所用软件:notepad++,ssh 一.linux 1.准备工作(可以在windows下执行本操作) 创建三个文件 1.1文件名:exp