VC Web打印解决方案概述
2016-01-08 13:17
405 查看
VC Web打印解决方案概述
Web打印在实际应用中比较广泛,比如公司报表、银行回单等。如果是直接在网页中嵌入打印比较简单,直接使用JS的打印功能。但如果生成的报表以html的形式存储于本地呢?下面基于vc++介绍两种方法。通过COM组建调用IE浏览器的打印功能
大致流程如下:Created with Raphaël 2.1.0start//定义变量 IOleCommandTarget *pCommandTarget; IDispatch *pDispatch; IWebBrowser2 *pWebBrowser2; IUnknown *pUnknown;初始化COM:CoInitialize(NULL)调用CoCreateInstance(/****/)创建浏览器对象,并获取IUnknown接口指针调用IUnknown的方法QueryInterface()获取IWebBrowser2接口调用IWebBrowser2的Navigate方法导航到指定URL调用IWebBrowser2的get_Document()方法加载文档,输出IDispatch接口调用IDispatch的QueryInterface()方法获取IOleCommandTarget接口调用IOleCommandTarget的Exec()方法执行打印detect print statu print over?释放COM资源,然后调用CoUninitialize();Endyesno
这种方式有很大的缺点,可控性差,有时可能默认浏览器不是IE、或者浏览器注册表被修改都会导致创建IE COM组件失败。并且每次打印都要去创建一次COM组件,打印完成再释放浏览器。如果通过增加COM引用计数的方式,经测试加载文档会失败,可能没有更深入的了解,微软官网上也是看得一知半解。
使用MFC的CHtmlView的打印功能
使用CHtmlView有两种方式,建工程时可以选择文档\视图结构,也可以选择基于对话框模式。如果选择文档\视图模式,后续选择工程视图的基类为CHtmlView,这样编译器会自动添加消息映射。.1 使用文档/视图方式
使用这种方式相对简单,只需添加如下消息映射:BEGIN_MESSAGE_MAP(CWebBrowserDocumentView, CHtmlView) //{{AFX_MSG_MAP(CWebBrowserDocumentView) ON_COMMAND(ID_FILE_PRINT, OnFilePrint) ON_WM_DESTROY() //}}AFX_MSG_MAP // Standard printing commands //ON_COMMAND(ID_FILE_PRINT, CHtmlView::OnFilePrint) END_MESSAGE_MAP()
如果消息映射为 ON_COMMAND(ID_FILE_PRINT, CHtmlView::OnFilePrint),点击打印的时候会弹出打印设置对话框(CPrintDialog),为了屏蔽对话框,需自己实现打印,所以添加ON_COMMAND(ID_FILE_PRINT, OnFilePrint)消息映射,然后在类里面添加消息响应方法:afx_msg void OnFilePrint()。
那么要怎么实现OnFilePrint()方法呢?
在vc编译器的安装目录:“VC98\MFC\SRC”下有个VIEWHTML.cpp文件,打开可以看到打印的实现方法,如下:
void CHtmlView::OnFilePrint() { // get the HTMLDocument if (m_pBrowserApp != NULL) { LPOLECOMMANDTARGET lpTarget = NULL; LPDISPATCH lpDisp = GetHtmlDocument(); if (lpDisp != NULL) { // the control will handle all printing UI if (SUCCEEDED(lpDisp->QueryInterface(IID_IOleCommandTarget, (LPVOID*) &lpTarget))) { lpTarget->Exec(NULL, OLECMDID_PRINT, 0, NULL, NULL); lpTarget->Release(); } lpDisp->Release(); } } }
所以,直接拿过来用就可以了。下面看一下IOleCommandTarget接口的Exec方法:
HRESULT Exec( [in] const GUID *pguidCmdGroup, [in] DWORD nCmdID, [in] DWORD nCmdexecopt, [in] VARIANT *pvaIn, [in, out] VARIANT *pvaOut );
参数:
pguidCmdGroup【in】 唯一的指令集标志,为NULL表示标准指令集,这里可以是CGID_MSHTML
nCmdID 【in】 要执行的指令ID,必须在pguidCmdGroup指定的指令集中
nCmdexecopt 【in】 指定如何执行该指令。可能取值为OLECMDEXECOPT和OLECMDID_WINDOWSTATE_FLAG的枚举值
pvaIn 【in】指向包含输入参数的VARIANTARG结构体指针,可以为NULL
pvaOut 【in out】 输出参数VARIANTARG结构体指针,可以为NULL
注意:关键是nCmdID、nCmdexecopt的值,打印的时候为了不弹出打印设置对话框,nCmdexecopt的值为OLECMDEXECOPT_DONTPROMPTUSER.
.2 基于对话框模式
基于对话框方式实际上也是间接使用文档\视图结构。首先定义一个框架类,如下:class CWebPrintFrame : public CFrameWnd { public: CWebPrintFrame(); DECLARE_DYNCREATE(CWebPrintFrame) public: virtual ~CWebPrintFrame(); public: void OnFilePrint(char* url); CWebPrintView *m_pView; LPCTSTR m_szUrl; BOOL m_bLoaded; // Generated message map functions protected: //{{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnClose(); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
实现如下:
////////////////////////////////////////////////////////////////////// // CWebPrintFrame ////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CWebPrintFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CWebPrintFrame, CFrameWnd) //{{AFX_MSG_MAP(CWebPrintFrame) ON_WM_CREATE() ON_WM_CLOSE() //}}AFX_MSG_MAP END_MESSAGE_MAP() CWebPrintFrame::CWebPrintFrame() { if (!Create(NULL,"PrintPreview",WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CRect(200,0,1224,800))) { TRACE0("Failed to create View Window!"); } } CWebPrintFrame::~CWebPrintFrame() { } int CWebPrintFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) { return -1; } CCreateContext contex; contex.m_pNewViewClass = RUNTIME_CLASS(CWebPrintView); contex.m_pCurrentFrame = this; contex.m_pCurrentDoc = NULL; contex.m_pLastView = NULL; m_pView = STATIC_DOWNCAST(CWebPrintView,CreateView(&contex)); m_bLoaded = FALSE; if (m_pView != NULL) { m_pView->ShowWindow(SW_SHOW); SetActiveView(m_pView); //SetLandscapeMode(DMORIENT_PORTRAIT); } ShowWindow(SW_SHOW); CWinApp *pApp = AfxGetApp(); pApp->m_pMainWnd = this; return 0; } void CWebPrintFrame::OnFilePrint(char* url) { this->m_szUrl = url; m_pView->Navigate2(m_szUrl,NULL,NULL); //等待加载完成 MSG msg; while(!m_bLoaded) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } //直接打印 m_pView->SendMessage(WM_COMMAND,ID_FILE_PRINT); } void CWebPrintFrame::OnClose() { CWebPrintFrame *pFrame = (CWebPrintFrame *)::AfxGetMainWnd(); CWinApp *pApp = AfxGetApp(); //pApp->m_pMainWnd = pFrame->m_pDlg; pFrame->DestroyWindow(); //CFrameWnd::OnClose(); }
然后定义视图类,如下:
class CWebPrintView : public CHtmlView { public: CWebPrintView(); DECLARE_DYNCREATE(CWebPrintView) // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CWebPrintView) public: virtual void OnDraw(CDC* pDC); // overridden to draw this view virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual void OnInitialUpdate(); // called first time after construct //}}AFX_VIRTUAL // Implementation public: virtual ~CWebPrintView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Generated message map functions protected: //{{AFX_MSG(CWebPrintView) afx_msg void OnFilePrint(); afx_msg void OnDocumentComplete(LPCTSTR lpszURL); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
实现如下:
////////////////////////////////////////////////////////////////////// // CWebPrintView ////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CWebPrintView, CHtmlView) BEGIN_MESSAGE_MAP(CWebPrintView, CHtmlView) //{{AFX_MSG_MAP(CWebPrintView) ON_COMMAND(ID_FILE_PRINT, OnFilePrint) ON_COMMAND(READYSTATE_COMPLETE,OnDocumentComplete) //}}AFX_MSG_MAP // Standard printing commands END_MESSAGE_MAP() CWebPrintView::CWebPrintView() { } CWebPrintView::~CWebPrintView() { } BOOL CWebPrintView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CHtmlView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CWebPrintView drawing void CWebPrintView::OnDraw(CDC* pDC) { ASSERT_VALID(pDC); } void CWebPrintView::OnInitialUpdate() { CHtmlView::OnInitialUpdate(); } ///////////////////////////////////////////////////////////////////////////// // CWebPrintView diagnostics #ifdef _DEBUG void CWebPrintView::AssertValid() const { CHtmlView::AssertValid(); } void CWebPrintView::Dump(CDumpContext& dc) const { CHtmlView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CPrintView message handlers void CWebPrintView::OnFilePrint() { LPOLECOMMANDTARGET lpTarget = NULL; LPDISPATCH lpDisp = GetHtmlDocument(); if (lpDisp != NULL) { // the control will handle all printing UI if (SUCCEEDED(lpDisp->QueryInterface(IID_IOleCommandTarget, (LPVOID*) &lpTarget))) { lpTarget->Exec(NULL, OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); lpTarget->Release(); } lpDisp->Release(); } } void CWebPrintView::OnDocumentComplete(LPCTSTR lpszURL) { CHtmlView::OnDocumentComplete(lpszURL); CWebPrintFrame* pFrame= (CWebPrintFrame* )AfxGetMainWnd(); pFrame->m_bLoaded = TRUE; }
调用方式如下:
CWebPrintFrame* pFrame = new CWebPrintFrame(); pFrame->OnFilePrint(szURL);
相关文章推荐
- $POST 、$HTTP_RAW_POST_DATA、php://input三者之间的差别
- 牛客网-《剑指offer》-跳台阶
- UITextFiled的输入框改成一条下划线
- Missing Ranges
- php获取当前日期时间 & php日期转时间戳,指定日期转换成时间戳
- UINvigation,导航条
- 文件版本和产品版本的区别
- 页面分页显示功能
- php7 编译安装 apache
- delphi IOS 通知 TNotification
- com.microsoft.sqlserver.jdbc.SQLServerException: '@P0' 附近有语法错误。
- listView下拉时,顶部会有一条渐变的线
- 泛学web测试
- mod_callcenter坐席不显示来电号码
- 牛客网-《剑指offer》-斐波那契数列
- PHP实现同服务器多个二级域名共享 SESSion
- 消灭Bug!十款免费移动应用测试框架推荐
- [示例]NSDictionary-按value排序数组中的字典并输出(描述器)
- php validator classes
- java垃圾回收机制