VC++对话框程序打印及打印预览的实现

本文详细介绍了如何在对话框程序中实现打印预览功能,包括新建三个类:CMyView、CMyFrame 和 CMyPreviewView。通过自定义画图函数和调整设备上下文设置,实现预览和打印效果。此外,文章还展示了如何响应按钮事件触发打印预览,并通过主对话框和框架窗口的交互来完成整个流程。

原文来自:V​C​+​+​对​话​框​程​序​打​印​及​打​印​预​览​的​实​现

现在我直接进入代码,原理自己看原文,我这里不多介绍了。

一共需要新建3个类,CMyView,CMyFrame,CMyPreviewView


CMyView

MyView.h

class CMyView : public CScrollView
{
	DECLARE_DYNCREATE(CMyView)

protected:
	CMyView();           // 动态创建所使用的受保护的构造函数
	virtual ~CMyView();

public:
#ifdef _DEBUG
	virtual void AssertValid() const;
#ifndef _WIN32_WCE
	virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
	virtual void OnDraw(CDC* pDC);      // 重写以绘制该视图
	virtual void OnInitialUpdate();     // 构造后的第一次

	DECLARE_MESSAGE_MAP()
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
public:
	virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);
	void OnFilePrintPreview(void);
	void DrawPic(CDC* pdc);//自定义画图函数
};

MyView.cpp

CMyView::CMyView()
{
	m_nMapMode = MM_TEXT;
}

void CMyView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
	// TODO: 在此添加专用代码和/或调用基类
	pDC->SetMapMode(MM_ANISOTROPIC); 
	//转换坐标映射方式 
	CSize   size=CSize(800,   560); 
	pDC->SetWindowExt(size);             //确定窗口大小 
	//得到实际设备每逻辑英寸的像素数量 
	int   xLogPixPerInch=pDC->GetDeviceCaps(LOGPIXELSX);   
	int   yLogPixPerInch=pDC->GetDeviceCaps(LOGPIXELSY); 
	//得到设备坐标和逻辑坐标的比例 
	long   xExt=(long)size.cx*xLogPixPerInch/96; 
	long   yExt=(long)size.cy*yLogPixPerInch/96; 
	pDC->SetViewportExt(xExt,yExt);
	CScrollView::OnPrepareDC(pDC, pInfo);
}

void CMyView::OnFilePrintPreview(void)
{
	CPrintPreviewState* pState = new CPrintPreviewState;
	pState->lpfnCloseProc =_AfxMyPreviewCloseProc;//设置打印预览窗口关闭时的调用函数;
	if(!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,RUNTIME_CLASS(CMyPreviewView), pState))
	{
		TRACE0("Error: DoPrintPreview failed.\n");
		AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
		delete pState;
	}
}

BOOL CALLBACK _AfxMyPreviewCloseProc(CFrameWnd* pFrameWnd)
{
	ASSERT_VALID(pFrameWnd);
	CMyPreviewView* pView = (CMyPreviewView*) pFrameWnd->GetDlgItem(AFX_IDW_PANE_FIRST);
	ASSERT_KINDOF(CPreviewView, pView);
	pView->OnPreviewClose();
	return FALSE;
}

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// TODO:  调用 DoPreparePrinting 以调用“打印”对话框

// 	return CScrollView::OnPreparePrinting(pInfo);
	return DoPreparePrinting(pInfo);
}
这里需要注意,调用的是 DoPreparePrinting(pInfo); 不是 OnPreparePrinting(pInfo);


最后在OnDraw中调用自己的画图函数

void CMyView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: 在此添加绘制代码

	DrawPic(pDC);
}

CMyFrame

MyFrame.h

#include "PdfDemoDlg.h"

// CMyFrame 框架
#include "MyView.h"
class CMyFrame : public CFrameWnd
{
	DECLARE_DYNCREATE(CMyFrame)
public:
	CMyFrame();           // 动态创建所使用的受保护的构造函数
	virtual ~CMyFrame();

	CMyFrame(CPdfDemoDlg* pWnd);

	CPdfDemoDlg *m_pOldWnd;//主对话框
	CMyView* m_pView;

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};


MyFrame.cpp

int CMyFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	CCreateContext context;	
	context.m_pNewViewClass = RUNTIME_CLASS(CMyView);	
	context.m_pCurrentFrame = this;
	context.m_pCurrentDoc = NULL;
	context.m_pLastView = NULL;	
	m_pView = STATIC_DOWNCAST(CMyView, 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;
}

CMyFrame::CMyFrame(CPdfDemoDlg* pWnd)
{
	m_pOldWnd= pWnd;
	CString str;
	str=_T("Print Preview");
	if(!Create(NULL,str,WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE,CRect(200,200,500,500)))
		TRACE0("Failed to create view window\n");
}

CMyFrame::~CMyFrame()
{
	m_pOldWnd->ShowWindow(SW_SHOW);
}


CMyPreviewView

MyPreviewView.h

#include <afxpriv.h>
// CMyPreviewView 视图

class CMyPreviewView : public CPreviewView
{
	DECLARE_DYNCREATE(CMyPreviewView)

protected:
	CMyPreviewView();           // 动态创建所使用的受保护的构造函数
	virtual ~CMyPreviewView();

public:
#ifdef _DEBUG
	virtual void AssertValid() const;
#ifndef _WIN32_WCE
	virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPreviewClose();
	afx_msg void OnPreviewPrint();
	virtual void OnDraw(CDC* /*pDC*/);
};
这里需要注意,VS2010自动继承的是CPreviewViewEx,需要自己修改。CPreviewViewEx不适用于该方式。


MyPreviewView.cpp

void CMyPreviewView::OnPreviewPrint()
{
	// TODO: 在此添加命令处理程序代码
	m_pPrintView->SendMessage(WM_COMMAND, ID_FILE_PRINT);
}

void CMyPreviewView::OnPreviewClose()
{
	// TODO: 在此添加命令处理程序代码
	CMyFrame* pf=(CMyFrame*)::AfxGetMainWnd();
	CWinApp *pApp=AfxGetApp();      
	pApp->m_pMainWnd=pf->m_pOldWnd;
	pf->DestroyWindow();
}

void CMyPreviewView::OnDraw(CDC* pDC)
{
CPreviewView::OnDraw(pDC);	
// TODO: 在此添加专用代码和/或调用基类
	m_pToolBar->PostMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE);// 控制条的命令状态更新
}

BEGIN_MESSAGE_MAP(CMyPreviewView, CPreviewView)
	ON_COMMAND(AFX_ID_PREVIEW_CLOSE, &CMyPreviewView::OnPreviewClose)
	ON_COMMAND(AFX_ID_PREVIEW_PRINT, &CMyPreviewView::OnPreviewPrint)
END_MESSAGE_MAP()


最后响应按钮调用

#include "MyFrame.h"
void CPdfDemoDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	this->SendMessage(WM_WSPPRINTPREVIEW,NULL,NULL);
}

主对话框中响应自定义消息WM_WSPPRINTPREVIEW

#define WM_WSPPRINTPREVIEW  WM_USER+13

LRESULT CPdfDemoDlg::OnWSPPrintPreview(WPARAM wParam, LPARAM lParam)
{
	CMyFrame* pFrame = new CMyFrame(this);
	return 0;
}



VC6和VS2010都是同样使用,只不过VS2010中自动继承的是CPreviewViewEx,需要自己修改。CPreviewViewEx不适用于该方式。





评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值