使用MFC实现打印功能

评价:
0
(0用户)

使用MFC实现打印功能

如果程序不是文档视图结构的,我们要使用MFC来进行打印,可以通过建立一个虚拟的文档视图结构来进行打印。MFC的打印的强大功能是在CView里提供的,而CView类的对象是一个子窗口,它必须是某一个框架窗口的子窗口,而在对话框程序中,我们只需要打印,而不需要显示这个框架窗口和视图。我们以按下按钮”打印”来执行打印程序,例如按钮为ID为IDC_PNT,消息相应函数为OnPnt(),即:

ON_BN_CLICKED(IDC_PNT, OnPnt);

  需要在OnPnt中建立一个框架窗口,同时使某个CView类的对象为该窗口的子窗口。因此需要建立两个类,一个为框架窗口类CPrintFrame,另一个为CPrintView。在新建一个用于打印的虚拟框架窗口时,需要将执行打印的对话框的指针传给框架窗口,这以便在对话框来响应WM_BEGIN_PRINTING和WM_END_PRINTING消息,使对话框可以完成打印的初始化和释放操作。在执行一个打印任务时,将打印的流程交给CView来进行,而这个CView是虚拟的,只是用来完成打印一些操作,其它内容则完全不负责处理,而当要执行CView::OnPrint时,则又将处理的具体内容传回到对话框,而对话框则只需要响应WM_MY_PRINT消息即可:

pFrame->m_pCallerDlg->SendMessage(WM_MY_PRINT,(WPARAM) pDC, (LPARAM) pInfo);

  使打印的具体处理又传回到对话框中,使开发人员根据具体的需要写WM_MY_PRINT的处理函数就可以实现打印,而CView::OnPrint(CDC* pDC, CPrintInfo* pInfo)的参数也从WM_MY_PRINT的消息参数传出来,在用户的对话框程序中,需要写的代码就很少,主要有以下几个步骤:

1. 建立一个CPrintFrame的对象,设该对象的指针为pFrame,并将对话框的指针传给该对象的m_pCallerDlg,即pFrame->m_pCallerDlg = this;

2. 调用对象的Create函数创建框架窗口;例如pFrame->Create(NULL,”频谱打印”,WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));

3. 如果要执行打印,则调用pFrame->m_pView->OnMyPrint();

4. 如果要执行打印预览,则调用:

pFrame->m_pView->OnMyPrintPreview();

例如:

void CDlgPrintDlg::OnPrint() //执行打印功能

{

CPrintFrame *pFrame = new CPrintFrame;

pFrame->m_pCallerDlg = this;

pFrame->Create(NULL,”Curve

Print”,WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));

pFrame->m_pView->OnMyPrint();

}

void CDlgPrintDlg::OnPrintPreview() //执行打印预览功能

{

CPrintFrame *pFrame = new CPrintFrame;

pFrame->m_pCallerDlg = this;

pFrame->Create(NULL,”Curve Print

Preview”,WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));

pFrame->m_pView->OnMyPrintPreview();

}

5. 在对话框中响应 WM_BEGIN_PRINTING, WM_END_PRINTING,WM_MY_PRINT消息,分别完成打印的初始化、释放和具体的打印操作

  框架实现了对打印的一些底层支持,直接的打印机制是通过函数StartDoc和EndDoc()来实现的。应用程序要使用打印机时,它首先使用CreateDC或PrintDlg来获取指向打印机设备环境的一个句柄,这就使得打印机设备驱动程序库模块被加载到内存(如果还没有加载到内存的话),并进行初始化。然后,程序调用StartDoc函数,通知一个新文档开始了。StartDoc函数是由GDI模块来处理的。GDI模块调用打印机设备驱动程序中的control函数告诉打印机准备打印。

     打印一个文档的过程以StartDoc调用开始,以EndDoc调用结束。调用StartPage来开始一页,调用EndPage来结束该页。

   

   下面这段代码在对话框中实现了对打印的支持。

   /*

   GetPrinterDC 获取设备环境的句柄。

   HDC GetPrinterDC()const;

   返回值:如果成功则返回一个打印机设备环境的句柄;否则返回null.

   说明:如果CPrintDialog构造函数的参数bPrintSetupOnly是FALSE(表明显示的是Print对话框,则GetPrinterDC返回一个打印机设备环境句柄。当你使用完这个设备环境时,你必须调用Windows DeleteDC函数来删除它。)

   */

   /*

   {

     long cbSize,

     CString lpszDocName,

     CString lpszOutput

   } DOCINFO;

   对文档进行定义的一个结构。

   cbSize:结构的大小

   lpszDocName:文档的名字

   lpszOutput:输出文档的名字

   */

   /*

   StartDoc:开始新的打印作业

   CDC::StartDoc

   int StartDoc(LPDOCINFO lpDocInfo);

   返回值:如果出错,例如存储空间不足或指定端口无效,则返回-1否则返回正值。

   参数: lpDocInfo: DOCINFO结构的指针。该结构包含了文档文件和输出文件的名字。

   说明:通知设备的驱动程序开始一个新的打印作业,其后所有的StartPage和EndPage调用处于假

   脱机状态,直到EndDoc调用出现。这确保了长于一页的文档不被其它作业中断。   

   */

   /*

   EndDoc  结束由StartDoc成员函数启动的打印作业。

   CDC::EndDoc

   int EndDoc();

   返回值:如果成功,则返回值大于零或等于零,出错则返回值小于零。下面列出了一般的错误

   类型:

   SP_ERROR:一般错误。

   SP_OUTOFDISK:假脱机所需的磁盘空间不足,没有其它可用的磁盘空间。

   SP_OUTOFMEMORY:假脱机所需的内存不足。

   SP_USERABORT: 用户在打印管理中中止作业。

   

   说明:中止由StartDoc成员函数调用的打印作业。在成功完成打印作业后应立即调用。

   如果应用遇到打印错误或取消的打印操作,决不可用EndDoc或AbortDoc去中止

   操作,GDI在返回错误值之前自动中止操作。   

   */

   /*

   StartPage:通知设备的驱动程序开始新页。

   CDC::StartPage

   int StartPage

   说明:调用该成员函数使用打印机驱动程序做好准备接收数据。在StartPage和EndPage之间,

   ResetDC成员函数不起作用。

   */

   /*

   EndPage:通知打印机驱动程序打印页结束。

   CDC::EndPage

   int EndPage()

   返回值:如果成功,则返回大于或等于零的值,如果失败则返回如下错误类型:

   SP_ERROR:一般错误

   SP_APPABORT: 作业终止

   SP_USERABORT:用户在打印管理中中止作业。

   SP_OUTOFDISK:假脱机所需的磁盘空间不足。

   SP_OUTOFMEMORY:假脱机所需的内存不足。

   

   说明:通知设备已经写完一页。该成员函数通常用在打印机驱动程序开始新的一页。

   */

   /*

   AbortDoc:终止当前打印任务,擦除自上次调用StartDoc成员函数以业写入设备的任何内容。

   CDC::AbortDoc

   int AbortDoc();

   返回值:如果成功,则返回大于或等于零的值,如果出现错误,则为负值。与EndPage和EndDoc返回的错误类型值一样。

   说明:终止当前打印任务,并擦除自上次StartDoc以后写入设备的任何任务。

   */

   

   /*

   CPrintInfo没有基类。

   CPrintInfo存储有关一次打印或打印预览的信息。每次选择Print或PrintPreview命令,框架就会创建一个CPrintInfo对象。并在命令完成时删除此对象。

   

   CPrintInfo包含打印时的一般信息,例如:要打印页的范围,打印机的状态,当前正在打印的页这些信息存放在CPintInfo的对象中;此对象还包括在CPrint对话框中输入的值。

   

   在打印期间,一个CPrintInfo对象在框架和视图类之间传递,并且用于两者之间交换信息。例如:

   框架通过对CPrintInfo类的m_nCurPgae成员赋值,来通知视图类要打印文档的哪一页,视图类检索此值,并执行指定页的实际打印。

     另一个例子就是文档的长度到打印的时候也不知道多少页。视图类每打印一页都要检测是否到了文档的末尾。当到达文档的末尾时,视图类将CPrintInfo的m_bContinuePrinting成员设置为FALSE,通知框架停止打印循环。

   */

   /*

   Attach:把Windows设备上下文句柄附加在CDC对象上。

   CDC::Attach

   BOOL Attach(HDC hDC);

   返回值:如果成功,返回非零值,否则为0

   参数: hDC:Windows设备上下文。

   说明:使用这个函数把hDC附加到CDC对象上。

   */

   /*

   Detach:从CDC对象中分离出Windows设备上下文。

   CDC::Detach

   HDC Detach()

   返回值:Windows设备上下文句柄。

   说明:调用该函数将m_hDC从CDC对象中分离出来。并将m_hDC与m_bAttribDC设备为NULL。

   */

   void CPrintProj::Print()

   {

    CDC dc;

    CPrintDialog printDlg(FALSE);

       //利用CPrintDialog生成打印机设备环境

    if(printDlg.DoModual() == IDCANCEL) //让用户选择打印纸张等

       return;

    dc.Attach(printDlg.GetPrinterDC());//让Handle连接到dc上.

    dc.m_bPrinting = TRUE;

    CString strTitle;

    strTitle.LoadString(AFX_IDS_APP_TITLE);

    DOCINFO di; //DOCINFO中有相关的打印信息

    ::ZeroMemory(&di,sizeof(DOCINFO));

    di.cbSize = sizeof(DOCINFO);

    di.lpszDocName = strTitle; //设置标题

    BOOL bPrintingOK = dc.StartDoc(&di); //开始打印

    CPrintInfo Info;

    Info.m_rectDraw.SetRect(0,0,dc.GetDeviceCaps(HORZRES),dc.GetDeviceCaps(VERTRES)); //设置范围.

       OnBeginPrinting(&dc,&Info); //调用你自定义的打印功能.

    fo(UINT page = Info.GetMinPage();page < Info.GetMaxPage() && bPrintOK;page++)

    {

     Info.m_nCurPage = page;

     OnPrint(&dc,&Info); //调用你的”Print page”函数

     bPrintOK = dc.EndPage() > 0; //结束页

    }

    OnEndPrinting(&dc,&Info);//结束打印.

    if(bPrintingOK)

     dc.EndDoc();

    else

     dc.AbortDoc();

    dc.Detach();

   }

   

   说明:其实在Windows环境中是设备无关的.只要有了DC,就可以使用各种GDI函数,而不需要理会是在屏幕或是在打印机上绘图.

来自百度文库

本文出自:https://wenku.baidu.com/view/41b5ab41a8956bec0975e355?fr=sogou&_wkts_=1687580026610

注册并通过认证的用户才可以进行评价!

admin:系统自动奖励,+10,  

发表评论