您的位置:首页 > 其它

MFC 打印和预览的功能

2010-06-07 21:41 232 查看
MFC 本身提供了很好的框架。

// XXX绘制

void XXX::OnDraw(CDC* pDC)
{
XXX* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

}

// XXX打印

BOOL XXX::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}

void XXX::OnBeginPrinting(CDC* pDC, CPrintInfo *pInfo)
{
// TODO: 添加额外的打印前进行的初始化过程

}

void XXX::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清除过程
}

// XXX消息处理程序

void XXX::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
//这里添加绘制的代码
CView::OnPrint(pDC, pInfo);
}

void CTest0607View::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point, CPreviewView* pView)
{
// TODO: 在此添加专用代码和/或调用基类

CView::OnEndPrintPreview(pDC, pInfo, point, pView);
}

但是OnPrint里面绘制的内容总是会被OnDraw()里面绘制覆盖。后来也看了网上很多例子,也有DLG来实现的,但是总是觉得不太好。

今天无意间看见一篇文章:OnPrint()和OnDraw()区别和联系

才知道OnPrint最后是一定会调用OnDraw()的。

以下是转的文章

基本基类----CView类中含有三个方法
1,虚函数OnPrint()
2,基本消息响应函数OnPaint(),非虚函数
3,虚函数OnDraw()
一般在我们创建Doc/View应用程序时,视图类的基类多数为CView类,或者其派生类,因此,在我们的应用程序中的View类中就继承了其父类的上面的三个方法,但是,在我们使用classwizard生成应用程序的框架的时候,向导只为我们的View类override了OnDraw()方法。其余两个方法没有生成。程序运行时,在输出显示(向显示器输出或者向打印机输出)之前,应用程序自动发出WM_PAINT消息,此时,我们的应用程序会调用我们的View类中的OnPaint()或者OnPrint()方法,但是,我们View类中并没有override其实现代码,因而调用其基类的相应的 OnPaint()或者OnPrint()方法,下面进行分类:
1在向显示器输出时,调用的是OnPaint()方法,而OnPaint()方法默认情况下会调用OnDraw()来具体动作,即向显示器输出具体的内容
2在向打印机输出时,调用的是OnPrint()方法,而OnPrint()方法默认情况下同样调用OnDraw()来具体动作,即向打印机输出具体内容
而实际上,我们只有一个已经实现了具体代码的OnDraw()方法,因此在向显示器输出和向打印机输出时的具体动作是一样的,也就是具体的输出方式和输出内容都是一样的。
那么OnPaint()和OnPrint()难道只调用OnDraw来实际动作,还要这连个函数干吗呢,不如直接用OnDraw不就完了吗?实际情况并非如此,分析如下:

CWnd::OnPaint

afx_msg void OnPaint( );

Remarks
The framework calls this member function when Windows or an application makes a request to repaint a portion of an application’s window. The

WM_PAINT message is sent when the UpdateWindow or RedrawWindow member function is called.

CView::OnDraw

virtual void OnDraw( CDC* pDC ) = 0;

Remarks
Called by the framework to render an image of the document.

The framework calls this function to perform screen display, printing, and print preview, and it passes a different device context in each case. There is no default implementation.
You must override this function to display your view of the document.

If you need to distinguish between normal screen display and printing, call the IsPrinting member function of the device context.

区别已经很明显。OnPaint()是CWnd的成员函数,所有CWnd的子类都有一份OnPaint,而OnDraw()则是CView类中声明的纯虚函数。OnPaint()响应WM_PAINT消息,OnDraw不响应任何消息,只是一个虚函数。CWnd的子类分为四大类:FrameWindows, Dialog Boxes, Views, Controls,因此除了View及其子类使用OnDraw()外,其余三类都使用OnPaint()来重画, 而View类里面是使用OnDraw(),但OnDraw()使用时由于是虚函数故也不会调用到上一级的OnPain()咯···OnPaint()的工作是'Screen Display',而OnDraw()则可以做'Screen display, printing, print preview'等工作。

再看MFC源代码中如何做:
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc); //···此时OnDraw()是包含在OnPain()中的!!!
}
OnPaint()是CWnd类的非虚函数,CView中重载了该函数。从代码中可以看出,在CView响应WM_PAINT消息的情况下,在OnPaint中先调用了OnPrepareDC(),然后调用了OnDraw()。查MSDN,可以看到,
OnPrepareDC()的作用是:framework中在OnDraw()之前调用它,或者在OnPrint中调用它,前者是为了准备屏幕显示,后者是为了打印。MFC中OnPrepareDC的源代码是:
void CView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
ASSERT_VALID(pDC);
UNUSED(pDC); // unused in release builds

// Default to one page printing if doc length not known
if (pInfo != NULL)
pInfo->m_bContinuePrinting =
(pInfo->GetMaxPage() != 0xffff || (pInfo->m_nCurPage == 1));
}
这是CView中的定义,OnPrepareDC()是一个虚函数。完全可以改写它(虚函数的区别)。在CView各子类中该函数的定义都不一样。
因此,尽管主调函数不同,传入的参数也不同,但是对于OnDraw方法来说,这个DC对象是毫无差别的,只是一个用来画内容的工具,在其具体动 作时,根本不区分是何种对象,因此也就实现了设备的无关性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: