友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第91部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
CString GetDeviceName() const; // return device name
CString GetPortName() const; // return output port name
HDC GetPrinterDC() const; // return HDC (caller must delete)
HDC CreatePrinterDC();
。。。
};
如果必要(从命令列参数中得知要直接打印某个文件到打印机上),利用::CreateDC
产生一个「打印机DC 」,并做打印动作。注意,printInfo 。m_bDirect 被设为TRUE,表
示跳过打印对话框,直接打印。
677
…………………………………………………………Page 740……………………………………………………………
第篇 深入 MFC 程式設計
OnPreparePrinting 是一个虚拟函数,所以如果CView 的衍生类别改写了它,控制权
就移转到衍生类别手中。本例将移转到CScribbleView 手中。
CScribbleView::OnPreparePrinting 的预设内容(AppWizard 自动为我们产生)是调用
DoPreparePrinting ,它并不是虚拟函数,而是CView 的一个辅助函数。以下是其调用堆
叠,直至【打印】对话框出现为止。
CView::OnFilePrint
CView::OnFilePrint (in VIEWPRNT。CPP)
CScribbleView::OnPreparePrinting (in SCRIBVW。CPP)
CScribbleView::OnPreparePrinting
CView::DoPreparePrinting (in VIEWPRNT。CPP)
CView::DoPreparePrinting
CWinApp::DoPrintDialog (in APPPRNT。CPP)
CWinApp::DoPrintDialog
CWinApp::UpdatePrinterSelection (in APPPRNT。CPP)
CWinApp::UpdatePrinterSelection
CPrintDialog::GetDefaults (in DLGPRNT。CPP)
CPrintDialog::GetDefaults
::PrintDlg (Win32 API)
::PrintDlg
CPrintDialog::DoModal (in DLGPRNT。CPP)
CPrintDialog::DoModal
::PrintDlg (Win32 API)
::PrintDlg
CView::DoPreparePrinting 将贮存在CPrintInfo 结构中的对话框CPrintDialog* m_pPD
显示出来,借此收集使用者对打印机的各种设定,然后产生一个「打印机DC 」,储存在
printinfo。m_pPD…》m_pd。hDC 之中。
如果使用者在【打印】对话框中选按【打印到文件】,则再显示一个【Print to File 】
对话框,让使用者设定档名。
678
…………………………………………………………Page 741……………………………………………………………
第 12 章 列印與預樱А�
接下来取文件名称和输出设备的名称(可能是打印机也可能是个文件),并产生一个
DOCINFO 结构,设定其中的lpszDocName 和lpszOutput 字段。此一DOCINFO 结构
将在稍后的StartDoc 动作中用到。
如果使用者在【打印】对话框中按下【确定】钮,OnFilePrint 就在堆栈中制造出一
个CDC 对象,并把前面所完成的「打印机DC 」附着到CDC 对象上:
CDC dcPrint;
dcPrint。Attach(printInfo。m_pPD…》m_pd。hDC);
dcPrint。m_bPrinting = TRUE;
一旦CDC 完成, OnFilePrint 把CDC 对象以及前面的CPrintInfo 对象传给
OnBeginPrinting 作为参数。OnBeginPrinting 是CView 的一个虚拟函数,原本什么也没
做。你可以改写它,设定打印前的任何初始状态。
设定AbortProc 。这应该是一个callback 函数,MFC 有一个预设的简易函数
_AfxAbortProc 可兹利用。
CView::OnFilePrint (in VIEWPRNT。CPP)
CView::OnFilePrint
CDC::SetAbortProc (macro; defined in AFXWIN1。INL)
CDC::SetAbortProc
::SetAbortProc (Win32 API)
::SetAbortProc
679
…………………………………………………………Page 742……………………………………………………………
第篇 深入 MFC 程式設計
把父窗口除能,产生【打印状态】对话框,根据文件名称以及输出设备名称,设定对
话盒内容,并显示之:
AfxGetMainWnd()…》EnableWindow(FALSE);
CPrintingDialog dlgPrintStatus(this);
。。。 //设定对话框内容
dlgPrintStatus。ShowWindow(SW_SHOW);
dlgPrintStatus。UpdateWindow();
CView::OnFilePrint (in VIEWPRNT。CPP)
CView::OnFilePrint
CPrintingDialog::CPrintingDialog (in VIEWPRNT。CPP)
CPrintingDialog::CPrintingDialog
CDialog::Create (产生对话框)
CDialog::Create
CWnd::ShowWindow (显示对话框)
CWnd::ShowWindow
StartDoc 通知打印机开始崭新的打印工作。这个函数其实就是激活Windows 打印引擎。
CView::OnFilePrint
CView::OnFilePrint (in VIEWPRNT。CPP)
CDC::StartDoc (macro; defined in AFXWIN1。INL)
CDC::StartDoc
::StartDoc (Win32 API)
::StartDoc
以for 循环针对文件中的每一页开始做打印动作。
调用CView::OnPrepareDC。此函数什么也没做。如果你要在每页前面加表头,就请
改写这个虚拟函数。
修改【打印状态】对话框中的页次。
StartPage 开始新的一页。
680
…………………………………………………………Page 743……………………………………………………………
第 12 章 列印與預樱А�
CView::OnFilePrint
CView::OnFilePrint
CDC::StartPage (macro; defined in AFXWIN1。INL)
CDC::StartPage
::StartPage (Win32 API)
::StartPage
⑤ 调用CView::OnPrint ,它的内部只有一个动作:调用OnDraw 。我们应该在
CScribbleView 中改写OnDraw 以绘出自己的图形。
CView ::OnFilePrint
CView ::OnFilePrint
CView ::OnPrint
CView ::OnPrint
CScribbleView ::OnDraw (我们应该改写OnDraw 以绘出自己的图形)
CScribbleView ::OnDraw
一页结束,调用一页结束,调用dcPrintdcPrint。。EndPageEndPage
CView ::OnFilePrint
CView ::OnFilePrint
CDC::EndPage (macro; defined in AFXWIN1。INL)
CDC::EndPage
::EndPage (Win32 API)
::EndPage
文件结束,调用EndDoc
CView::OnFilePrint
CView::OnFilePrint
CDC::EndDoc
CDC::EndDoc (macro; defined in AFXWIN1。INL)
::EndDoc (Win32 API)
::EndDoc
整个打印工作结束。如果有些什么绘图资源需要释放,你应该改写OnEndPrinting 函
式并在其中释放之。
CView::OnFilePrint
CView::OnFilePrint
CScribbleView::OnEndPrinting
CScribbleView::OnEndPrinting
681
…………………………………………………………Page 744……………………………………………………………
第篇 深入 MFC 程式設計
去除【打印状态】对话框。
将「打印机DC 」解除附着,CPrintInfo 的析构式会把DC 还给Windows 。
从上面这些分析中归纳出来的结论是,一共有六个虚拟函数可以改写,请看图12…5。
Framework 调用次序 建议改写项目
CMyView::OnPreparePrinting 设定Document 长度。调用CView::DoPreparePrinting 以显示
CMyView::OnPreparePrinting 【Print】对话框并产生打印机DC。
CMyView::OnBeginPrinting 设定以DC 为准的Document 长度;配置GDI 资源
CMyView::OnBeginPrinting
CDC::StartDoc
CDC::StartDoc
CMyView::OnPrepareDC 改变viewport 原点、剪截区、以及其它DC 属性。
CMyView::OnPrepareDC
CDC::StartPage
CDC::StartPage
CMyView::OnPrint 列打印头、页尾等等
CMyView::OnPrint
CMyView::OnDraw GDI 绘图动作
CMyView::OnDraw
CDC::EndPage
CDC::EndPage
CDC::EndDoc
CDC::EndDoc
CMyView::OnEndPrinting 释放GDI 资源
CMyView::OnEndPrinting
图12…5 MFC 打印流程与我们的着力点
682
…………………………………………………………Page 745……………………………………………………………
第 12 章 列印與預樱А�
以下是图12…5 的补充说明。
■当使用者按下【File/Print 】命令项, Application Framework 首先调用
CMyView::OnPreparePrinting 。这个函数接受一个CPrintInfo 指针做为参数,允许
使用者设定Document 的打印长度(从第几页到第几页)。预设页码是1 至
0xFFFF , 程序员应该在OnPreparePrinting 中调用SetMaxPage 预设页数。
SetMaxPage 之后,程序应该调用CView::DoPreparePrinting ,它会显示【打印】
对话框,并产生一个打印机DC 。当对话框结束,CPrintInfo 也从中获得了使用
者设定的各个打印项目(例如从第n1 页印到第n2 页) 。
Framework 如何得知使用者对于打印状态的设定?CPrintInfo 有五个函数可用,下一
节有更详细的说明。
■针对每一页,Framework 会调用CMyView::OnPrepareDC,这函数在前一章介绍
CScrollView 时也曾提过,当时是因为我们使用卷动窗口,而由于卷动的关系,
绘图之前必须先设定DC 的映射模式和原点等性质。这次稍有不同的是,它收
到打印机DC 做为第一参数,CPrintInfo 对象做为第二参数。我们改写这个函
式,使它依目前的页码来调整DC ,例如改变打印原点和截割区域以保证印出
来的Document 内容的合适性等等。
■稍早我一再强调所有绘图动作都应该集中在OnDraw 函数中,Framework 会自
动调用它。更精确地说,Framework 其实是先调用OnPrint,传两个参数进去,
第一参数是个DC , 第二参数是个CPrintInfo 指针。OnPrint 内部再调用
OnDraw,这次只传DC 过去,做为唯一参数:
// in VIEWCORE。CPP
void CView::OnPrint(CDC* pDC; CPrintInfo*)
{
ASSERT_VALID(pDC);
// Override and set printing variables based on page number
OnDraw(pDC); // Call Draw
}
683
…………………………………………………………Page 746……………………………………………………………
第篇 深入 MFC 程式設計
有了这样的差异,我们可以这么区分这两个函数的功能:
z OnPrint:负责「只在打印时才做(屏幕显示时不做)」的动作。例如印出
表头和页尾。
z OnDraw :共通性绘图动作(包括输出到屏幕或打印机上)都在此完成。
看看另一个函数OnPaint:
// in VIEWCORE。CPP
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
你会发现原来它们是这么分工的:
WM_MAND
CView::OnPrint 唯「打印」才有之工作,将在此进行
(ID_FILE_PRI NT) CView::OnPrint
CView::OnDraw 「打印」与「显示」共通的
CView::OnDraw
工作,在此进行
WM_ PA INT CView ::OnPaint 唯「显示」才有的工作,将在此进行
CView::OnPaint
所谓「显示」是指输出到屏幕上,「打印」是指输出到打印机上。
由同一函数完成显示(display )与打印(print )动作,才能够达到「所见即所得」(What
You See Is What You Get ,WYSIWYG )的目的。如果你不需要一个WYSIWYG 程序,
可以改写OnPrint 使它不要调用OnDraw,而调用另一个绘图例程。
不要认为什么情况下都需要WYSIWYG 。一个文字编辑器可能使用粗体字打印但使用控
制码在屏幕上代表这粗体字。
684
…………………………………………………………Page 747……………………………………………………………
第 12 章 列印與預樱А�
Scribble 打印机制的增强
MFC 预设的打印机制够聪敏了,但还没有聪敏到解决所有的问题。这些问题包括:
■打印出来的影像可能不是你要的大小
■不会分页
■没有表头(header )
■没有页尾(footer )
毕竟屏幕输出和打印机输出到底还是有着重大的差异。窗口有卷动杆而打印机没有,这
伴随而来的就是必须计算Document 的大小和纸张的大小,以解决分页的问题;此外,
我们必须想想,在MFC 预设的打印机制中,改写哪一个地方,才能让我们有办法在
Document 的输出页加上表头或页尾。
打印机的页和文件的页
首先,我们必须区分「页」对于Document 和对于打印机的不同意义。从打印机观点来
看,一页就是一张纸,然而一张纸并不一定容纳Document 的一页。例如你想印一些通
讯资料,这些资料可能是要被折叠起来的,因此一张纸印的是Document 的第一页和最
后一页(亲爱的朋友,想想你每天看的报纸)。又例如印一个巨大的电子表格,它可能是
Document 上的一页,却占据两张A4 纸。
MFC 这个Application Framework 把关于打印的大部份信息都记录在CPrintInfo 中,其
中数笔资料与分页有密切关系。下表是取得分页资料的相关成员,其中只有SetMaxPage
和m_nCurPage 和m_nNumPreviewPages 在Scribble 程序中会用到,原因是Scribble
程序对许多问题做了简化。
685
…………………………………………………………Page 748……………………………………………………………
第篇 深
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!