通过CreateDC得到打印机DC,怎么如何设置打印机共享的DPI

您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
VC 从excl读取数据打印到固定位置.doc 7页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:90 &&
VC 从excl读取数据打印到固定位置
你可能关注的文档:
··········
··········
广丰鄂摘要:程序利用微软提供的excel操作的库函数读入数据,再调用MFC中的CDC类进行固定位置打印。内容:程序主要分两步:第一步从excel读取数据。第二步把excel读入的数据打印到纸张的固定位置。从excel读取数据一:准备工作开始新建基于对话框的工程,记得在第四个向导中选择作为静态链接库导入。新建好之后导入excel操作库函数,依次选择View-&ClassWizard-&AddNewClass-&Fromatypelibrary。在弹出的对话框中选择装excel的安装目录,选择excel.exe,然后添加类,主要类型有_Applicaiton,Workbooks,_Workbook,Worksheets,_Wordsheet,Range类,其他类型可根据需要自己添加。Excel接口类中层次如下所示: -_Application -Workbooks工作薄集合 -_Workbook工作薄 -Worksheets工作表集合 -_Worksheet工作表 -Range单元格区域(在程序中可能还会使用到word类库,导入步骤一样,添加的类有_Application,Documents,_Document,Selection,因为word中的类可能与excel中的类名有冲突,可以在冲突的类中添加命名空间,在头文件和源文件中重复的类都包含到一个命名空间,这样就可以有效解决导入两个不同库而出现的类同名的问题)导入excel库后,可以先看下导入的类提供的函数有哪些,一般可以根据其名字判断该函数的作用,如果不清楚你要做的步骤应该包含哪些函数,可以试下excel中提供的宏:先打开excel应用程序,点击工具-&宏-&录制宏,开始录制。进行你想要的操作,比如多打开工作博,或者添加工作簿,或者其他操作,操作结束后,点击结束宏。查看录制的宏,点击工具-&宏-&宏。。。查看宏,本操作是一个已存在的文件,得到的宏如图1所示:图1打开存在文件的宏分析宏,发现打开文件是在Wordbooks类的操作,使用的是Workbooks中的Open函数,然后可以查看导入的库中的Workbooks下的Open函数,选择正确的参数,即可执行打开文件操作。Workbooks下的Open函数原型如下:PDISPATCHWorkbooks::Open(LPCTSTRFilename,constVARIANT&UpdateLinks,constVARIANT&ReadOnly,constVARIANT&Format,constVARIANT&Password,constVARIANT&WriteResPassword,constVARIANT&IgnoreReadOnlyRecommended,constVARIANT&Origin,constVARIANT&Delimiter,constVARIANT&Editable,constVARIANT&Notify,constVARIANT&Converter,constVARIANT&AddToMru,constVARIANT&Local,constVARIANT&CorruptLoad);会发现类中函数的参数几乎都是VARIANT类型的参数,Variant是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant也可以包含Empty、Error、Nothing及Null等特殊值。可以用VarType函数或TypeName函数来决定如何处理Variant中的数据。“excel.h”和#include“atlbase.h”,要在文件中使用excel库函数,首先必须在此文件包含excel的头文件,atlbase是为了操作简单。在功成名+App结尾的源文件中的InitInstance中加入如下代码:if(!AfxOleInit()){ AfxMessageBox(&初始化Ole失败!&); returnFALSE;}在想要执行excel操作的程序函数或消息响应代码中添加对excel的代码。首先定义类的对象:spaceExcel::_ApplicationexcelA WorkbooksexcelWorkB _WorkbookexcelWorkB WorksheetsexcelWorkS _WorksheetexcelWorkS RangeexcelRange,usedR在_Application类中添加了一个命名空间并把此类包含在命名空间中。B.打开excel应
正在加载中,请稍后...C++(116)
CPrintDialog(2)
前段时间需要将日志信息通过打印机打印出来。
总结了一下其中的一些用法:
1:用CPrintDialog 可以呼出窗口让用户选择打印机或者采用默认的打印机直接打印。
& & StartPage…..EndPage &完成一页文档的打印。 &如需改变DC设置,需要调用ReSetDC()
& & 多次调用这两个函数,可以实现打印多页
2:TextOut坐标的确定。
& & &TextOut中的坐标是DC中的逻辑坐标。
& & &和实际的物理坐标需要转换。
& & GetDeviceCpas(); &//获取DC中的Device信息。
& & GetTextMetrics(); //获取字体的信息。 字体高度和本身高度+行距。
3:TextOut中的字体可以设置。
& & 关键代码如下:
& & &CFont myF
& & &myFont.CreatePontFont(….);
& & &oldFont = dc.SelectObject();
& & &myFont.DelectObject()';
1:转载相关文档:
打印单位的转换
这个的关键是我们要得到显示设备的DPI,即每英寸设备支持的点数。有了DPI我们就可以在我们习惯的单位和设备单位之间转换了,用到的API是GetDeviceCaps(),这个函数功能强大,具体可参考MSDN,在这里我们只用来得到设备DPI。看示例代码:
[cpp] view plaincopy
//某些设备水平和垂直方向的DPI可能不同,所以要分别得到。 &
& &//得到水平方向的转换比例 &
& &float getXScale(HDC printDC) &//printDC: 打印机DC设备句柄 &
& & & &//得到打印机水平方向的DPI &
& & & &int xDPI = GetDeviceCaps(printDC, LOGPIXELSX); &
& & & &//254.0: 每英寸25.4毫米 &
& & & &float xScale = (float)(254.0 / xDPI); &
& & & &return xS &
& &//得到垂直方向的转换比例 &
& &float getYScale(HDC printDC) &//printDC: 打印机DC设备句柄 &
& & & &//得到打印机垂直方向的DPI &
& & & &int yDPI = GetDeviceCaps(printDC, LOGPIXELSY); &
& & & &float yScale = (float)(254.0 / yDPI); &
& & & &return yS &
& &//厘米转换为设备像素,水平方向 &
& &double cm2Unit_W(float xScale, double w) //w单位为厘米 &
& & & &return w*100/xS &
& &//厘米转换为设备像素,垂直方向 &
& &double cm2Unit_H(float yScale, double h) //h单位为厘米 &
& & & &return h*100/yS &
上面代码中,如果将printDC换为显示器设备DC句柄,即可得到厘米转换为显示器像素单位,打印预览时使用。得到显示器设备句柄可用::GetDC(NULL)得到。
打印基本流程
有了前面的知识,现在我们就可以打印了。Windows打印是有着固定的流程的,流程也比较简单。按照固定的顺序调用打印API即可:StartDoc() -& StartPage() -& 打印具体内容 -& EndPage() -& EndDoc()。如果要打印多页,循环StartPage()至EndPage()即可。
示例代码:
[cpp] view plaincopy
DOCINFO & & &&
& &ZeroMemory(&doc,sizeof(doc)); & &&
& &doc.cbSize = sizeof(doc); & &&
& &doc.lpszDocName = (LPCTSTR)&Print Test File&; &
& &StartDoc(printDC, &doc); &//准备打印 &
& &StartPage(printDC); &//开始打印页 &
& &//在(2.5cm, 2.5cm)处打印文本 &
& &char* text = &打印测试文本&; &
& &float xScale = getXScale(printDC); &
& &float yScale = getYScale(printDC); &
& &double x = cm2Unit_W(xScale, 2.5); &
& &double y = cm2Unit_H(yScale, 2.5); &
& &//在指定位置打印文本 &
& &TextOut(printDC, (int)x, (int)y, (LPTSTR)text, strlen(text)); &
& &EndPage(printDC); &//结束打印页 &
& &EndDoc(printDC); &//结束打印 &
打印字体的设置
很多时候我们希望能控制打印字体,下面的代码可以创建你想要的字体格式:
[cpp] view plaincopy
/* &创建自定义打印字体&
& & & &fontFace:字体名称,如果为NULL,默认采用“宋体”&
& & & &fontHeight:字体高度,单位为厘米&
& & & &isBold:是否加粗&
& & & &isItalic:是否斜体&
& & & &isUnderLine:是否下划线&
& & & &isStrikeOut:是否删除线&
& &HFONT getFont(LPCTSTR fontFace, double fontHeight, bool isBold, bool isItalic, bool isUnderLine, bool isStrikeOut) &
& & & &int width = 0; //字体宽度由系统决定 &
& & & &int weight = FW_NORMAL; &
& & & &DWORD italic = 0; &
& & & &DWORD underLine = 0; &
& & & &DWORD strikeOut = 0; &
& & & &DWORD charSet = DEFAULT_CHARSET; &
& & & &LPCTSTR face = (LPCTSTR)&宋体&; &
& & & &float height = cm2Unit_H(fontHeight); &
& & & &if(fontFace != 0) &
& & & &{ &
& & & & & &face = fontF &
& & & &} &
& & & &if(isBold) &
& & & &{ &
& & & & & &weight = FW_BOLD; &
& & & &} &
& & & &if(isItalic) &
& & & &{ &
& & & & & &italic = 1; &
& & & &} &
& & & &if(isUnderLine) &
& & & &{ &
& & & & & &underLine = 1; &
& & & &} &
& & & &if(isStrikeOut) &
& & & &{ &
& & & & & &strikeOut = 1; &
& & & &} &
& & & &HFONT font = CreateFont((int)height, width, 0, 0, &&
& & & & & & & & & & & & & & & & weight, italic, underLine, strikeOut, charSet, &
& & & & & & & & & & & & & & & & OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, &&
& & & & & & & & & & & & & & & & DEFAULT_PITCH | FF_DONTCARE, face ); &
以上就是我们在实现打印中遇到的常见问题,相信理解了这些,在我们自己的程序中实现打印就不再是什么困难的事情了。
/zh-cn/library/cc485711(VS.71).aspx#_core_printer_pages_vs.._document_pages
为打印多页文档,框架与视图以如下方式交互。首先,框架显示“打印”对话框,为打印机创建设备上下文,并调用
成员函数。然后,对于文档中的每一页,框架调用 CDC 对象的
成员函数,指示视图对象打印页,并调用
成员函数。如果在开始某个特定页之前必须更改打印机模式,视图将调用
,它将更新含有新的打印机模式信息的 DEVMODE 结构。全部文档打印完毕后,框架调用
成员函数。
重写视图类函数
类定义在打印过程中被框架调用的几个成员函数。通过在视图类中重写这些函数,提供框架打印逻辑与视图类打印逻辑之间的连接。下表列出了这些成员函数。
用于打印的 CView 可重写函数
OnPreparePrinting
在“打印”对话框中插入值,尤其是文档的长度
OnBeginPrinting
分配字体或其他 GDI 资源
OnPrepareDC
调整给定页的设备上下文属性,或进行打印时分页
打印给定页
OnEndPrinting
解除分配 GDI 资源
也可用其他函数执行打印相关处理,但这些函数是驱动打印过程的函数。
下图阐释了打印过程所涉及的步骤,并显示了在何处调用 CView 的每个打印成员函数。本文其余部分是对大多数步骤更详细的解释。分配 GDI 资源一文介绍了打印过程的其他部分。
CPrintInfo
结构中存储许多关于打印作业的信息。CPrintInfo 中的几个值是关于分页的;这些值如下表所示。
存储在 CPrintInfo 中的页码信息
成员变量或函数名
引用的页码
GetMinPage/SetMinPage
文档的第一页
GetMaxPage/SetMaxPage
文档的最后一页
GetFromPage
要打印的第一页
要打印的最后一页
m_nCurPage
当前正在打印的页
页码从 1 开始,也就是说,第一页的编号为 1,而不是 0。有关上述及其他
CPrintInfo
成员的更多信息,请参见“MFC 参考”。
在打印过程的开始,框架调用视图的
OnPreparePrinting
成员函数,向 CPrintInfo 结构传递一个指针。“应用程序向导”提供调用 CView 的另一个成员函数
DoPreparePrinting
的 OnPreparePrinting 实现。DoPreparePrinting 是显示“打印”对话框并创建打印机设备上下文的函数。
这时,应用程序并不知道文档的页数。它对文档的第一页和最后一页的页码使用默认值 1 和 0xFFFF。如果您知道文档的页数,在将文档发送到DoPreparePrinting 之前,请重写 OnPreparePrinting,并为 CPrintInfo 结构调用
SetMaxPage
。这使您得以指定文档的长度。
接下来 DoPreparePrinting 显示“打印”对话框。当它返回时,CPrintInfo 结构包含用户指定的值。如果用户希望只打印选定页码范围内的文档,他或她可以在“打印”对话框中指定起始页码和终止页码。框架使用
CPrintInfo
的 GetFromPage 和 GetToPage 函数检索这些值。如果用户未指定页码范围,框架将调用 GetMinPage 和 GetMaxPage 并使用返回的值来打印整个文档。
对于文档中将要打印的每一页,框架调用视图类中的两个成员函数(
OnPrepareDC
),并传递给每个函数两个参数:一个指向
对象的指针和一个指向 CPrintInfo 结构的指针。每次当框架调用 OnPrepareDC 和 OnPrint 时,它都传递 CPrintInfo 结构的m_nCurPage 成员中的不同值。框架通过这种方式通知视图要打印哪些页。
OnPrepareDC
成员函数也可用于屏幕显示。它在绘制之前调整设备上下文。OnPrepareDC 在打印中起同样的作用,但有两点不同:首先,CDC 对象表示打印机设备上下文而不是屏幕设备上下文;其次,CPrintInfo 对象作为第二个参数传递。(当为屏幕显示调用 OnPrepareDC 时,此参数为 NULL。)重写 OnPrepareDC 以便根据正在打印的页的不同来调整设备上下文。例如,可通过移动视区原点和剪辑区域,确保文档中的适当部分得到打印。
成员函数执行页的实际打印。默认打印的实现方式一文显示了框架是如何用打印机设备上下文调用
来执行打印的。更确切地说,框架用 CPrintInfo 结构和设备上下文调用 OnPrint,OnPrint 将设备上下文传递给 OnDraw。重写 OnPrint,执行任何只应在打印而非屏幕显示期间完成的呈现。例如,打印页眉或页脚(有关更多信息,请参见页眉和页脚一文)。然后,从 OnPrint 的重写调用 OnDraw 来进行屏幕显示和打印的共同呈现。
OnDraw 既进行屏幕显示呈现又进行打印呈现的事实意味着您的应用程序是 WYSIWYG(所见即所得)。然而,假设您正在写的不是“所见即所得”应用程序。例如,一个文本编辑器使用粗体作为打印字体,但同时显示控制代码指示屏幕上粗体文本。对于这种情况,应严格使用 OnDraw 进行屏幕显示。当您重写 OnPrint 时,用一个对单独绘制函数的调用取代对 OnDraw 的调用。该函数使用未显示在屏幕上的属性,以文档显示在纸上的方式绘制文档。
打印机页与文档页
提到页码,有时必须得区分打印机页的概念和文档页的概念。从打印机的角度讲,一页是一张纸。但是,一张纸并不一定等于文档中的一页。例如,如果打印一份通讯稿,纸张将要折叠,一张纸可能同时含有文档的第一页和最后一页(它们是并排的)。同样,如果打印一份电子表格,文档根本不是由页组成的。相反,一张纸可能包含第一到第二十行,第六到第十列。
CPrintInfo
结构中的页码都是指打印机页。框架对通过打印机的每一页纸调用一次 OnPrepareDC 和 OnPrint。当重写
OnPreparePrinting
函数来指定文档长度时,必须使用打印机页。如果存在一一对应关系(即,一个打印机页等于一个文档页),那么事情就简单了。反之,如果文档页与打印机页并非一一对应,则必须在两者之间进行转换。例如,打印一份电子表格。当重写 OnPreparePrinting 时,必须计算打印整个电子表格所需的纸张数,并在调用 CPrintInfo 的 SetMaxPage 成员函数时使用该值。同样,当重写 OnPrepareDC 时,必须将 m_nCurPage 转换成会出现在特定纸张上的行和列的范围,然后相应调整视区原点。
打印时分页
有些情况下,您的视图类可能在文档实际打印之前并不会事先知道文档的长度。例如,如果您的应用程序不是“所见即所得”的,那么屏幕上的文档长度并不对应于其打印时的长度。
当您为视图类重写
OnPreparePrinting
时,就会产生这样的问题:无法向
CPrintInfo
结构的 SetMaxPage 函数传递值,因为您不知道文档的长度。如果用户不使用“打印”对话框指定终止页码,框架就不知该在何时停止打印循环。唯一可以确定何时停止打印循环的方法是打印出全部文档并弄清其何时终止。您的视图类必须在文档打印期间检查是否到达文档末尾,并在到达时通知框架。
框架依赖于您的视图类的
OnPrepareDC
函数来告知何时停止。在每次调用 OnPrepareDC 之后,框架检查 CPrintInfo 结构的一个名为 m_bContinuePrinting 的成员。该成员的默认值为 TRUE。只要它保持此默认值,框架就继续打印循环。如果它设置为 FALSE,框架就停止。若要执行打印时分页,请重写 OnPrepareDC 以检查是否已到达文档末尾,如果已经到达,则将 m_bContinuePrinting 设置为 FALSE。
如果当前页大于 1,OnPrepareDC 的默认实现将把 m_bContinuePrinting 设置为 FALSE。这意味着如果未指定文档长度,框架将假设文档的长度为一页。这样做的结果之一就是在调用 OnPrepareDC 的基类版本时必须谨慎。不要假定 m_bContinuePrinting 在调用基类版本之后将为TRUE。
2:MSDN上的一段示例代码:
[cpp] view plaincopy
// get the default printer &
CPrintDialog dlg(FALSE); &
dlg.GetDefaults(); &
// is a default printer set up? &
HDC hdcPrinter = dlg.GetPrinterDC(); &
if (hdcPrinter == NULL) &
& &MessageBox(_T(&Buy a printer!&)); &
& &// create a CDC and attach it to the default printer &
& &CDC dcP &
& &dcPrinter.Attach(hdcPrinter); &
& &// call StartDoc() to begin printing &
& &DOCINFO &
& &memset(&docinfo, 0, sizeof(docinfo)); &
& &docinfo.cbSize = sizeof(docinfo); &
& &docinfo.lpszDocName = _T(&CDC::StartDoc() Code Fragment&); &
& &// if it fails, complain and exit gracefully &
& &if (dcPrinter.StartDoc(&docinfo) & 0) &
& & & MessageBox(_T(&Printer wouldn't initalize&)); &
& & & // start a page &
& & & if (dcPrinter.StartPage() & 0) &
& & & & &MessageBox(_T(&Could not start page&)); &
& & & & &dcPrinter.AbortDoc(); &
& & & else &
& & & & &// actually do some printing &
& & & & &CGdiObject* pOldFont = dcPrinter.SelectStockObject(SYSTEM_FONT); &
& & & & &dcPrinter.TextOut(50, 50, _T(&Hello World!&), 12); &
& & & & &dcPrinter.EndPage(); &
& & & & &dcPrinter.EndDoc(); &
& & & & &dcPrinter.SelectObject(pOldFont); &
转自:/CataNews/60/info8939.html
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:201938次
积分:3023
积分:3023
排名:第11365名
原创:68篇
转载:242篇
(1)(3)(2)(1)(1)(1)(1)(1)(11)(5)(1)(9)(11)(14)(16)(70)(3)(6)(8)(10)(1)(13)(6)(11)(43)(7)(15)(5)(8)(3)(2)(6)(2)(18)温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(1107)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'VC接口枚举本地和网络打印机,并创建打印机实现打印',
blogAbstract:'1.背景:因为打印份数和打印范围神马的程序中已经做了控制,不需要用户在默认的windows打印窗口再设置,希望只出现一个给用户选择打印机的列表,并创建所选打印机DC实现打印\n2.方法:\n参考'
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}随笔 - 36&
评论 - 10&
&&&&&&&&&&&
前段时间需要将日志信息通过打印机打印出来。 总结了一下其中的一些用法: 1:用CPrintDialog 可以呼出窗口让用户选择打印机或者采用默认的打印机直接打印。 &&& StartPage…..EndPage& 完成一页文档的打印。& 如需改变DC设置,需要调用ReSetDC() &&& 多次调用这两个函数,可以实现打印多页 2:TextOut坐标的确定。 &&&& TextOut中的坐标是DC中的逻辑坐标。 &&&& 和实际的物理坐标需要转换。 &&& GetDeviceCpas();& //获取DC中的Device信息。 &&& GetTextMetrics(); //获取字体的信息。 字体高度和本身高度+行距。 3:TextOut中的字体可以设置。 &&& 关键代码如下: &&&& CFont myF &&&& myFont.CreatePontFont(….); &&&& oldFont = dc.SelectObject(); &&&& myFont.DelectObject()'; & & 附上 1:转载相关文档: 打印单位的转换 这个的关键是我们要得到显示设备的DPI,即每英寸设备支持的点数。有了DPI我们就可以在我们习惯的单位和设备单位之间转换了,用到的API是GetDeviceCaps(),这个函数功能强大,具体可参考MSDN,在这里我们只用来得到设备DPI。看示例代码:
//某些设备水平和垂直方向的DPI可能不同,所以要分别得到。
//得到水平方向的转换比例
float getXScale(HDC printDC)
//printDC: 打印机DC设备句柄
//得到打印机水平方向的DPI
int xDPI = GetDeviceCaps(printDC, LOGPIXELSX);
//254.0: 每英寸25.4毫米
float xScale = (float)(254.0 / xDPI);
//得到垂直方向的转换比例
float getYScale(HDC printDC)
//printDC: 打印机DC设备句柄
//得到打印机垂直方向的DPI
int yDPI = GetDeviceCaps(printDC, LOGPIXELSY);
float yScale = (float)(254.0 / yDPI);
//厘米转换为设备像素,水平方向
double cm2Unit_W(float xScale, double w) //w单位为厘米
return w*100/xS
//厘米转换为设备像素,垂直方向
double cm2Unit_H(float yScale, double h) //h单位为厘米
return h*100/yS
上面代码中,如果将printDC换为显示器设备DC句柄,即可得到厘米转换为显示器像素单位,打印预览时使用。得到显示器设备句柄可用::GetDC(NULL)得到。
打印基本流程
有了前面的知识,现在我们就可以打印了。Windows打印是有着固定的流程的,流程也比较简单。按照固定的顺序调用打印API即可:StartDoc() -& StartPage() -& 打印具体内容 -& EndPage() -& EndDoc()。如果要打印多页,循环StartPage()至EndPage()即可。
示例代码:
ZeroMemory(&doc,sizeof(doc));
doc.cbSize = sizeof(doc);
doc.lpszDocName = (LPCTSTR)"Print Test File";
StartDoc(printDC, &doc);
//准备打印
StartPage(printDC);
//开始打印页
//在(2.5cm, 2.5cm)处打印文本
char* text = "打印测试文本";
float xScale = getXScale(printDC);
float yScale = getYScale(printDC);
double x = cm2Unit_W(xScale, 2.5);
double y = cm2Unit_H(yScale, 2.5);
//在指定位置打印文本
TextOut(printDC, (int)x, (int)y, (LPTSTR)text, strlen(text));
EndPage(printDC);
//结束打印页
EndDoc(printDC);
//结束打印
打印字体的设置
很多时候我们希望能控制打印字体,下面的代码可以创建你想要的字体格式:
创建自定义打印字体
fontFace:字体名称,如果为NULL,默认采用“宋体”
fontHeight:字体高度,单位为厘米
isBold:是否加粗
isItalic:是否斜体
isUnderLine:是否下划线
isStrikeOut:是否删除线
HFONT getFont(LPCTSTR fontFace, double fontHeight, bool isBold, bool isItalic, bool isUnderLine, bool isStrikeOut)
int width = 0; //字体宽度由系统决定
int weight = FW_NORMAL;
DWORD italic = 0;
DWORD underLine = 0;
DWORD strikeOut = 0;
DWORD charSet = DEFAULT_CHARSET;
LPCTSTR face = (LPCTSTR)"宋体";
float height = cm2Unit_H(fontHeight);
if(fontFace != 0)
face = fontF
if(isBold)
weight = FW_BOLD;
if(isItalic)
italic = 1;
if(isUnderLine)
underLine = 1;
if(isStrikeOut)
strikeOut = 1;
HFONT font = CreateFont((int)height, width, 0, 0,
weight, italic, underLine, strikeOut, charSet,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, face );
以上就是我们在实现打印中遇到的常见问题,相信理解了这些,在我们自己的程序中实现打印就不再是什么困难的事情了。
为打印多页文档,框架与视图以如下方式交互。首先,框架显示“打印”对话框,为打印机创建设备上下文,并调用
成员函数。然后,对于文档中的每一页,框架调用 CDC 对象的
成员函数,指示视图对象打印页,并调用
成员函数。如果在开始某个特定页之前必须更改打印机模式,视图将调用
,它将更新含有新的打印机模式信息的
结构。全部文档打印完毕后,框架调用
成员函数。
重写视图类函数
类定义在打印过程中被框架调用的几个成员函数。通过在视图类中重写这些函数,提供框架打印逻辑与视图类打印逻辑之间的连接。下表列出了这些成员函数。
用于打印的 CView 可重写函数
名称重写原因
OnPreparePrinting
在“打印”对话框中插入值,尤其是文档的长度
OnBeginPrinting
分配字体或其他 GDI 资源
OnPrepareDC
调整给定页的设备上下文属性,或进行打印时分页
打印给定页
OnEndPrinting
解除分配 GDI 资源
也可用其他函数执行打印相关处理,但这些函数是驱动打印过程的函数。
下图阐释了打印过程所涉及的步骤,并显示了在何处调用 CView 的每个打印成员函数。本文其余部分是对大多数步骤更详细的解释。一文介绍了打印过程的其他部分。
CPrintInfo
结构中存储许多关于打印作业的信息。CPrintInfo 中的几个值是关于分页的;这些值如下表所示。
存储在 CPrintInfo 中的页码信息
成员变量或函数名引用的页码
GetMinPage/SetMinPage文档的第一页
GetMaxPage/SetMaxPage文档的最后一页
GetFromPage要打印的第一页
GetToPage要打印的最后一页
m_nCurPage当前正在打印的页
页码从 1 开始,也就是说,第一页的编号为 1,而不是 0。有关上述及其他
CPrintInfo
成员的更多信息,请参见“MFC 参考”。
在打印过程的开始,框架调用视图的
OnPreparePrinting
成员函数,向 CPrintInfo 结构传递一个指针。“应用程序向导”提供调用 CView 的另一个成员函数
DoPreparePrinting
的 OnPreparePrinting 实现。DoPreparePrinting 是显示“打印”对话框并创建打印机设备上下文的函数。
这时,应用程序并不知道文档的页数。它对文档的第一页和最后一页的页码使用默认值 1 和 0xFFFF。如果您知道文档的页数,在将文档发送到 DoPreparePrinting 之前,请重写 OnPreparePrinting,并为 CPrintInfo 结构调用
SetMaxPage
。这使您得以指定文档的长度。
接下来 DoPreparePrinting 显示“打印”对话框。当它返回时,CPrintInfo 结构包含用户指定的值。如果用户希望只打印选定页码范围内的文档,他或她可以在“打印”对话框中指定起始页码和终止页码。框架使用
CPrintInfo
的 GetFromPage 和 GetToPage 函数检索这些值。如果用户未指定页码范围,框架将调用 GetMinPage 和 GetMaxPage 并使用返回的值来打印整个文档。
对于文档中将要打印的每一页,框架调用视图类中的两个成员函数(
OnPrepareDC
),并传递给每个函数两个参数:一个指向
对象的指针和一个指向 CPrintInfo 结构的指针。每次当框架调用 OnPrepareDC 和 OnPrint 时,它都传递 CPrintInfo 结构的 m_nCurPage 成员中的不同值。框架通过这种方式通知视图要打印哪些页。
OnPrepareDC
成员函数也可用于屏幕显示。它在绘制之前调整设备上下文。OnPrepareDC 在打印中起同样的作用,但有两点不同:首先,CDC 对象表示打印机设备上下文而不是屏幕设备上下文;其次,CPrintInfo 对象作为第二个参数传递。(当为屏幕显示调用 OnPrepareDC 时,此参数为 NULL。)重写 OnPrepareDC 以便根据正在打印的页的不同来调整设备上下文。例如,可通过移动视区原点和剪辑区域,确保文档中的适当部分得到打印。
成员函数执行页的实际打印。一文显示了框架是如何用打印机设备上下文调用
来执行打印的。更确切地说,框架用 CPrintInfo 结构和设备上下文调用 OnPrint,OnPrint 将设备上下文传递给 OnDraw。重写 OnPrint,执行任何只应在打印而非屏幕显示期间完成的呈现。例如,打印页眉或页脚(有关更多信息,请参见一文)。然后,从 OnPrint 的重写调用 OnDraw 来进行屏幕显示和打印的共同呈现。
OnDraw 既进行屏幕显示呈现又进行打印呈现的事实意味着您的应用程序是 WYSIWYG(所见即所得)。然而,假设您正在写的不是“所见即所得”应用程序。例如,一个文本编辑器使用粗体作为打印字体,但同时显示控制代码指示屏幕上粗体文本。对于这种情况,应严格使用 OnDraw 进行屏幕显示。当您重写 OnPrint 时,用一个对单独绘制函数的调用取代对 OnDraw 的调用。该函数使用未显示在屏幕上的属性,以文档显示在纸上的方式绘制文档。
打印机页与文档页
提到页码,有时必须得区分打印机页的概念和文档页的概念。从打印机的角度讲,一页是一张纸。但是,一张纸并不一定等于文档中的一页。例如,如果打印一份通讯稿,纸张将要折叠,一张纸可能同时含有文档的第一页和最后一页(它们是并排的)。同样,如果打印一份电子表格,文档根本不是由页组成的。相反,一张纸可能包含第一到第二十行,第六到第十列。
CPrintInfo
结构中的页码都是指打印机页。框架对通过打印机的每一页纸调用一次 OnPrepareDC 和 OnPrint。当重写
OnPreparePrinting
函数来指定文档长度时,必须使用打印机页。如果存在一一对应关系(即,一个打印机页等于一个文档页),那么事情就简单了。反之,如果文档页与打印机页并非一一对应,则必须在两者之间进行转换。例如,打印一份电子表格。当重写 OnPreparePrinting 时,必须计算打印整个电子表格所需的纸张数,并在调用 CPrintInfo 的 SetMaxPage 成员函数时使用该值。同样,当重写 OnPrepareDC 时,必须将 m_nCurPage 转换成会出现在特定纸张上的行和列的范围,然后相应调整视区原点。
打印时分页
有些情况下,您的视图类可能在文档实际打印之前并不会事先知道文档的长度。例如,如果您的应用程序不是“所见即所得”的,那么屏幕上的文档长度并不对应于其打印时的长度。
当您为视图类重写
OnPreparePrinting
时,就会产生这样的问题:无法向
CPrintInfo
结构的 SetMaxPage 函数传递值,因为您不知道文档的长度。如果用户不使用“打印”对话框指定终止页码,框架就不知该在何时停止打印循环。唯一可以确定何时停止打印循环的方法是打印出全部文档并弄清其何时终止。您的视图类必须在文档打印期间检查是否到达文档末尾,并在到达时通知框架。
框架依赖于您的视图类的
OnPrepareDC
函数来告知何时停止。在每次调用 OnPrepareDC 之后,框架检查 CPrintInfo 结构的一个名为 m_bContinuePrinting 的成员。该成员的默认值为 TRUE。只要它保持此默认值,框架就继续打印循环。如果它设置为 FALSE,框架就停止。若要执行打印时分页,请重写 OnPrepareDC 以检查是否已到达文档末尾,如果已经到达,则将 m_bContinuePrinting 设置为 FALSE。
如果当前页大于 1,OnPrepareDC 的默认实现将把 m_bContinuePrinting 设置为 FALSE。这意味着如果未指定文档长度,框架将假设文档的长度为一页。这样做的结果之一就是在调用 OnPrepareDC 的基类版本时必须谨慎。不要假定 m_bContinuePrinting 在调用基类版本之后将为 TRUE。
2:MSDN上的一段示例代码:// get the default printer
CPrintDialog dlg(FALSE);
dlg.GetDefaults();
// is a default printer set up?
HDC hdcPrinter = dlg.GetPrinterDC();
if (hdcPrinter == NULL)
MessageBox(_T("Buy a printer!"));
// create a CDC and attach it to the default printer
dcPrinter.Attach(hdcPrinter);
// call StartDoc() to begin printing
memset(&docinfo, 0, sizeof(docinfo));
docinfo.cbSize = sizeof(docinfo);
docinfo.lpszDocName = _T("CDC::StartDoc() Code Fragment");
// if it fails, complain and exit gracefully
if (dcPrinter.StartDoc(&docinfo) & 0)
MessageBox(_T("Printer wouldn't initalize"));
// start a page
if (dcPrinter.StartPage() & 0)
MessageBox(_T("Could not start page"));
dcPrinter.AbortDoc();
// actually do some printing
CGdiObject* pOldFont = dcPrinter.SelectStockObject(SYSTEM_FONT);
dcPrinter.TextOut(50, 50, _T("Hello World!"), 12);
dcPrinter.EndPage();
dcPrinter.EndDoc();
dcPrinter.SelectObject(pOldFont);
阅读(...) 评论()}

我要回帖

更多关于 XP打印机共享怎么设置 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信