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. 51nod 1021 石子归并 区间DP

    1021 石子归并  基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  取消关注 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆 ...

  2. BZOJ2819: Nim 树链剖分

    Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游 ...

  3. 启动Sql server的服务CMD命令

    启动:net start mssqlserver 停止:net stop mssqlserver

  4. v-bind绑定属性样式

    一.class的四种绑定方式 1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{'class-a':isA ...

  5. java对象在内存的大小

    前言 一直以来,对java对象大小的概念停留在基础数据类型,比如byte占1字节,int占4字节,long占8字节等,但是一个对象包含的内存空间肯定不只有这些. 假设有类A和B,当new A()或者n ...

  6. stm32 ADC使用方法

    void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_AP ...

  7. #网页中动态嵌入PDF文件/在线预览PDF内容#

    摘要:在web开发时我们有时会需要在线预览PDF内容,在线嵌入pdf文件: 问题1:如何网页中嵌入PDF: 在网页中: 常用的几种PDF预览代码片段如下: 代码片段1: 1 <object ty ...

  8. 【异常记录(11)】 Web应用程序项目 已配置为使用 IIS。无法访问 元数据库。您没有足够的特权访问计算机上的 IIS 网站

    解决办法: 1.项目上右键, 编辑 xxxx.csproj 2.找到  <UseIIS> 标签, 改为 <UseIIS>False</UseIIS> 3.右键,重新 ...

  9. GATK--使用转载

    http://blog.sciencenet.cn/blog-1469385-819498.html 文章目录 一.准备工作 二.流程概览 三.流程 首先说说GATK可以做什么.它主要用于从seque ...

  10. shell 去掉字符串的单引号

    echo \'deded\' | sed $'s/\'//g'