数据表中数据如下:
code     year    类别    库存 .......010000   2000     aa    2000
010000   2000     bb    6300
010000   2000     cc    10500
010000   2000     dd    10020
010000   2000     ee    100020000   2001     aa    4123
020000   2001     bb    4123
020000   2001     cc    4123
020000   2001     dd    4123
020000   2001     ee    4123
.........我想做成的样式是第一页:
[code]010000   [year]2000
------------------------------
    类别          库存
    aa            2000   
    bb            6300
    cc            10500
    dd            10020
    ee            100第二页
[code]020000   [year]2001
------------------------------
    类别          库存
    aa            4123
    bb            4123
    cc            4123
    dd            4123
    ee            4123依次类推,请问应该怎么做?请多提好的方法,谢谢!

解决方案 »

  1.   

    如果是自己画报表,实现这样的还是很容易的。
    你可以在OnPrint中进行年份的判断,如果是下一年的,换页
      

  2.   

    如果是自己画报表,实现这样的还是很容易的。
    你可以在OnPrint中进行年份的判断,如果是下一年的,换页
      

  3.   

    VC数据库编程中的打印控制 
    李佑民  --------------------------------------------------------------------------------
     
      VC数据库编程中的打印控制比较复杂,但它也给程序员最大的灵活性,而这种灵活性正是我们需要的。因为各行业、部门的报表一般都不太规整,特别是表头部分,二、三重嵌套的情况很常见。下面我们就开发中碰到的一些问题与同行们探讨。   Document/View框架之外的打印   熟悉VC的程序员都知道Microsoft 的AppWizard生成的应用程序框架中,可以选择免费的打印及打印预览功能,但前提是必须选择Document/View结构。然而我们的数据库应用中一般都不需要一个文档类来保存文档,因为数据库(源)就是我们的文档,数据一般是在一个对话框或视中与用户交互,编辑或修改结果直接通过数据库引擎写回数据库中。我们的程序主框架要么是基于对话框的、要么是基于无文档类的单视(或多视)结构,在这种情况下,AppWizard 在打印控制部分并不能给我们任何帮助,只能自己负责完成打印控制。   总结起来,一次打印操作要遵循以下步骤:   1.得到或生成打印设备场景,可通过显示打印对话框让用户选择打印机与纸张等设置,也可在程序中直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向;   2.开始在该设备场景中的一次打印作业,实际打印报表内容,终止打印作业;   3.清除打印设备场景,完成本次打印操作。   在下面的例子中,我们在一个对话框中让用户选择打印某个报表,没有显示打印设置对话框,而是直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向。之所以这样做是因为各行业、部门的报表格式一般都是至上而下的统一格式。函数DoPreparePrintDC()、DoPrint()和DoClearPrintDC()分别对应上述的三个步骤:   BOOL CMyDialog::DoPreparePrintDC()   // 准备打印场景   {    #define  FONTSIZE 14    // 获取打印机的设备属性    CPrintDialog dlgPrint( FALSE );    // 得到当前系统缺省打印机设置    if(!dlgPrint.GetDefaults()) return FALSE;    LPDEVMODE pDM=dlgPrint.GetDevMode();    if(pDM==NULL) return FALSE;    ::GlobalUnlock(pDM);    // 联结打印DC,m—hDC是定义为HDC m—hDC的类成员变量    m—hDC=dlgPrint.CreatePrinterDC();    // m—DC是定义为CDC m—DC的类成员变量    if(!m—DC.Attach(m—hDC) return FALSE;    // 设置打印标志    m—DC.m—bPrinting=TRUE;    short cxInch=m—DC.GetDeviceCaps(LOGPIXELSX);    short cyInch=m—DC.GetDeviceCaps(LOGPIXELSY);    // 建立打印字体,m—fontPrint 是定义为CFont m_fontPrint的类成员变量    if(!m—fontPrint.CreateFont(MulDiv(FONTSIZE, -cyInch, 72),0,0,0, FW—NORMAL,0,0,0, GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH|FF—DONTCARE, HFONTNAME)    return FALSE;    return TRUE;}   void CDlgDataPrint::DoClearPrintDC()   // 清除打印场景   { m—fontPrint.DeleteObject();    m—DC.Detach();    ::DeleteDC( m—hDC );}   void CDlgDataPrint::DoPrint()   // 实际打印输出   { if(DoPreparePrintDC()==FALSE) return;    // 开始一次打印作业    CString str;    str.LoadString(AFX—IDS—APP—TITLE);    DOCINFO di;    ::ZeroMemory (&di, sizeof (DOCINFO));    di.cbSize=sizeof (DOCINFO);    di.lpszDocName=str;    m—DC.StartDoc(&di);    m—DC.StartPage();    // 将打印字体选进设备场景    CFont* pOldFont=m—DC.SelectObject(&m—fontPrint);    // 输出报表,建议用CDC::DrawText()函数便于控制打印范围    ...    // 终止打印作业    m—DC.EndPage();    m—DC.EndDoc();    m—DC.SelectObject(pOldFont);    // 清除打印场景    DoClearPrintDC();}   表格问题   对格式固定或表头、表体比较复杂的情况,特别是有嵌套表格的情况下,我们认为先将打印结果以文本形式写入一临时文件,然后再对文件进行打印输出的方法会使事情简单一些。因为这样在程序中就可以只关心数据(表体)的输出,而表头则可以固定格式存入数据库。   但是,我们在对文本形式的报表进行打印输出时却发现一个有趣的现象,有时输出结果的相邻两行表格竖线不能对齐,而有时又可以。原来是 Windows 图形输出的问题,只要我们在建立打印字体时,字体的高度是偶数就可保证竖线对齐,如果是奇数则不能对齐。知道了原因,在建立打印字体时只需加入如下代码即可:   ...   #define  FONTSIZE 14   #define  HFONTNAME ″宋体″   // 建立打印字体,m—fontPrint是定义为CFont m—fontPrint的类成员变量   int nFontHeight=MulDiv(FONTSIZE,-cyInch, 72);   if(nFontHeight % 2) nFontHeight++;   if(!m—fontPrint.CreateFont(nFontHeight, 0, 0, 0, FW—NORMAL, 0, 0,0,GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH | FF—DONTCARE, HFONTNAME))    return FALSE;   ...   还有一点小技巧,输出文本形式的报表时,对报表的横线只需要输出其正常高度的二分之一或三分之一,这样报表看起来更紧凑美观。这也是我们在前面建议用CDC::DrawText()进行绘制输出的原因。  
     直接打印,不需要文档/视  
    闻怡洋 译 [email protected] http://vchelp.163.net  --------------------------------------------------------------------------------
     
    This article was contributed by Chris Maunder. 如果你需要在没有使用文档/视图的应用中使用打印功能(比如说在对话框中)你将无法利用MFC提供的功能,而且对于某些新手来讲有些困难。 下面的的代码可以供你在对话框中如果在DOC/View中一样使用打印功能。你必须定义OnBeginPrinting, OnEndPrinting 和 OnPrint三个函数,其原型和功能与在VIEW中一样。 void CMyDialog::Print() 
    {
    CDC dc;
    CPrintDialog printDlg(FALSE);
    //利用CPrintDialog 生成打印机设备环境
    if (printDlg.DoModal() == IDCANCEL) // Get printer settings from user 让用户选择打印纸张等
    return;dc.Attach(printDlg.GetPrinterDC()); // Attach a printer DC 让HANDLE连接到dc上
    dc.m_bPrinting = TRUE;CString strTitle; // Get the application title ?
    strTitle.LoadString(AFX_IDS_APP_TITLE);DOCINFO di; // Initialise print document details DOCINFO中有相关的打印信息
    ::ZeroMemory (&di, sizeof (DOCINFO));
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = strTitle;//设置标题BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job 开始打印// Get the printing extents and store in the m_rectDraw field of a 
    // CPrintInfo object
    CPrintInfo Info;//
    Info.m_rectDraw.SetRect(0,0, 
    dc.GetDeviceCaps(HORZRES), 
    dc.GetDeviceCaps(VERTRES));//设置范围OnBeginPrinting(&dc, &Info); // 调用你自己定义的初始化功能
    for (UINT page = Info.GetMinPage(); page<Info.GetMaxPage()&& bPrintOK;page++)
    {Info.m_nCurPage = page;
    OnPrint(&dc, &Info); // Call your "Print page" function
    bPrintingOK = (dc.EndPage() > 0); // end page
    }
    OnEndPrinting(&dc, &Info); // 结束打印if (bPrintingOK)
    dc.EndDoc(); // end a print job
    else
    dc.AbortDoc(); // abort job.dc.Detach(); // detach the printer DC
    } [译者:其实在WINDOWS环境中是设备无关的。只要有了DC,你可以使用各种GDI函数,而不需要理会是在屏幕或是在打印机上绘图。在Windows3.X一般使用CreateDC创建打印环境,在WIN32下好象并不是很兼容,使用CPrintDialog产生打印DC是个不错的方法。你只要看看MFC的源代码就能搞清楚PrintDialog是怎么产生DC的了。 蓝色的代码是讲诉如何初始化打印的参数,而其他的参数你可以在OnBeginPrint中进行设置] 
     
     
      

  4.   

    VC数据库编程中的打印控制 
    李佑民  --------------------------------------------------------------------------------
     
      VC数据库编程中的打印控制比较复杂,但它也给程序员最大的灵活性,而这种灵活性正是我们需要的。因为各行业、部门的报表一般都不太规整,特别是表头部分,二、三重嵌套的情况很常见。下面我们就开发中碰到的一些问题与同行们探讨。   Document/View框架之外的打印   熟悉VC的程序员都知道Microsoft 的AppWizard生成的应用程序框架中,可以选择免费的打印及打印预览功能,但前提是必须选择Document/View结构。然而我们的数据库应用中一般都不需要一个文档类来保存文档,因为数据库(源)就是我们的文档,数据一般是在一个对话框或视中与用户交互,编辑或修改结果直接通过数据库引擎写回数据库中。我们的程序主框架要么是基于对话框的、要么是基于无文档类的单视(或多视)结构,在这种情况下,AppWizard 在打印控制部分并不能给我们任何帮助,只能自己负责完成打印控制。   总结起来,一次打印操作要遵循以下步骤:   1.得到或生成打印设备场景,可通过显示打印对话框让用户选择打印机与纸张等设置,也可在程序中直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向;   2.开始在该设备场景中的一次打印作业,实际打印报表内容,终止打印作业;   3.清除打印设备场景,完成本次打印操作。   在下面的例子中,我们在一个对话框中让用户选择打印某个报表,没有显示打印设置对话框,而是直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向。之所以这样做是因为各行业、部门的报表格式一般都是至上而下的统一格式。函数DoPreparePrintDC()、DoPrint()和DoClearPrintDC()分别对应上述的三个步骤:   BOOL CMyDialog::DoPreparePrintDC()   // 准备打印场景   {    #define  FONTSIZE 14    // 获取打印机的设备属性    CPrintDialog dlgPrint( FALSE );    // 得到当前系统缺省打印机设置    if(!dlgPrint.GetDefaults()) return FALSE;    LPDEVMODE pDM=dlgPrint.GetDevMode();    if(pDM==NULL) return FALSE;    ::GlobalUnlock(pDM);    // 联结打印DC,m—hDC是定义为HDC m—hDC的类成员变量    m—hDC=dlgPrint.CreatePrinterDC();    // m—DC是定义为CDC m—DC的类成员变量    if(!m—DC.Attach(m—hDC) return FALSE;    // 设置打印标志    m—DC.m—bPrinting=TRUE;    short cxInch=m—DC.GetDeviceCaps(LOGPIXELSX);    short cyInch=m—DC.GetDeviceCaps(LOGPIXELSY);    // 建立打印字体,m—fontPrint 是定义为CFont m_fontPrint的类成员变量    if(!m—fontPrint.CreateFont(MulDiv(FONTSIZE, -cyInch, 72),0,0,0, FW—NORMAL,0,0,0, GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH|FF—DONTCARE, HFONTNAME)    return FALSE;    return TRUE;}   void CDlgDataPrint::DoClearPrintDC()   // 清除打印场景   { m—fontPrint.DeleteObject();    m—DC.Detach();    ::DeleteDC( m—hDC );}   void CDlgDataPrint::DoPrint()   // 实际打印输出   { if(DoPreparePrintDC()==FALSE) return;    // 开始一次打印作业    CString str;    str.LoadString(AFX—IDS—APP—TITLE);    DOCINFO di;    ::ZeroMemory (&di, sizeof (DOCINFO));    di.cbSize=sizeof (DOCINFO);    di.lpszDocName=str;    m—DC.StartDoc(&di);    m—DC.StartPage();    // 将打印字体选进设备场景    CFont* pOldFont=m—DC.SelectObject(&m—fontPrint);    // 输出报表,建议用CDC::DrawText()函数便于控制打印范围    ...    // 终止打印作业    m—DC.EndPage();    m—DC.EndDoc();    m—DC.SelectObject(pOldFont);    // 清除打印场景    DoClearPrintDC();}   表格问题   对格式固定或表头、表体比较复杂的情况,特别是有嵌套表格的情况下,我们认为先将打印结果以文本形式写入一临时文件,然后再对文件进行打印输出的方法会使事情简单一些。因为这样在程序中就可以只关心数据(表体)的输出,而表头则可以固定格式存入数据库。   但是,我们在对文本形式的报表进行打印输出时却发现一个有趣的现象,有时输出结果的相邻两行表格竖线不能对齐,而有时又可以。原来是 Windows 图形输出的问题,只要我们在建立打印字体时,字体的高度是偶数就可保证竖线对齐,如果是奇数则不能对齐。知道了原因,在建立打印字体时只需加入如下代码即可:   ...   #define  FONTSIZE 14   #define  HFONTNAME ″宋体″   // 建立打印字体,m—fontPrint是定义为CFont m—fontPrint的类成员变量   int nFontHeight=MulDiv(FONTSIZE,-cyInch, 72);   if(nFontHeight % 2) nFontHeight++;   if(!m—fontPrint.CreateFont(nFontHeight, 0, 0, 0, FW—NORMAL, 0, 0,0,GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH | FF—DONTCARE, HFONTNAME))    return FALSE;   ...   还有一点小技巧,输出文本形式的报表时,对报表的横线只需要输出其正常高度的二分之一或三分之一,这样报表看起来更紧凑美观。这也是我们在前面建议用CDC::DrawText()进行绘制输出的原因。  
     直接打印,不需要文档/视  
    闻怡洋 译 [email protected] http://vchelp.163.net  --------------------------------------------------------------------------------
     
    This article was contributed by Chris Maunder. 如果你需要在没有使用文档/视图的应用中使用打印功能(比如说在对话框中)你将无法利用MFC提供的功能,而且对于某些新手来讲有些困难。 下面的的代码可以供你在对话框中如果在DOC/View中一样使用打印功能。你必须定义OnBeginPrinting, OnEndPrinting 和 OnPrint三个函数,其原型和功能与在VIEW中一样。 void CMyDialog::Print() 
    {
    CDC dc;
    CPrintDialog printDlg(FALSE);
    //利用CPrintDialog 生成打印机设备环境
    if (printDlg.DoModal() == IDCANCEL) // Get printer settings from user 让用户选择打印纸张等
    return;dc.Attach(printDlg.GetPrinterDC()); // Attach a printer DC 让HANDLE连接到dc上
    dc.m_bPrinting = TRUE;CString strTitle; // Get the application title ?
    strTitle.LoadString(AFX_IDS_APP_TITLE);DOCINFO di; // Initialise print document details DOCINFO中有相关的打印信息
    ::ZeroMemory (&di, sizeof (DOCINFO));
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = strTitle;//设置标题BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job 开始打印// Get the printing extents and store in the m_rectDraw field of a 
    // CPrintInfo object
    CPrintInfo Info;//
    Info.m_rectDraw.SetRect(0,0, 
    dc.GetDeviceCaps(HORZRES), 
    dc.GetDeviceCaps(VERTRES));//设置范围OnBeginPrinting(&dc, &Info); // 调用你自己定义的初始化功能
    for (UINT page = Info.GetMinPage(); page<Info.GetMaxPage()&& bPrintOK;page++)
    {Info.m_nCurPage = page;
    OnPrint(&dc, &Info); // Call your "Print page" function
    bPrintingOK = (dc.EndPage() > 0); // end page
    }
    OnEndPrinting(&dc, &Info); // 结束打印if (bPrintingOK)
    dc.EndDoc(); // end a print job
    else
    dc.AbortDoc(); // abort job.dc.Detach(); // detach the printer DC
    } [译者:其实在WINDOWS环境中是设备无关的。只要有了DC,你可以使用各种GDI函数,而不需要理会是在屏幕或是在打印机上绘图。在Windows3.X一般使用CreateDC创建打印环境,在WIN32下好象并不是很兼容,使用CPrintDialog产生打印DC是个不错的方法。你只要看看MFC的源代码就能搞清楚PrintDialog是怎么产生DC的了。 蓝色的代码是讲诉如何初始化打印的参数,而其他的参数你可以在OnBeginPrint中进行设置] 
     
     
      

  5.   

    VC数据库编程中的打印控制 
    李佑民  --------------------------------------------------------------------------------
     
      VC数据库编程中的打印控制比较复杂,但它也给程序员最大的灵活性,而这种灵活性正是我们需要的。因为各行业、部门的报表一般都不太规整,特别是表头部分,二、三重嵌套的情况很常见。下面我们就开发中碰到的一些问题与同行们探讨。   Document/View框架之外的打印   熟悉VC的程序员都知道Microsoft 的AppWizard生成的应用程序框架中,可以选择免费的打印及打印预览功能,但前提是必须选择Document/View结构。然而我们的数据库应用中一般都不需要一个文档类来保存文档,因为数据库(源)就是我们的文档,数据一般是在一个对话框或视中与用户交互,编辑或修改结果直接通过数据库引擎写回数据库中。我们的程序主框架要么是基于对话框的、要么是基于无文档类的单视(或多视)结构,在这种情况下,AppWizard 在打印控制部分并不能给我们任何帮助,只能自己负责完成打印控制。   总结起来,一次打印操作要遵循以下步骤:   1.得到或生成打印设备场景,可通过显示打印对话框让用户选择打印机与纸张等设置,也可在程序中直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向;   2.开始在该设备场景中的一次打印作业,实际打印报表内容,终止打印作业;   3.清除打印设备场景,完成本次打印操作。   在下面的例子中,我们在一个对话框中让用户选择打印某个报表,没有显示打印设置对话框,而是直接取系统缺省打印机设置,然后根据报表格式设置纸张大小和打印方向。之所以这样做是因为各行业、部门的报表格式一般都是至上而下的统一格式。函数DoPreparePrintDC()、DoPrint()和DoClearPrintDC()分别对应上述的三个步骤:   BOOL CMyDialog::DoPreparePrintDC()   // 准备打印场景   {    #define  FONTSIZE 14    // 获取打印机的设备属性    CPrintDialog dlgPrint( FALSE );    // 得到当前系统缺省打印机设置    if(!dlgPrint.GetDefaults()) return FALSE;    LPDEVMODE pDM=dlgPrint.GetDevMode();    if(pDM==NULL) return FALSE;    ::GlobalUnlock(pDM);    // 联结打印DC,m—hDC是定义为HDC m—hDC的类成员变量    m—hDC=dlgPrint.CreatePrinterDC();    // m—DC是定义为CDC m—DC的类成员变量    if(!m—DC.Attach(m—hDC) return FALSE;    // 设置打印标志    m—DC.m—bPrinting=TRUE;    short cxInch=m—DC.GetDeviceCaps(LOGPIXELSX);    short cyInch=m—DC.GetDeviceCaps(LOGPIXELSY);    // 建立打印字体,m—fontPrint 是定义为CFont m_fontPrint的类成员变量    if(!m—fontPrint.CreateFont(MulDiv(FONTSIZE, -cyInch, 72),0,0,0, FW—NORMAL,0,0,0, GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH|FF—DONTCARE, HFONTNAME)    return FALSE;    return TRUE;}   void CDlgDataPrint::DoClearPrintDC()   // 清除打印场景   { m—fontPrint.DeleteObject();    m—DC.Detach();    ::DeleteDC( m—hDC );}   void CDlgDataPrint::DoPrint()   // 实际打印输出   { if(DoPreparePrintDC()==FALSE) return;    // 开始一次打印作业    CString str;    str.LoadString(AFX—IDS—APP—TITLE);    DOCINFO di;    ::ZeroMemory (&di, sizeof (DOCINFO));    di.cbSize=sizeof (DOCINFO);    di.lpszDocName=str;    m—DC.StartDoc(&di);    m—DC.StartPage();    // 将打印字体选进设备场景    CFont* pOldFont=m—DC.SelectObject(&m—fontPrint);    // 输出报表,建议用CDC::DrawText()函数便于控制打印范围    ...    // 终止打印作业    m—DC.EndPage();    m—DC.EndDoc();    m—DC.SelectObject(pOldFont);    // 清除打印场景    DoClearPrintDC();}   表格问题   对格式固定或表头、表体比较复杂的情况,特别是有嵌套表格的情况下,我们认为先将打印结果以文本形式写入一临时文件,然后再对文件进行打印输出的方法会使事情简单一些。因为这样在程序中就可以只关心数据(表体)的输出,而表头则可以固定格式存入数据库。   但是,我们在对文本形式的报表进行打印输出时却发现一个有趣的现象,有时输出结果的相邻两行表格竖线不能对齐,而有时又可以。原来是 Windows 图形输出的问题,只要我们在建立打印字体时,字体的高度是偶数就可保证竖线对齐,如果是奇数则不能对齐。知道了原因,在建立打印字体时只需加入如下代码即可:   ...   #define  FONTSIZE 14   #define  HFONTNAME ″宋体″   // 建立打印字体,m—fontPrint是定义为CFont m—fontPrint的类成员变量   int nFontHeight=MulDiv(FONTSIZE,-cyInch, 72);   if(nFontHeight % 2) nFontHeight++;   if(!m—fontPrint.CreateFont(nFontHeight, 0, 0, 0, FW—NORMAL, 0, 0,0,GB2312—CHARSET, OUT—CHARACTER—PRECIS, CLIP—CHARACTER—PRECIS,DEFAULT—QUALITY, DEFAULT—PITCH | FF—DONTCARE, HFONTNAME))    return FALSE;   ...   还有一点小技巧,输出文本形式的报表时,对报表的横线只需要输出其正常高度的二分之一或三分之一,这样报表看起来更紧凑美观。这也是我们在前面建议用CDC::DrawText()进行绘制输出的原因。  
     直接打印,不需要文档/视  
    闻怡洋 译 [email protected] http://vchelp.163.net  --------------------------------------------------------------------------------
     
    This article was contributed by Chris Maunder. 如果你需要在没有使用文档/视图的应用中使用打印功能(比如说在对话框中)你将无法利用MFC提供的功能,而且对于某些新手来讲有些困难。 下面的的代码可以供你在对话框中如果在DOC/View中一样使用打印功能。你必须定义OnBeginPrinting, OnEndPrinting 和 OnPrint三个函数,其原型和功能与在VIEW中一样。 void CMyDialog::Print() 
    {
    CDC dc;
    CPrintDialog printDlg(FALSE);
    //利用CPrintDialog 生成打印机设备环境
    if (printDlg.DoModal() == IDCANCEL) // Get printer settings from user 让用户选择打印纸张等
    return;dc.Attach(printDlg.GetPrinterDC()); // Attach a printer DC 让HANDLE连接到dc上
    dc.m_bPrinting = TRUE;CString strTitle; // Get the application title ?
    strTitle.LoadString(AFX_IDS_APP_TITLE);DOCINFO di; // Initialise print document details DOCINFO中有相关的打印信息
    ::ZeroMemory (&di, sizeof (DOCINFO));
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = strTitle;//设置标题BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job 开始打印// Get the printing extents and store in the m_rectDraw field of a 
    // CPrintInfo object
    CPrintInfo Info;//
    Info.m_rectDraw.SetRect(0,0, 
    dc.GetDeviceCaps(HORZRES), 
    dc.GetDeviceCaps(VERTRES));//设置范围OnBeginPrinting(&dc, &Info); // 调用你自己定义的初始化功能
    for (UINT page = Info.GetMinPage(); page<Info.GetMaxPage()&& bPrintOK;page++)
    {Info.m_nCurPage = page;
    OnPrint(&dc, &Info); // Call your "Print page" function
    bPrintingOK = (dc.EndPage() > 0); // end page
    }
    OnEndPrinting(&dc, &Info); // 结束打印if (bPrintingOK)
    dc.EndDoc(); // end a print job
    else
    dc.AbortDoc(); // abort job.dc.Detach(); // detach the printer DC
    } [译者:其实在WINDOWS环境中是设备无关的。只要有了DC,你可以使用各种GDI函数,而不需要理会是在屏幕或是在打印机上绘图。在Windows3.X一般使用CreateDC创建打印环境,在WIN32下好象并不是很兼容,使用CPrintDialog产生打印DC是个不错的方法。你只要看看MFC的源代码就能搞清楚PrintDialog是怎么产生DC的了。 蓝色的代码是讲诉如何初始化打印的参数,而其他的参数你可以在OnBeginPrint中进行设置]