网上搜索了几天关于对话框的打印问题.大部分都抄来抄去的...
实现对话框所见即所得模式,其实就是在对话框上绘制...一般还是使用打印预览然后打印的功能吧.
发现这篇不错,,,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稍候介绍
}
{
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"
# 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(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);
}
{
m_pOldWnd - >ShowWindow(SW_SHOW);
}
④用ClassWizard增加WM_CREATE消息处理函数,
关联CSevView视图对象; 调用其OnFilePrintPreview函数进行打印预览(若要直接打印,可直接向其发送消息);隐藏主对话框。
此项照着copy就好了.嘿嘿
关联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;
}
{
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;
}
{
m_nMapMode = MM_TEXT;
}
②增加消息映射实现打印。
ON_COMMAND(ID_FILE_PRINT,CView
:
:OnFilePrint)
③重载虚函数OnPreparePrinting,调用DoPreparePrinting生成用于打印或打印预览的设备描述表。
BOOL CSevView
:
:OnPreparePrinting(CPrintInfo
* pInfo)
{
return DoPreparePrinting(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;
}
}
{
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;
}
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_)
//
# 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 "SevPrintPreviewDlg.h"
# include "SevPreviewView.h"
#include "SevFrame.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);
}
# include "stdafx.h"
#include "SevPrintPreviewDlg.h"
# include "SevPreviewView.h"
#include "SevFrame.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扩展动态链接库,以方便加入到程序中。
下面加入一个通过上述方式实现的程序和一个功能完善的程序.