http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105790245b09c0252bd7a74a2485d315d2390f07506694ea7a7d0d5d83d87f6305ac4957f7b86c65377571eb8f8dd50a8bb485582a9f5631671df65663d50edcba5154cb37e12efeae69f0caf625e7aec5a5de4320c944040a9780fb4d7467&p=c4759a46d7c002fb09be9b7c5b5390&newp=b471c54ad5c242fe19f3cb2d02148c231610db2151ddd4122e958d17&user=baidu&fm=sc&query=%B7%C7%C4%AC%C8%CF%B4%F2%D3%A1%BB%FA&qid=f3d87aaa0004b57b&p1=2

文章编号: 166129 - 查看本文应用于的产品

: Microsoft Visual c + +.net (2002) 支持这两个托管的代码模型所提供的.net 框架和非托管本机 Windows 代码模型。本文中信息的部分或全部适用于托管的 Visual c + + 代码,可能只能通过使用.net 框架应用。
展开全部 | 关闭全部

本文内容

概要

在 开发 MFC 应用程序,它有时是用于以编程方式打印到网络打印机或 $ 辅助打印机的非默认打印机的 (不带打印对话框)。若要执行此操作需要 DEVMODE 和 DEVNAMES 结构。这篇文章显示了一个可以设置最多使用 GetPrinter() 调用这些数据结构的方式,并提供有关如何使用它们的示例。

: 在这篇文章中的某些代码不能应用于 Windows 95 和 Windows 98 由于 GetPrinter 可能不适用于网络打印机。

更多信息

在 MFC 应用程序的正常打印操作,过程中打印对话框将显示该对话框可选择要打印到的打印机。在打印对话框中显示的默认打印机是在操作系统中指定的默认打印机。 MFC 将存储在默认打印机 CWinApp::m_hDevMode 和 CWinApp::m_hDevNames 中应用程序的受保护的数据成员。因为 MFC 将初始化为 NULL 这些变量,MFC 的打印体系结构默认操作系统的默认打印机第一次执行时打印操作。操作系统默认打印机的 DEVMODE 和 DEVNAMES 然后复制到在 MFC 应用程序的 m_hDevMode 和 m_hDevNames 数据成员。

有时,可能会在需要打印到默认打印机以外的其他打印机,而无需用户通过打印对话框中指定它的情况。辅助打印机或 $ 网络打印机 (假定您的操作系统都已经安装了驱动程序),可以使用非默认打印机

无 论您需要使用非默认打印机在永久的基础上或只有一个打印作业,您将需要 DEVMODE 和 DEVNAMES 结构创建 DC 上的打印机。从 GetPrinter() PRINTER_INFO_2 结构包含填充 DEVMODE 和 DEVNAMES 结构所需的全部信息。

创建一个 DEVMODE 和 DEVNAMES 结构

下面的代码示例演示如何使用 GetPrinter() 创建 DEVMODE 和 DEVNAMES 结构基于打印机名称。该代码是全局函数的返回数据结构,通过它的参数。

#include <winspool.h>

// returns a DEVMODE and DEVNAMES for the printer name specified
BOOL 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;
}

作为了快速参考下面是 DEVNAMES 的声明与每个字段的简短说明:

// commdlg.h
// the first three members are character offsets from the beginning of the // structure pointing to the specific string
typedef struct tagDEVNAMES {
WORD wDriverOffset; // file name of driver (without extension)
WORD wDeviceOffset; // device name
WORD wOutputOffset; // device name of physical output medium
WORD wDefault; // DN_DEFAULTPRN if default printer chosen
} DEVNAMES;

设置应用程序的默认打印机

若要设置默认打印机,您需要设置 m_hDevNames 和 m_hDevMode 数据成员 (它受保护) 该 CWinApp 的成员函数通过该应用程序的派生对象,GetPrinterDevice()。您可以实现下面的函数,并调用它时您需要更改默认打印机。

void CMainFrame::OnActionSetnondefaultprinter()
{
HGLOBAL hDevMode = NULL;
HGLOBAL hDevNames = NULL;
if (GetPrinterDevice(_T("\\\\RED-PRN-25\\PRIV0006"), &hDevNames, &hDevMode))
AfxGetApp()->SelectPrinter(hDevNames, hDevMode);
else
AfxMessageBox(_T("Failed to select custom printer"));
}

绕过打印对话框时使用应用程序的默认打印机

若要绕过打印对话框,OnPreparePrinting 需要被重写,以便可以将 m_bDirect 标志设置为 TRUE。然后调用 DoPreparePrinting,以设置-> m_pd.hDevMode m_pPD pInfo 的值和 pInfo-> m_pPD-> m_pd.hDevNames 到相应的应用程序对象的数据成员和创建 DC 上的打印机。

BOOL CNonDefPrinterView::OnPreparePrinting(CPrintInfo* pInfo)
{
pInfo->m_bDirect = TRUE; // TRUE if bypassing Print Dialog
return DoPreparePrinting(pInfo);
}

绕过打印对话框时使用非默认打印机

要跳过打印对话框,并使用非默认打印机,您需要-> m_pd m_pPD pInfo 数据成员自己设置和创建 DC 上的打印机。以下是将实现此目的的代码:

BOOL CNonDefPrinterView::OnPreparePrinting(CPrintInfo* pInfo)
{
// set to non-default printer without changing default app printer
HGLOBAL hDevMode;
HGLOBAL hDevNames; if (!GetPrinterDevice(_T("\\\\RED-PRN-25\\PRIV0006"), &hDevNames, &hDevMode))
AfxMessageBox(_T("GetPrinterDevice called failed\n")); pInfo->m_pPD->m_pd.hDevMode = hDevMode;
pInfo->m_pPD->m_pd.hDevNames = hDevNames;
pInfo->m_pPD->CreatePrinterDC(); return TRUE;
}

本示例显示了使用 GetPrinterDevice 函数。有关更多详细信息,请参见上面。

如何以编程方式打印到在 MFC 中的非默认打印机的更多相关文章

  1. 【VC++技术杂谈002】打印技术之获取及设置系统默认打印机

    本文主要介绍如何获取以及设置系统的默认打印机. 1.获取系统中的所有打印机 获取系统中的所有打印机可以使用EnumPrinters()函数,该函数可以枚举全部的本地.网络打印机信息.其函数原型为: B ...

  2. SpringMVC(十六):如何使用编程方式替代/WEB-INF/web.xml中的配置信息

    在构建springmvc+mybatis项目时,更常用的方式是采用web.xml来配置,而且一般情况下会在web.xml中使用ContextLoaderListener加载applicationCon ...

  3. 如何在MFC中创建非矩形button

    一般情况下,我们创建的按钮都是矩形的,但有时为了满足特殊的需求,我们要在对话框中创建一个非矩形的按钮,比如,圆形,椭圆等. 要实现一个非矩形的按钮,这就涉及到了自绘控件.自绘控件的方法有很多,可以参考 ...

  4. EF三种编程方式的区别Database first ,Model first ,code first

    首先对于EF中先出现的datebase  first和model first两种编程方式,其的区别根据字面意思很容易能够理解. datebase  first就是代表数据库优先,那么前提就是先创建数据 ...

  5. C#+EntityFramework编程方式详细之Code First 数据迁移

    在前几篇的C#+EntityFramework编程方式中介绍了C#+EntityFramework编程方式Code First ,Model First以及Dtatabase First 等编程方式, ...

  6. 多线程编程之二 ---MFC中的多线程开发

    下载源代码 五.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消 ...

  7. MFC模态和非模态对话框编程

    MFC中对话框有两种形式,一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box). 一.模态对话框(model dialog box) 在程 ...

  8. 解决在编程方式下无法访问Spark Master问题

    我们可以选择使用spark-shell,spark-submit或者编写代码的方式运行Spark.在产品环境下,利用spark-submit将jar提交到spark,是较为常见的做法.但是在开发期间, ...

  9. 38、数据源Parquet之使用编程方式加载数据

    一.概述 Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目,最新的版本是1.8.0. 列式存 ...

随机推荐

  1. Sql Server 创建表添加说明

    http://bbs.csdn.net/topics/340184487 在此感谢 提供参考 CREATE TABLE ToPayFee (    Id INT IDENTITY(1,1) PRIMA ...

  2. MVC ---- T4(1)

    T4 模板编辑插件:tangibleT4EditorPlusModellingToolsVS2012.msi 下载地址:http://t4-editor.tangible-engineering.co ...

  3. Android广播接收器和Activity间传递数据

    Activity向广播接收器传递数据很简单,只需要在发送广播前将数据put进Intent中就行了. 广播接收器怎么向Activity传送数据?这里要用到接口,通过在广播接收器里定义一个接口,然后让接收 ...

  4. Linux——进程管理简单学习笔记(二)

    计划任务: 为什么要设置计划任务 : 实现数据库备份,发送系统通知神马的..... 计划任务的命令: 一: at :  安排作业在某一时刻执行一次 nbatch    安排作业在系统负载不重时执 行一 ...

  5. pandas 设置单元格的值

    import pandas as pd import pickle import numpy as np dates = pd.date_range() df = pd.DataFrame(np.ar ...

  6. Jmeter自动化测试 数据驱动测试,将数据存入csv文件中来调用,或将数据存在DB中进行调用

    1. 将测试的用例名称,测试请求方式,测试链接,预置数据,断言等都放到excel中,然后转成csv格式,在用Jmeter带的csv数据配置文件导入 运行之前将线程组中配置,线程数设置为1,循环的次数设 ...

  7. 常见dos命令汇总

    常用的内部命令有md.cd.rd.dir.path.copy.type.edit.ren.del.cls.ver.date.time.prompt.常用的外部命令有deltree.format.dis ...

  8. UTC和GMT时间辨析

    一.UTC和GMT 每个地区都有自己的本地时间,在网上以及无线电通信中时间转换的问题就显得格外突出. 整个地球分为二十四时区,每个时区都有自己的本地时间.在国际无线电通信场合,为了统一起见,使用一个统 ...

  9. Qt5.3.2_CentOS6.4(x86)_代码文件编码

    1.1.1.Qt5.3.2_MinGW 在Windows中安装时,默认的文件编码是 UTF8. 1.2.在 CentOS6.4中安装 qt-opensource-linux-x86-5.3.2.run ...

  10. mac 下安装mongodb

    转载自https://segmentfault.com/a/1190000002547229 概念 MongoDB 是一个跨平台的,面向文档的数据库,提供高性能,高可用性和可扩展性方便. MongoD ...