mfc对话框上添加打印预览和打印

以下的内容是照着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 函数里需要将程序的主窗口设置成当前的 框架类 的窗口,用于欺骗MFC,让MFC知道当前的主窗口是 框架类窗口,这样才能打印.

当打印完成需要修改回去,切记!!  这就是为什么上面需要保存主窗口(对话框窗口)的原因.

CWinApp    *pApp = AfxGetApp();
pApp->m_pMainWnd = this;



在框架视图的 OnFilePrintPreview 函数中需要创建一个 CPrintPreviewState 类对象,这个是个系统类,将关闭打印预览的回调函数设置进去,
然后调用 DoPrintPreview, DoPrintPreview 是开始打印预览的函数, 这个函数有个参数是 打印预览视图类 的 运行时,

CPrintPreviewState*    pState    = new CPrintPreviewState;
pState->lpfnCloseProc    = ProcClosePrintPreview;    // 点叉关闭打印预览视图的回调函数

// 最好显示工具栏,可以在预览时直接点工具栏上的按钮打印,并且有放大缩小功能
// CPreviewPrint 派生自系统的 CPreviewView, 是打印预览的视图
// this 是框架视图
// 需要在程序的.rc文件中加入如下一行,不然不能建立工具栏
// #include "l.chs\\afxprint.rc"
// 摘自 http://blog.csdn.net/autumn20080101/article/details/8815248
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;

 

当你点击打印预览工具栏上的放大缩小的时候会调用 打印预览视图的 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上关闭的时候都需要手动销毁

posted on 2017-08-23 13:59  litandy  阅读(1366)  评论(0编辑  收藏  举报

导航