原文链接:http://www.cnblogs.com/xianyunhe/archive/2011/12/18/2292043.html

MFC框架中内置了打印框架,已实现单页的打印,如果视图中只有一页图形,并依据像素打印视图,不需要添加任何代码就可直接使用,非常方便。侯捷的《深入浅出MFC》中对MFC的打印框架进行了剖析,详细讲解各函数之间的调用关系,但对多页打印,却并未讲解。下面研究如何实现多页打印。

1、页面布局

在界面区域较大时,我们需要多页打印,如Excel表的打印。当横向和纵向都无法打印在一页时,页面的布局可逐行排列,也可以逐列排列。页面布局的两种示意图如下所示。

1)逐行排列页面布局示意如下:

1

2

3

4

5

6

2)逐列排列页面布局示意如下:

1

3

5

2

4

6

 

2、设定页数

在打印前,需要先设定打印的页数,即根据整个视图的大小和页面的大小来计算页数。只要才打印前设置即可。下面是在子类中重载CView类的OnBeginPrinting函数,用于实现页数的计算,实现代码如下:

 

复制代码
 1 void CMultiPagePrintView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
2 {
3 // TODO: add extra initialization before printing
4
5 /*得到打印纸的像素大小*/
6 int iPageWidth = pDC->GetDeviceCaps(HORZRES);
7 int iPageHeight = pDC->GetDeviceCaps(VERTRES);
8
9 /*得到窗口的大小*/
10 CSize szTotalWnd = GetTotalSize();
11
12 /*得到行和列的数量*/
13 int iRowCnt = szTotalWnd.cy / iPageHeight;
14 if (szTotalWnd.cy % iPageHeight > 0)
15 {
16 iRowCnt++;
17 }
18 int iColCnt = szTotalWnd.cx / iPageWidth;
19 if (szTotalWnd.cx % iPageWidth > 0)
20 {
21 iColCnt++;
22 }
23
24 /*得到要打印的页数*/
25 int iPageCnt = iRowCnt * iColCnt;
26 pInfo->SetMaxPage(iPageCnt);
27 }
复制代码

 

3、设置页面原点

在打印每一页的过程中,只需得到当前打印页面的页码,并计算出该页面原点对应的视图中的位置,然后调用CView::OnPrint即可完成打印。由于页面采用逐行排列和逐页排列时,页面对应的视图位置并不相同,因此,需要根据页面的排列模式分开计算。实现代码如下:

复制代码
 1 void CMultiPagePrintView::OnPrint(CDC* pDC, CPrintInfo* pInfo) 
2 {
3 // TODO: Add your specialized code here and/or call the base class
4
5 /*得到打印纸的像素大小*/
6 int iPageWidth = pDC->GetDeviceCaps(HORZRES);
7 int iPageHeight = pDC->GetDeviceCaps(VERTRES);
8
9 /*得到窗口的大小*/
10 CSize szTotalWnd = GetTotalSize();
11
12 /*得到行和列的数量*/
13 int iRowCnt = szTotalWnd.cy / iPageHeight;
14 if (szTotalWnd.cy % iPageHeight > 0)
15 {
16 iRowCnt++;
17 }
18 int iColCnt = szTotalWnd.cx / iPageWidth;
19 if (szTotalWnd.cx % iPageWidth > 0)
20 {
21 iColCnt++;
22 }
23
24 /*得到当前页的行和列编号,起始编号均为0*/
25 int iPageRowIdx = 0;
26 int iPageColIdx = 0;
27
28 if (LAYOUT_BY_ROW == m_iPageLayout)
29 {
30 iPageRowIdx = (pInfo->m_nCurPage-1) / iColCnt;
31 iPageColIdx = (pInfo->m_nCurPage-1) % iColCnt;
32 }
33 else
34 {
35 iPageRowIdx = (pInfo->m_nCurPage-1) % iRowCnt;
36 iPageColIdx = (pInfo->m_nCurPage-1) / iRowCnt;
37 }
38
39
40 /*得到当前页的原点*/
41 CPoint ptOrgin(0,0);
42 ptOrgin.x = iPageColIdx * iPageWidth;
43 ptOrgin.y = iPageRowIdx * iPageHeight;
44 pDC->SetWindowOrg(ptOrgin);
45
46 CScrollView::OnPrint(pDC, pInfo);
47 }
复制代码

 

4、示例程序

本文以像素分辨率为2480*3507A4打印纸为例,分别实现了逐行排列和逐列排列的打印。为了方便检验打印是否正确,在页面中标注了页码和当前页所在的界面的行和列,其中页面的起始值为1,而行和列的起始值为0

工程文件下载:

PUDN:http://www.pudn.com/downloads407/sourcecode/windows/control/detail1735047.html

CSDN:http://download.csdn.net/detail/xianyunhe1234/3937881