对话框程序调用Frame框架实现打印的具体细节

网上搜索了几天关于对话框的打印问题.大部分都抄来抄去的...

实现对话框所见即所得模式,其实就是在对话框上绘制...一般还是使用打印预览然后打印的功能吧.

发现这篇不错,,,http://blog.csdn.net/dailygrace/article/details/5277330 ,,不过其中还有少许错误,

咱们就一步一步的来实现吧.

最后本文给出一个可行的方案,也是网上收集的例子.

PS:由于个人修改的 所以改掉了类名.也算一遍梳理吧.

再PS:程序编译可能还会有一些小错误,一般是符号不同造成的了.例如双引号,括号的全半角差异... - -||


下面进入正题:

1.用MFC应用向导创建对话框应用程序,设主对话框类为CMyPrintPreviewDlg(程序名称为 MyPrintPreview ),

在主对话框上放一按钮,(标题:打印预览,ID:IDC_BTN_PREVIEW),
用类向导增加其BN_CLICKED的消息响应函数OnButtonPreview生成打印预览界面
 
void CMyPrintPreviewDlg : :OnButtonPreview() 
{
    CSevFrame * pf = new CSevFrame( this); //CSevFrame稍候介绍 
}
 
2、增加新类:
用ClassWizard新建CSevFrame类(基类CFrameWnd),  功能上相当于文档/视图的应用程序的框架窗口类
用ClassWizard新建CSevView类(基类CScrollView),功能上相当于文档/视图的应用程序的视图类
增加CSevPreviewView类((此类后面已经给出)基类CPreviewView(我就没找到这个类),注意在头其定义头文件中加入包含afxpriv.h),用于打印预览界面的视图类。
 
3、对新生成的各类修改如下:
 
CSevFrame类:
 
①增加公有数据成员
    CMyPrintPreviewDlg* m_pOldWnd;//用于保存主对话框对象;
    CSevView* m_pView;             //用于保存视图类对象;
由于存在CMyPrintPreviewDlg类和CSevView类,所以要包含两个头文件.
# include "CMyPrintPreviewDlg.h"
# include "CSevView.h"
 
②重载构造函数,保存对主对话框对象指针,创建窗口
//头文件声明
CSevFrame(CMyPrintPreviewDlg * pOld);

//cpp文件定义
CSevFrame : :CSevFrame(CMyPrintPreviewDlg * pOld)
{
    m_pOldWnd = pOld;
     if( !Create(NULL, "打印预览", WS_OVERLAPPEDWINDOW |FWS_ADDTOTITLE,CRect( 200, 200, 500, 500)))
        TRACE0( "Failed to create view window\n");
}
 
③修改析构函数,让主对话框显示
CSevFrame : : ~CSevFrame()
{
    m_pOldWnd - >ShowWindow(SW_SHOW);
}
 
④用ClassWizard增加WM_CREATE消息处理函数,
关联CSevView视图对象;
调用其OnFilePrintPreview函数进行打印预览(若要直接打印,可直接向其发送消息);隐藏主对话框。
此项照着copy就好了.嘿嘿
int CSevFrame : :OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
     if (CFrameWnd : :OnCreate(lpCreateStruct) == - 1)
         return - 1;

    CCreateContext context;
    context.m_pNewViewClass = RUNTIME_CLASS(CSevView);
    context.m_pCurrentFrame = this;
    context.m_pCurrentDoc = NULL;
    context.m_pLastView = NULL;
    m_pView = STATIC_DOWNCAST(CSevView, CreateView( &context)); 
     if(m_pView != NULL)
    {
        m_pView - >ShowWindow(SW_SHOW);
        SetActiveView(m_pView);
    }
    SetIcon(m_pOldWnd - >GetIcon(FALSE),FALSE);
    SetIcon(m_pOldWnd - >GetIcon(TRUE),TRUE);
    ShowWindow(SW_MAXIMIZE);
    CWinApp *pApp =AfxGetApp();
    pApp - >m_pMainWnd = this;
    m_pView - >OnFilePrintPreview();
     //m_pView->SendMessage(WM_COMMAND, ID_FILE_PRINT);//直接打印
    m_pOldWnd - >ShowWindow(SW_HIDE);
     return 0;
}
 
修改CSevView类
 
①修改构造函数:将坐标射模式置为缺省模式。
CSevView : :CSevView()

    m_nMapMode = MM_TEXT;
}
 
②增加消息映射实现打印。
    ON_COMMAND(ID_FILE_PRINT,CView : :OnFilePrint)
 
③重载虚函数OnPreparePrinting,调用DoPreparePrinting生成用于打印或打印预览的设备描述表。
BOOL CSevView : :OnPreparePrinting(CPrintInfo * pInfo) 
{
     return DoPreparePrinting(pInfo);
}
 
④增加公有函数OnFilePrintPreview,调用DoPrintPreview实现打印预览,
该函数需要传入四个参数:
  1打印预览工具条资源ID,
  2执行打印及打印预览的视图对象指针,
  3打印预览界面视图类的CRuntimeClass指针,
  4打印预览状态类CPrintPreviewState对象指针。
void CSevView : :OnFilePrintPreview( )
{
    CPrintPreviewState * pState = new CPrintPreviewState;
    pState - >lpfnCloseProc =_AfxMyPreviewCloseProc; //设置打印预览窗口关闭时的调用函数;
     if( !DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,RUNTIME_CLASS(CSevPreviewView), pState))
    {
        TRACE0( "Error: DoPrintPreview failed.\n");
        AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
         delete pState;
    }
}
 
⑤在Myview.cpp文件中增加全局函数,_AfxMyPreviewCloseProc,当单击打印预览窗口关闭按钮时被调用。
//头文件声明
BOOL CALLBACK _AfxMyPreviewCloseProc(CFrameWnd * pFrameWnd);

//cpp文件定义
BOOL CALLBACK _AfxMyPreviewCloseProc(CFrameWnd * pFrameWnd)
{
    ASSERT_VALID(pFrameWnd);
    CSevPreviewView * pView = (CSevPreviewView *) pFrameWnd - >GetDlgItem(AFX_IDW_PANE_FIRST);
    ASSERT_KINDOF(CPreviewView, pView);
    pView - >OnPreviewClose();
     return FALSE;
}

4、修改CSevPreviewView类,增加工具栏按钮的消息响应函数OnPreviewClose(),OnPreviewPrint(),
由于此类较简单,列出该类代码如下(注意粗体部分):
 
SevPreviewView.h
// SevPreviewView.h: interface for the CSevPreviewView class.
//

# if ! defined(AFX_MYPREVIEWVIEW_H__0AE8B670_B1AE_11DA_812E_00E04C39032F__INCLUDED_)
# define AFX_MYPREVIEWVIEW_H__0AE8B670_B1AE_11DA_812E_00E04C39032F__INCLUDED_
# if _MSC_VER > 1000
# pragma once
# endif // _MSC_VER > 1000
# include <afxpriv.h >
class CSevPreviewView : public CPreviewView  
{
DECLARE_DYNCREATE(CSevPreviewView)
   public :
    afx_msg void OnPreviewClose();

   protected :
    CSevPreviewView();
     virtual ~CSevPreviewView();
     void OnDraw(CDC * pDC);
     void CSevPreviewView : :OnEndPrintPreview(CDC * pDC, CPrintInfo * pInfo, POINT point, CPreviewView * pView);
    afx_msg void OnPreviewPrint();
DECLARE_MESSAGE_MAP()
};
# endif // !defined(AFX_MYPREVIEWVIEW_H__0AE8B670_B1AE_11DA_812E_00E04C39032F__INCLUDED_)
 
SevPreviewView.cpp
// SevPreviewView.cpp: implementation of the CSevPreviewView class.
# include "stdafx.h"
#include "Sev
PrintPreviewDlg.h"
# include "SevPreviewView.h"
#include "Sev
Frame.h"
# ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
# define new DEBUG_NEW
# endif
//
IMPLEMENT_DYNCREATE(CSevPreviewView, CPreviewView)
CSevPreviewView : :CSevPreviewView()
{
}
CSevPreviewView : : ~CSevPreviewView()
{
}
BEGIN_MESSAGE_MAP(CSevPreviewView, CPreviewView)
    ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnPreviewClose)
    ON_COMMAND(AFX_ID_PREVIEW_PRINT, OnPreviewPrint)
END_MESSAGE_MAP()
void CSevPreviewView : :OnDraw(CDC *pDC)
{
    CPreviewView : :OnDraw(pDC);
    m_pToolBar - >PostMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE); // 控制条的命令状态更新
}
void CSevPreviewView : :OnEndPrintPreview(CDC * pDC, CPrintInfo * pInfo, POINT point, CPreviewView * pView) 
{
    CPreviewView : :OnEndPrintPreview(pDC, pInfo, point, pView);
}
void CSevPreviewView : :OnPreviewClose()
{
    CSevFrame * pf =(CSevFrame *) : :AfxGetMainWnd();
    CWinApp *pApp =AfxGetApp();      
    pApp - >m_pMainWnd =pf - >m_pOldWnd;//原文漏掉几个字母
    pf - >DestroyWindow();
}
void CSevPreviewView : :OnPreviewPrint()
{
    m_pPrintView - >SendMessage(WM_COMMAND, ID_FILE_PRINT);
}
 
至此,基于对话框应用程序的具有打印及打印预览的基本支持已经生成,完全由新生成的三个类来支持。
正如上一部分介绍的,可以在CSevView类中定义CView类的几个在打印过程中虚拟函数
CView::OnPreparePrinting,
CView::OnBeginPrinting,
CView::OnPrepareDC,
CView::OnPrint,
CView::OnEndPrinting,
来定制其打印或打印预览的内容。
也可以将实现打印或打印预览新增的三个类,生成MFC扩展动态链接库,以方便加入到程序中。

下面加入一个通过上述方式实现的程序和一个功能完善的程序.


MFC的视图打印/预览功能基于CView::OnFilePrint和CView::OnFilePrintPreview这两个函数 如果要对用户自定义对话框(模态)内的子视图(以下简称A视图)进行打印,直接调用A视图的CView::OnFilePrint即可,弹出的“选择打印机”对话框同样也是模态对话框,覆盖在用户对话框上。 如果要对用户对话框内的A视图进行预览,直接调用A视图的CView::OnFilePrintPreview后,预览视图(MFC CPreviewView类实例)内虽然预览正常,但是挡住了用户对话框。由于用户对话框是模态的,导致预览视图上的“打印...”、“上一页”、“下一页”、“放大”、“缩小”、“单页/双页”和“关闭”等按钮均无法响应鼠标点击,处于“假死”状态。 解决方法: 在调用A视图的CView::OnFilePrintPreview之前,先关闭用户对话框(CDialog::OnCancel),由于这时已不存在用于预览的A视图,再重新创建一个相同的视图(以下简称B视图),以B视图来启动OnFilePrintPreview进行预览。 MFC视图预览的原理是:以主框架窗口(CMainFrame)作为预览框架,隐藏原先的子视图(用CMainFrame::GetActiveView得到的那个,以下简称C视图),用CPreviewView类替换,同时创建包含“打印...”、“放大”、“关闭”等按钮的工具栏(CDialogBar类),最后将CPreviewView::m_pPreviewDC作为C视图OnDraw的CDC*参数传入,这样,虽然调用的是C视图的OnDraw函数,实际上却显示在了CPreviewView视图中,起到了“预览”的效果。在点击预览框架工具栏上的“打印...”按钮后, MFC体系将向原先的主框架(本例中和预览框架是同一个,都是CMainFrame)发送ID_FILE_PRINT的WM_COMMAND消息。在缺省的配置中,这将启动C视图的OnFilePrint,从而在打印机上打出C视图的内容。 在本例中,为了打印B视图,需要在CMainFrame中处理WM_COMMAND/ID_FILE_PRINT,加入额外的条件,来判断对按钮“打印...”的点击是来自B还是C视图的预览框架。在本例中用了一个变量CMainFrame::m_nPrintFrom。根据其取值(0或者1),分别启动B或者C视图的OnFilePrint。 使用方法: 程序示例在VC++2010上通过。主菜单项“打印预览测试”下,有两个子菜单项,“对话框用户视图的打印预览”用于B视图(画出一个圆);“单文档视图的打印预览”用于C视图(画出一个正方形),等同于“文件”主菜单项下的“打印预览(V)”。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值