按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
当你改变窗口大小,产生WM_PAINT ,OnDraw 会收到一个「显示屏DC 」。
当你选按【File/Print。。。 】,OnDraw 会收到一个「打印机DC 」。
数章之前讨论CView 时我曾经提过,OnDraw 是CView 类别中最重要的成员函数,所
有的绘图动作都应该放在其中。请注意,OnDraw 接受一个「CDC 对象指针」做为它的
参数。当窗口接受WM_PAINT 消息,Framework 就调用OnDraw 并把一个「显示屏DC 」
传过去,于是OnDraw 输出到屏幕上。
Windows 的图形装置接口(GDI )完全与硬件无关,相同的绘图动作如果送到「显示屏
DC 」,就是在屏幕上绘图,如果送到「打印机DC 」,就是在打印机上绘图。这个道理
很容易就解释了为什么您的程序代码没有任何特殊动作却具备打印功能:当使用者按下
【File/Print 】,application framework 送给OnDraw 的是一个「打印机DC 」而不再是「显
示幕DC 」。
在MFC 应用程序中,View 和application framework 分工合力完成打印工作。Application
framework 的责任是:
显示【Print 】对话框,如图12…1b。
为打印机产生一个CDC 对象。
调用CDC 对象的StartDoc 和EndDoc 两函数。
持续不断地调用CDC 对象的StartPage ,通知View 应该输出哪一页;一页打印
完毕则调用CDC 对象的EndPage 。
我们(程序员)在View 对象上的责任是:
通知application framework 总共有多少页要打印。
application framework 要求打印某特定页时,我们必须将Document 中对应的部
份输出到打印机上。
配置或释放任何GDI 资源,包括笔、刷、字形。。。等等。
如果需要,送出任何escape 码改变打印机状态,例如走纸、改变打印方向等等。
670
…………………………………………………………Page 733……………………………………………………………
第 12 章 列印與預樱А�
送出escape 码的方式是,调用CDC 对象的Escape 函数。
现在让我们看看这两组工作如何交叉在一起。为实现上述各项交互动作,CView 定义了
几个相关的成员函数,当你在AppWizard 中选择【Printing and Print Preview 】选项之后,
除了OnDraw,你的View 类别内还被加入了三个虚拟函数空壳:
// in SCRIBBLEVIEW。H
class CScribbleView : public CScrollView
{
。。。
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC; CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC; CPrintInfo* pInfo);
。。。
};
// in SCRIBBLEVIEW。CPP
BOOL CScribbleView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CScribbleView::OnBeginPrinting(CDC* /*pDC*/; CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CScribbleView::OnEndPrinting(CDC* /*pDC*/; CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
改写这些函数有助于我们在framework 的打印机制与应用程序的View 对象之间架起
沟通桥梁。
为了了解MFC 中的打印机制,我又动用了我的法宝:Visual C++ Debugger 。我发现,
AppWizard 为我的View 做出这样的Message Map :
671
…………………………………………………………Page 734……………………………………………………………
第篇 深入 MFC 程式設計
BEGIN_MESSAGE_MAP(CScribbleView; CScrollView)
。。。
// Standard printing mands
ON_MAND(ID_FILE_PRINT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_PREVIEW; CView::OnFilePrintPreview)
END_MESSAGE_MAP()
显然,当【File/Print。。。 】被按下,命令消息将流往CView::OnFilePrint 去处理,于是我以
Debugger 进入该位置并且一步一步执行,得到图12…4 的结果。
// in VIEWPRNT。CPP
#0001 void CView::OnFilePrint()
#0002 {
#0003 // get default print info
#0004 CPrintInfo printInfo;
#0005 ASSERT(printInfo。m_pPD != NULL); // must be set
#0006
#0007 if (GetCurrentMessage()…》wParam == ID_FILE_PRINT_DIRECT)
#0008 {
#0009 CmandLineInfo* pCmdInfo = AfxGetApp()…》m_pCmdInfo;
#0010
#0011 if (pCmdInfo != NULL)
#0012 {
#0013 if (pCmdInfo…》m_nShellmand == CmandLineInfo::FilePrintTo)
#0014 {
#0015 printInfo。m_pPD…》m_pd。hDC = ::CreateDC(pCmdInfo…》m_strDriverName;
#0016 pCmdInfo…》m_strPrinterName; pCmdInfo…》m_strPortName; NULL);
#0017 if (printInfo。m_pPD…》m_pd。hDC == NULL)
#0018 {
#0019 AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
#0020 return;
#0021 }
#0022 }
#0023 }
#0024
#0025 printInfo。m_bDirect = TRUE;
#0026 }
#0027
#0028 if (OnPreparePrinting (&printInfo))