由于很多情况下无法利用文档/视图框架,需要自定义打印,一般方法有用API的,比较麻烦些。本文的方法主要基于MFC,在对话框内自定义了打印,调试运行良好,先将实现方法列出。
定义三个类CWooPrintFrmWnd,CWooPrintView,CWooPreviewView。代码如下,重点是CWooPreviewView中要定义好装订线距离,页数,页头,页尾等参数,以灵活实现多页打印、多字体图元打印。
#if !defined(AFX_WOOPRINTFRMWND_H__61B64D36_91A4_4E28_9F58_E3BC1A6E9DD5__INCLUDED_)
#define AFX_WOOPRINTFRMWND_H__61B64D36_91A4_4E28_9F58_E3BC1A6E9DD5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// WooPrintFrmWnd.h : header file
//
#include "WooPrintView.h"
/////////////////////////////////////////////////////////////////////////////
// CWooPrintFrmWnd frame
class CWooPrintFrmWnd : public CFrameWnd
{
DECLARE_DYNCREATE(CWooPrintFrmWnd)
protected:
// Attributes
public:
BOOL m_bDirectPrint;
CWnd* m_pOldWnd;
CWooPrintView* m_pView;//用于保存视图类对象
CWooPrintFrmWnd(); // protected constructor used by dynamic creation
CWooPrintFrmWnd(BOOL bPrint); // protected constructor used by dynamic creation
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWooPrintFrmWnd)
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CWooPrintFrmWnd();
// Generated message map functions
//{{AFX_MSG(CWooPrintFrmWnd)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WOOPRINTFRMWND_H__61B64D36_91A4_4E28_9F58_E3BC1A6E9DD5__INCLUDED_)
#if !defined(AFX_WOOPRINTVIEW_H__7718474D_1BE9_4300_8F69_D0A5B84C1555__INCLUDED_)
#define AFX_WOOPRINTVIEW_H__7718474D_1BE9_4300_8F69_D0A5B84C1555__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// WooPrintView.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CWooPrintView view
class CWooPrintView : public CView
{
protected:
CWooPrintView(); // protected constructor used by dynamic creation
DECLARE_DYNCREATE(CWooPrintView)
UINT m_nPageNums;
UINT m_BindingLineGap;//装订线距离
UINT m_FootHeight;
UINT m_HeaderHeight;
CFont m_FontHeader;
CFont m_FontFooter;
// Attributes
public:
void OnFilePrintPreview();
// Operations
public:
virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo);
void PrintPageFooter(CDC* pDC,CPrintInfo* pInfo);
void PrintPageHeader(CDC* pDC,CPrintInfo* pInfo);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWooPrintView)
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CWooPrintView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Generated message map functions
//{{AFX_MSG(CWooPrintView)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WOOPRINTVIEW_H__7718474D_1BE9_4300_8F69_D0A5B84C1555__INCLUDED_)
#if !defined(AFX_WOOPREVIEWVIEW_H__7EF15__INCLUDED_)
#define AFX_WOOPREVIEWVIEW_H__7EF15__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "afxpriv.h"
/////////////////////////////////////////////////////////////////////////////
// CWooPreviewView view
class CWooPreviewView : public CPreviewView
{
protected:
CWooPreviewView();
DECLARE_DYNCREATE(CWooPreviewView)
public:
afx_msg void OnPreviewClose();
afx_msg void OnPreviewPrint();
// Generated message map functions
protected:
//{{AFX_MSG(CWooPreviewView)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
#endif // !defined(AFX_WOOPREVIEWVIEW_H__7EF15__INCLUDED_)
添加实现代码
// WooPrintFrmWnd.cpp : implementation file
//
#include "stdafx.h"
#include "WooPrintFrmWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWooPrintFrmWnd
IMPLEMENT_DYNCREATE(CWooPrintFrmWnd, CFrameWnd)
CWooPrintFrmWnd::CWooPrintFrmWnd()
{
}
CWooPrintFrmWnd::CWooPrintFrmWnd(BOOL bPrint)
{
m_bDirectPrint = bPrint;
m_pOldWnd = AfxGetApp()->m_pMainWnd;
if(!Create(NULL, "****程序→打印预览", WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE,CRect(200,200,600,600)))
TRACE0("Failed to create view window!/n");
}
CWooPrintFrmWnd::~CWooPrintFrmWnd()
{
m_pOldWnd->ShowWindow(SW_SHOW);
}
BEGIN_MESSAGE_MAP(CWooPrintFrmWnd, CFrameWnd)
//{{AFX_MSG_MAP(CWooPrintFrmWnd)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWooPrintFrmWnd message handlers
BOOL CWooPrintFrmWnd::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &= (~WS_THICKFRAME);
cs.style &= (~WS_MAXIMIZEBOX);
return CFrameWnd::PreCreateWindow(cs);
}
int CWooPrintFrmWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CWooPrintView);
context.m_pCurrentFrame = this;
context.m_pCurrentDoc = NULL;
context.m_pLastView = NULL;
m_pView = STATIC_DOWNCAST(CWooPrintView, 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);
if (!m_bDirectPrint)//预览
{
ShowWindow(SW_MAXIMIZE);
m_pOldWnd->ShowWindow(SW_HIDE);
AfxGetApp()->m_pMainWnd=this;
m_pView->PostMessage(WM_COMMAND, ID_FILE_PRINT_PREVIEW);
}
else//直接打印
{
ShowWindow(SW_HIDE);
m_pView->SendMessage(WM_COMMAND, ID_FILE_PRINT);
}
return 0;
}
// WooPrintView.cpp : implementation file
//
#include "stdafx.h"
#include "WooPrintView.h"
#include "WooPrintFrmWnd.h"
#include "WooPrintDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BOOL CALLBACK _AfxMyPreviewCloseProc(CFrameWnd* pFrameWnd)//很关键,删除以上打印类资源
{
ASSERT_VALID(pFrameWnd);
CWooPreviewView* pView = (CWooPreviewView*) pFrameWnd->GetDlgItem(AFX_IDW_PANE_FIRST);
ASSERT_KINDOF(CPreviewView, pView);
pView->OnPreviewClose();
return FALSE;
};
/////////////////////////////////////////////////////////////////////////////
// CWooPreviewView
IMPLEMENT_DYNCREATE(CWooPreviewView, CPreviewView)
CWooPreviewView::CWooPreviewView()
{
}
BEGIN_MESSAGE_MAP(CWooPreviewView, CPreviewView)
//{{AFX_MSG_MAP(CWooPreviewView)
ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnPreviewClose)
ON_COMMAND(AFX_ID_PREVIEW_PRINT, OnPreviewPrint)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWooPreviewView message handlers
void CWooPreviewView::OnPreviewClose()//关闭预览窗口
{
CWooPrintFrmWnd* pFrame = (CWooPrintFrmWnd*) ::AfxGetMainWnd();
AfxGetApp()->m_pMainWnd = pFrame->m_pOldWnd;
pFrame->DestroyWindow();
}
void CWooPreviewView::OnPreviewPrint()//从预览窗口直接打印
{
m_pPrintView->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);//ID_FILE_PRINT_DIRECT
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CWooPrintView
IMPLEMENT_DYNCREATE(CWooPrintView, CView)
CWooPrintView::CWooPrintView()
{
m_BindingLineGap = 100;
m_HeaderHeight = 120;
m_FootHeight = 100;
m_FontHeader.CreateFont(.............);
m_FontFooter.CreateFont(..............);
}
CWooPrintView::~CWooPrintView()
{
if (&m_FontHeader)
m_FontHeader.DeleteObject();
if (&m_FontFooter)
m_FontFooter.DeleteObject();
}
BEGIN_MESSAGE_MAP(CWooPrintView, CView)
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
//{{AFX_MSG_MAP(CWooPrintView)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWooPrintView drawing
/////////////////////////////////////////////////////////////////////////////
// CWooPrintView diagnostics
#ifdef _DEBUG
void CWooPrintView::AssertValid() const
{
CView::AssertValid();
}
void CWooPrintView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif //_DEBUG
void CWooPrintView::OnDraw(CDC* pDC)
{
}
/////////////////////////////////////////////////////////////////////////////
// CWooPrintView message handlers
BOOL CWooPrintView::OnPreparePrinting(CPrintInfo* pInfo)
{
int nLines = .......................;//行数
m_nPageNums = (nLines%20==0? nLines/20 : (1+nLines/20) );//页数,每页约20行
m_nPageNums = (m_nPageNums==0? 1:m_nPageNums);
pInfo->SetMinPage(1);
pInfo->SetMaxPage(m_nPageNums);
return DoPreparePrinting(pInfo);
}
void CWooPrintView::OnFilePrintPreview( )
{
CPrintPreviewState* pState = new CPrintPreviewState;
pState->lpfnCloseProc =_AfxMyPreviewCloseProc;//设置打印预览窗口关闭时的调用函数;
if(!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this, RUNTIME_CLASS(CWooPreviewView), pState))
{
TRACE0("Error: DoPrintPreview failed./n");
AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
delete pState;
}
}
void CWooPrintView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CView::OnPrepareDC(pDC, pInfo);
if (pDC->IsPrinting() && pInfo!=NULL)
{
pDC->SetMapMode(MM_LOMETRIC);
CSize size;
size.cx = abs(pInfo->m_rectDraw.Width());
size.cy = abs(pInfo->m_rectDraw.Height());
pDC->SetWindowExt(size);//设备实际的实际逻辑大小
//得到实际设备每逻辑英寸的像素数量
int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);
int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);
//得到设备坐标大小//确定视口大小
long xExt = (long)size.cx*xLogPixPerInch/254 ;
long yExt = (long)-size.cy*yLogPixPerInch/254 ;
pDC->SetViewportExt((int)xExt, (int)yExt);
}
}
void CWooPrintView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
if (pInfo->m_nCurPage > m_nPageNums)
return;
PrintPageHeader(pDC, pInfo);
.........................
for (UINT i=1; i<=m_nPageNums; i++)
{
CString str = "..........";
if (pInfo->m_nCurPage == i)
pDC->TextOut(............);
}
.....................................
PrintPageFooter(pDC, pInfo);
}
void CWooPrintView::PrintPageHeader(CDC* pDC, CPrintInfo* pInfo)
{
}
void CWooPrintView::PrintPageFooter(CDC* pDC,CPrintInfo* pInfo)
{
}
最后,使用时
void CWooDlg::OnOK() //直接打印
{
OnSelPrintType();
CWooPrintFrmWnd* WooPrintFrmWnd = new CWooPrintFrmWnd(1);
}
void CWooDlg::OnPreviewPrint() //预览
{
OnSelPrintType();
CWooPrintFrmWnd* WooPrintFrmWnd = new CWooPrintFrmWnd(0);
}