以下的内容是照着CSDN上下载的一份代码写的,如有不对望指正
打印预览和打印流程
在对话框类建立一个框架类的对象指针成员,框架类可以派生自 CFrame,
当要打印的时候,现创建出框架对象,可以将当前的对话框的窗口对象传到框架对象中保存
然后框架对象调用 Create 创建自己的窗口,
在框架的OnCreate函数中创建view, view是派生自 CScrollView 的,并且设置 m_nMapMode 为 MM_TEXT,这个最好在构造函数中
可以使用框架类的 CreateView
然后将打印的内容写入到 CBitmap 对象中,比如 m_bitmapPrint 中,如下代码可以将显示窗口的内容写入到 m_bitmapPrint
CRect rectWnd;
CBitmap *pOldBitmap;
CDC* pDC = GetDC();
CDC* pMemDC = new CDC;
//获取窗口位图
GetWindowRect(rectWnd);
m_bitmapPrint.DeleteObject();
m_bitmapPrint.CreateCompatibleBitmap(pDC, rectWnd.Width(), rectWnd.Height());
pMemDC->CreateCompatibleDC(pDC);
pOldBitmap = pMemDC->SelectObject(&m_bitmapPrint);
PrintWindow(pMemDC, 0);
pMemDC->SelectObject(pOldBitmap);
//释放内存
ReleaseDC(pMemDC);
delete pMemDC;
然后调用框架类的 DoPrintView, 其中调用框架视图的 OnFilePrintPreview, 这2个函数名字是自己写的
在 DoPrintView 函数里需要将程序的主窗口设置成当前的 框架类 的窗口,不然会报错!!
CWinApp *pApp = AfxGetApp();
pApp->m_pMainWnd = this;
在框架视图的 OnFilePrintPreview 函数中需要创建一个 CPrintPreviewState 类对象,这个是个系统类,将关闭打印预览的回调函数设置进去,
然后调用 DoPrintPreview, DoPrintPreview 是开始打印预览的函数, 这个函数有个参数是 打印预览视图类 的 运行时,
CPrintPreviewState* pState = new CPrintPreviewState;
pState->lpfnCloseProc = ProcClosePrintPreview; // 关闭打印预览视图的回调函数
// 最好显示工具栏,可以在预览时直接点工具栏上的按钮打印,并且有放大缩小功能
// CPreviewPrint 派生自系统的 CPreviewView, 是打印预览的视图
// this 是框架视图
if(!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this, RUNTIME_CLASS(CPreviewPrint), pState))
{
TRACE0("Error: DoPrintPreview failed.\n");
AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
delete pState;
}
这个打印预览视图需要派生自系统的 CPreviewView 类,然后就创建出打印预览视图的界面,注意这个视图不是之前框架里面那个视图
然后系统回调框架视图类的 OnPreparePrinting, 并传进来一个 CPrintInfo 类的指针参数,只需要在这里直接调用父类 CView 的 DoPreparePrinting,
然后系统回调框架视图类的 OnBeginPrinting, 并传进来一个 CDC 指针参数和 CPrintInfo 类的指针参数,这里可以设置打印多少页,
pInfo->SetMaxPage(3); // 可以设置多页,当设置多页时, pInfo 里的 m_nCurPage 成员会指示,从1开始计数
然后直接调用父类 CScrollView 的 OnBeginPrinting
这时就会调用打印预览视图的 OnDraw 函数, 直接调用父类 CPreviewView 的 OnDraw 函数,
如果在创建打印预览视图的时候指定了工具栏, 可以给工具栏post WM_IDLEUPDATECMDUI 消息 wParam == bDisableIfNoHandler
然后系统回调框架视图类的 OnPrint, 并传进来一个 CDC 指针参数和 CPrintInfo 类的指针参数,
然后发送消息给 对话框类, 将之前准备好的 m_bitmapPrint 给 StretchBlt 到 CDC 指针参数对应的 DC 中
CRect rectWnd;
BITMAP bmGraphy;
CBitmap bitmapTemp, *pOldBmpGraphy;
CDC* pGraphyDC = new CDC;
CDC* pDC = GetDC();
CDC* pPrintDC = (CDC*)wParam; // OnPrint 中的 CDC 指针参数
CPrintInfo* pInfo = (CPrintInfo*)lParam; // OnPrint 中的 CPrintInfo 指针参数
//pInfo 里的 m_nCurPage 成员会指示当前是哪一页,从1开始计数,根据这个修改内容就行
m_bitmapPrint.GetBitmap(&bmGraphy);
pGraphyDC->CreateCompatibleDC(pDC);
pOldBmpGraphy = pGraphyDC->SelectObject(&m_bitmapPrint);
pPrintDC->StretchBlt(pInfo->m_rectDraw.left, pInfo->m_rectDraw.top, pInfo->m_rectDraw.Width(), pInfo->m_rectDraw.Height(), pGraphyDC, 0, 0, bmGraphy.bmWidth, bmGraphy.bmHeight, SRCCOPY);
pGraphyDC->SelectObject(pOldBmpGraphy);
//释放内存
ReleaseDC(pGraphyDC);
delete pGraphyDC;
return 1;
当你点击打印预览工具栏上的放大缩小的时候会调用 打印预览视图的 OnDraw 函数, 然后再次调用 框架视图的 OnPrint 函数,然后同上
到此打印预览完成
当你点击打印预览界面上的打印按钮时,系统回调 打印预览视图的 OnPreviewPrint 函数,可以直接发(WM_COMMAND, ID_FILE_PRINT)消息通知给 框架视图类
然后系统回调框架视图类的 OnPreparePrinting, 此时显示的是一个 CPrintDialog 对话框,然后点确定之后,
系统回调框架视图类的 OnBeginPrinting 和 OnPrint, 跟打印预览一样了
当关闭打印预览视图界面时可以点工具栏,也可以点右上角叉,
当点工具栏的关闭时,系统会回调 打印预览视图类的 OnPreviewClose 函数,因为此时程序的主窗口类是 框架类 而不是 主对话框类,(之前在 DoPrintView 设置的)
所以需要将程序的主窗口类设置成主对话框类,如果不设置会关闭整个程序而不是打印预览视图.还需要手动销毁 框架类,系统测试不会代替你销毁
如果是通过点击右上角非客户区的叉按钮,则会调用之前设置的关闭回调函数,可以在里面手动调用 打印预览视图 的 OnPreviewClose,但是,
不能手动销毁 框架类,系统会代替程序销毁的,所以在这里需要做判断
CPrintFrame* pFrame = (CPrintFrame*)::AfxGetMainWnd();
// 这里需要修改 CWinApp 对应的主窗口, 默认是框架类,需要设置成宿主的窗口类
// 如果不修改会将整个程序关掉
CWinApp* pApp = AfxGetApp();
pApp->m_pMainWnd = pFrame->m_pMainDlg;
if(!m_bClickNCClose){
// 点击了工具栏上的关闭需要手动的销毁框架
// 点击了非客户区的关闭按钮就不需要手动销毁框架
pFrame->DestroyWindow();
}
以上在vs2005上调试通过,vs2010上关闭的时候都需要手动销毁