Visual C++6.0是开发Windows应用程序的强大工具,但是要通过它实现程序的打印功能,一直是初学者的一个难点,经常有朋友询问如何在VC中实现打印功能,他们往往感到在MFC提供的框架内实现这个问题很复杂,不知道如何下手。本例针对这个问题,介绍一种简单的方法实现文字串的打印功能,读者朋友可以在此基础上稍微改动一下,就可以实现文件、图像的打印功能。

  一、实现方法

  在Windows操作系统下,显示器、打印机和绘图仪都被视为输出设备,正常情况下,系统默认的输出设备是显示器。要使用打印机,首先需要创建一个指向打印机的设备环境句柄,然后通过该句柄调用相关的绘图函数把所需的文字和图形输出至打印机上。当打印结束后,删除这个设备环境句柄即可。

  当Windows系统中安装好打印机后,系统总是自动设置一个打印机为系统的默认打印机,在Windows的启动配置文件Win.ini中的[window]段中列出了带有关键字device的默认打印机。下面是某一机器中Win.ini中的[Windows]字段的内容:

[windows]
load=
run=
NullPort=None
device=HP LaserJet 4050(computer000),HPBFDB1,LPT1

  在上述关键字device后的字符串中,包含了系统中默认打印机的三个重要属性,它们依次是打印机的设备名HP LaserJet 4050(computer000),驱动程序名是HPBFDB1,输出端口为LPT1。

  为了操纵系统默认的打印机,实现程序的打印功能,在程序中可调用API函数GetProfileString()从Win.ini文件中获得device这个设备字符串,该函数的原型为:DWORD GetProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize)。函数中lpAppName参数为所要检索的Win.ini文件中的字段名;lpKeyName为字段中的关键字名;lpDefault为默认的字符串;lpReturnedString为检索到的字符串,如果该函数没有从lpKeyName关键字中检索到相应的字符串,则kpRetrunedString返回默认字符串lpDefault;nSize为返回字符串的长度。

  获取上述字符串后,再使用strtok()函数将该字符串进行分解,获得与打印机相关的三个属性,作为API函数CreateDC()创建打印机设备环境句柄的参数,CreateDC()函数如果调用成功,则为默认打印机创建一个设备环境句柄,否则返回一个空值(NULL)。该函数的原形为:HDC CreateDC(LPCTSTR lpszDriver,LPCTSTR lpszDevice,LPCTSTR lpszOutput,CONST DEVMODE *lpinitData)。该函数的前三个参数恰好对应打印机的三个属性,最后一个参数为初始化打印机驱动程序的数据,一般情况下该参数设置为NULL就可以了。

  在具体打印的过程中,调用int StartDoc( HDC hdc, CONST DOCINFO *lpdi )函数来开始一个打印任务,其中参数lpdi为一个指向DOCINFO结构的指针,该结构如下:

typedef struct { 
 int cbSize; //结构的尺寸大小;
 LPCTSTR lpszDocName; //文档的名字;
 LPCTSTR lpszOutput; //输出文档名,一般情况下为NULL;
 LPCTSTR lpszDatatype;//用来记录打印过程的数据类型,一般情况下为NULL;
 DWORD fwType; //用来支持打印工作的额外

信息,一般情况下为NULL;
} DOCINFO, *LPDOCINFO; 
  开始一个打印任务后,再调用StartPage(hdcprint)函数让打印机走纸,通知打印机有文档将要打印;接下来的工作就是输出数据了,这部分工作对于开发人员来说就象往计算机屏幕上输出文字、图像一样容易,只不过是计算机根据当前的设备环境句柄自动将数据输出到打印机罢了。数据打印完后,需要作一些善后处理工作,使用RestoreDC(hdcprint,-1)函数恢复打印机设备句柄、EndPage(hdcprint)函数让打印机停止打印,最后调用EndDoc(hdcprint)函数结束上述的打印作业。

  二、编程步骤

  1、启动Visual C++6.0,新建一个基于对话框的应用程序Test,在程序的对话框窗体中加入一个按钮(Button),设置这个Button的属性:ID=IDC_PRINT,CAPTION="打印";

  2、使用Class Wizard类向导为该按钮添加一个鼠标单击处理函数OnPrint()

  3、修改TestDlg.cpp文件中的OnPrint()函数;

  4、添加代码,编译运行程序。

==========================================================================================================================

在打印预览对话框类中

  1. extern int nPaperSize_X ;
  2. extern int nPaperSize_Y ;
  3. extern int nOneLines;
  4. extern int nNextLines;
  5. //打印结构
  6. typedef struct
  7. {
  8. int  nMaxLine;   //最大行数
  9. int  nCountPage;   //一共页数
  10. int  nCurPage;   //当前页码
  11. BOOL IsPrint;   //是否打印
  12. HWND hWnd;    //窗口句柄
  13. HWND hListView;   //列表控件句柄
  14. TCHAR szTag[256];   //其它数据
  15. int  nTag;    //其它数据
  16. LPVOID lpVoid;    //其它数据
  17. CGridCtrlEx *pObj;   //区分是月报表还是日报表
  18. }PRNINFO, *PPRNINFO;
  1. //回调函数,设置打印属性
  2. void CPreviewParentDlg::SetCallBackFun( PRINTPREVIEW pFun, PRNINFO &sPrnInfo )
  3. {
  4. memcpy(&m_PrnInfo, &sPrnInfo, sizeof(PRNINFO));
  5. m_pDrawInfoFun = pFun;
  6. m_nCount = m_PrnInfo.nMaxLine;  // 总的行数
  7. m_nCountPage = 1;
  8. int m = m_nCount-m_OneCount;
  9. int n = m/m_NextCount;
  10. m_nCountPage += n;
  11. n = m%m_NextCount;
  12. if(n>0)
  13. m_nCountPage++;   // 页数
  14. m_PrnInfo.nCountPage = m_nCountPage;
  15. sPrnInfo.nCountPage = m_nCountPage;
  16. }
  1. void CPreviewChildDlg::PrintDoc()
  2. {
  3. NotifyDlg Ndlg(_T("决定打印当前报表吗?"), TRUE);
  4. if (Ndlg.DoModal() == IDCANCEL)
  5. return;
  6. PRINTDLG printInfo;
  7. ZeroMemory(&printInfo,sizeof(printInfo));  //清空该结构
  8. printInfo.lStructSize = sizeof(printInfo);
  9. printInfo.hwndOwner = 0;
  10. printInfo.hDevMode = 0;
  11. printInfo.hDevNames = 0;
  12. //这个是关键,PD_RETURNDC 如果不设这个标志,就拿不到hDC了
  13. //            PD_RETURNDEFAULT 这个就是得到默认打印机,不需要弹设置对话框
  14. printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
  15. PrintDlg(&printInfo);//调用API拿出默认打印机
  16. DWORD rst = CommDlgExtendedError();//看看出错没有
  17. if(rst != 0)
  18. {//出错了,清空标志再次调用API,此时就会弹出打印设置对话框供用户选择了
  19. printInfo.Flags = 0;
  20. PrintDlg(&printInfo);
  21. }
  22. HDC printDC=printInfo.hDC; //得到打印DC,输出到打印,
  23. CDC MemDc;
  24. MemDc.Attach(printDC);
  25. if(m_pDrawInfoFun!= NULL)
  26. {
  27. m_PrnInfo.IsPrint = TRUE;  // 用打印机打印
  28. m_PrnInfo.nCurPage = m_CurPage;
  29. m_PrnInfo.nCountPage = m_CountPage;
  30. m_pDrawInfoFun(MemDc, m_PrnInfo);
  31. }
  32. MemDc.DeleteDC();}
  1. //刷新预览区
  2. void CPreviewChildDlg::OnPaint()
  3. {
  4. CPaintDC dc(this); // device context for painting
  5. // TODO: Add your message handler code here
  6. CClientDC dlgDC(this);
  7. SetWindowOrgEx(dlgDC.m_hDC, m_xPt, m_yPt, NULL);
  8. CDC MemDc;
  9. MemDc.CreateCompatibleDC(NULL);
  10. CBitmap cBitmap;
  11. int xP = dlgDC.GetDeviceCaps(LOGPIXELSX);
  12. int yP = dlgDC.GetDeviceCaps(LOGPIXELSY);
  13. DOUBLE xPix = (DOUBLE)xP*10/254;    //每 mm 宽度的像素
  14. DOUBLE yPix = (DOUBLE)yP*10/254;    //每 mm 高度的像素
  15. cBitmap.CreateCompatibleBitmap(&dlgDC, nPaperSize_X*xPix, nPaperSize_Y*yPix);
  16. MemDc.SelectObject(&cBitmap);
  17. if(m_pDrawInfoFun!= NULL)
  18. {
  19. m_PrnInfo.IsPrint = FALSE;  //显示的是 预览窗口
  20. m_PrnInfo.nCurPage = m_CurPage;
  21. m_pDrawInfoFun(MemDc, m_PrnInfo);   //调用回调函数
  22. }
  23. dlgDC.BitBlt(xP/2, yP/2, nPaperSize_X*xPix+xP/2, nPaperSize_Y*yPix+yP/2, &MemDc, 0, 0, SRCCOPY);
  24. MemDc.DeleteDC();
  25. cBitmap.DeleteObject();
  26. // Do not call CDialog::OnPaint() for painting messages
  27. }

=============调用打印功能类

  1. void CAttendReportDlg::PrintData()
  2. {
  3. CGridCtrlEx *pGridCtrl = NULL;
  4. BOOL bDay = FALSE;
  5. if ( ((CButton*)GetDlgItem(IDC_RADIO_DAY))->GetCheck() )
  6. {
  7. pGridCtrl = m_pDayGridCtrl;
  8. bDay = TRUE;
  9. }
  10. else if ( ((CButton*)GetDlgItem(IDC_RADIO_MONTH))->GetCheck() )
  11. {
  12. pGridCtrl = m_pMonGridCtrl;
  13. }
  14. if( pGridCtrl->GetRowCount() <= 1 )    // 没有记录
  15. return;
  16. ///选择打印机对话框
  17. CDC MemDc;
  18. HDC hdcPrint = NULL;
  19. CPrintDialog dlg(FALSE);
  20. if (m_bPrint)  //打印按钮,不弹出选择对话框,获取默认打印设备
  21. {
  22. PRINTDLG printInfo;
  23. ZeroMemory(&printInfo,sizeof(printInfo));  //清空该结构
  24. printInfo.lStructSize = sizeof(printInfo);
  25. printInfo.hwndOwner = 0;
  26. printInfo.hDevMode = 0;
  27. printInfo.hDevNames = 0;
  28. //这个是关键,PD_RETURNDC 如果不设这个标志,就拿不到hDC了
  29. //PD_RETURNDEFAULT 这个就是得到默认打印机,不需要弹出设置对话框
  30. printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
  31. PrintDlg(&printInfo);//调用API拿出默认打印机
  32. DWORD rst = CommDlgExtendedError();//看看出错没有
  33. if(rst != 0)
  34. {//出错了,清空标志再次调用API,此时就会弹出打印设置对话框供用户选择了
  35. printInfo.Flags = 0;
  36. PrintDlg(&printInfo);
  37. }
  38. hdcPrint=printInfo.hDC; //得到打印DC,输出到打印
  39. }
  40. else  //弹出对话框选择打印设备
  41. {
  42. dlg.DoModal();
  43. hdcPrint = dlg.GetPrinterDC();
  44. }
  45. if(hdcPrint == NULL)
  46. {
  47. NotifyDlg Ndlg(_T("打印机初始化失败!"));
  48. Ndlg.DoModal();
  49. return;
  50. }
  51. MemDc.Attach(hdcPrint);
  52. nPaperSize_X = MemDc.GetDeviceCaps(HORZSIZE);    // 纸张宽度
  53. nPaperSize_Y = MemDc.GetDeviceCaps(VERTSIZE);    // 纸张高度
  54. int xP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSX);    //x方向每英寸像素点数
  55. int yP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSY);    //y方向每英寸像素点数
  56. int xPix = (DOUBLE)xP*10/254;   //每 mm 宽度的像素
  57. int yPix = (DOUBLE)yP*10/254;   //每 mm 高度的像素
  58. DOUBLE fAdd = 5*yPix;       //每格递增量
  59. nOneLines = (nPaperSize_Y * 0.85*yPix)/fAdd;
  60. nNextLines = (nPaperSize_Y * 0.85*yPix)/fAdd+1;
  61. PRNINFO PrnInfo = {0};
  62. PrnInfo.hListView = NULL;
  63. PrnInfo.hWnd = this->m_hWnd;
  64. PrnInfo.IsPrint = m_bPrint;
  65. PrnInfo.nCurPage = 1;
  66. PrnInfo.nMaxLine = pGridCtrl->GetRowCount()-1;
  67. PrnInfo.pObj = pGridCtrl;
  68. CPreviewParentDlg DlgPreView;
  69. CPreviewChildDlg DlgChildPreView;
  70. if (bDay)
  71. {
  72. DlgPreView.SetCallBackFun(PrintDayInfo, PrnInfo);  //回调函数,设置打印或预览函数,及纸张排版信息
  73. DlgChildPreView.SetCallBackFun(PrintDayInfo, PrnInfo);
  74. }
  75. else
  76. {
  77. DlgPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
  78. DlgChildPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
  79. }
  80. if (!m_bPrint)
  81. {
  82. DlgPreView.DoModal();
  83. }
  84. else
  85. {
  86. DlgChildPreView.PrintDoc();
  87. }
  88. MemDc.DeleteDC();
  89. }
  90. void CAttendReportDlg::PrintDayInfo( CDC &memDC, PRNINFO PrnInfo )
  91. {
  92. if(memDC.m_hDC == NULL)
  93. return;
  94. int nCurPage = PrnInfo.nCurPage;    //当前页
  95. BOOL IsPrint = PrnInfo.IsPrint;     //是否打印
  96. int nMaxPage = PrnInfo.nCountPage;  //最大页码
  97. HWND hWnd = PrnInfo.hWnd;
  98. CString csLFinality, csRFinality;
  99. CGridCtrlEx *pGridCtrl = PrnInfo.pObj;
  100. CTime time = CTime::GetCurrentTime();
  101. csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
  102. csLFinality = _T("报表日期:") + csLFinality;
  103. csRFinality.Format(_T("第 %i 页/共 %i 页"), nCurPage, nMaxPage);
  104. TCHAR szTitle[] = _T("考 勤 日 报 表");
  105. CRect rc, rt1, rt2, rt3, rt4, rt5, rt6, rt7, rt8, rt9, rt10;
  106. CPen *hPenOld;
  107. CPen cPen;
  108. CFont TitleFont, DetailFont, *oldfont;
  109. //标题字体
  110. TitleFont.CreateFont(-MulDiv(14,memDC.GetDeviceCaps(LOGPIXELSY),72),
  111. 0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
  112. OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
  113. VARIABLE_PITCH|FF_SWISS,_T("黑体"));
  114. //细节字体
  115. DetailFont.CreateFont(-MulDiv(10,memDC.GetDeviceCaps(LOGPIXELSY),92),
  116. 0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
  117. OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
  118. VARIABLE_PITCH|FF_SWISS,_T("宋体"));
  119. //粗笔
  120. cPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
  121. int xP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSX);    //x方向每英寸像素点数
  122. int yP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSY);    //y方向每英寸像素点数
  123. DOUBLE xPix = (DOUBLE)xP*10/254;    //每 mm 宽度的像素
  124. DOUBLE yPix = (DOUBLE)yP*10/254;    //每 mm 高度的像素
  125. DOUBLE fAdd = 5*yPix;       //每格递增量
  126. DOUBLE nTop = 30*yPix;      //第一页最上线
  127. int   iStart = 0;           //从第几行开始读取
  128. DOUBLE nBottom = nTop+nOneLines*fAdd;
  129. if(nCurPage != 1)
  130. nTop = 30*yPix-fAdd;    //非第一页最上线
  131. if(nCurPage == 2)
  132. iStart = nOneLines;
  133. if(nCurPage>2)
  134. iStart = nOneLines+(nCurPage - 2)*nNextLines;
  135. DOUBLE nLeft = 15*xPix;         //最左线
  136. DOUBLE nRight = xPix*(nPaperSize_X-15); //最右线
  137. DOUBLE nItemWide = ((nPaperSize_X-30)/14)*xPix;
  138. DOUBLE nTextAdd = 1.5*xPix;
  139. if(IsPrint)
  140. {
  141. //真正打印部分
  142. static DOCINFO di = {sizeof (DOCINFO),  szTitle} ;
  143. //开始文档打印/////////////////////////////////////////     start print
  144. //////////////////////////////////////////////////////////
  145. if(memDC.StartDoc( &di ) < 0) // startdoc-----enddoc
  146. {
  147. NotifyDlg dlg(_T("连接到打印机化败!"));
  148. dlg.DoModal();
  149. }
  150. else
  151. {
  152. iStart = 0;
  153. nTop = 30*yPix;     //第一页最上线
  154. for(int iTotalPages = 1; iTotalPages<=nMaxPage; iTotalPages++)
  155. {
  156. int nCurPage = iTotalPages;
  157. csRFinality.Format(_T("第 %i 页/共 %i 页"), nCurPage, nMaxPage);
  158. time=CTime::GetCurrentTime();
  159. csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
  160. csLFinality = _T("报表日期:") + csLFinality;
  161. if(nCurPage != 1)
  162. nTop = 30*yPix-fAdd;    //非第一页最上线
  163. if(nCurPage == 2)
  164. iStart = nOneLines;
  165. if(nCurPage>2)
  166. iStart = nOneLines+(nCurPage - 2)*nNextLines;
  167. //开始页
  168. if(memDC.StartPage() < 0)
  169. {
  170. NotifyDlg dlg(_T("打印失败!"));
  171. dlg.DoModal();
  172. memDC.AbortDoc();
  173. return;
  174. }
  175. else
  176. {
  177. //打印
  178. //标题
  179. oldfont = memDC.SelectObject(&TitleFont);
  180. int nItem = nNextLines;
  181. if(nCurPage == 1)
  182. {
  183. nItem = nOneLines;
  184. rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
  185. memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  186. }
  187. //细节
  188. memDC.SelectObject(&DetailFont);
  189. rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
  190. //上横线
  191. memDC.MoveTo(rc.left, rc.top);
  192. memDC.LineTo(rc.right, rc.top);
  193. rt1.SetRect(nLeft, nTop, rc.right -12.4*nItemWide , nTop+fAdd);     //编 号
  194. rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
  195. rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
  196. rt4.SetRect(rt3.right, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom); //班次
  197. rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //时段
  198. rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤时间
  199. rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //迟到(分)
  200. rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
  201. rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //旷工(分)
  202. rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //请假(分)
  203. memDC.DrawText(_T("编 号"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  204. memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  205. memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  206. memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  207. memDC.DrawText(_T("时 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  208. memDC.DrawText(_T("考勤时间"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  209. memDC.DrawText(_T("迟到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  210. memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  211. memDC.DrawText(_T("旷工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  212. memDC.DrawText(_T("请假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  213. memDC.MoveTo(rt1.right, rt1.top);
  214. memDC.LineTo(rt1.right, rt1.bottom);
  215. memDC.MoveTo(rt2.right, rt1.top);
  216. memDC.LineTo(rt2.right, rt1.bottom);
  217. memDC.MoveTo(rt3.right, rt1.top);
  218. memDC.LineTo(rt3.right, rt1.bottom);
  219. memDC.MoveTo(rt4.right, rt1.top);
  220. memDC.LineTo(rt4.right, rt1.bottom);
  221. memDC.MoveTo(rt5.right, rt1.top);
  222. memDC.LineTo(rt5.right, rt1.bottom);
  223. memDC.MoveTo(rt6.right, rt1.top);
  224. memDC.LineTo(rt6.right, rt1.bottom);
  225. memDC.MoveTo(rt7.right, rt1.top);
  226. memDC.LineTo(rt7.right, rt1.bottom);
  227. memDC.MoveTo(rt8.right, rt1.top);
  228. memDC.LineTo(rt8.right, rt1.bottom);
  229. memDC.MoveTo(rt9.right, rt1.top);
  230. memDC.LineTo(rt9.right, rt1.bottom);
  231. memDC.MoveTo(rc.left, rt1.bottom);
  232. memDC.LineTo(rc.right, rt1.bottom);
  233. CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
  234. rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
  235. rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.4*nItemWide, rc.bottom);
  236. rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
  237. rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
  238. rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom);
  239. rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right +1.6*nItemWide, rt1.bottom);
  240. rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
  241. rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
  242. rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
  243. rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
  244. rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
  245. int nCountItem = pGridCtrl->GetRowCount();
  246. for(int i=1;i<nItem; i++)
  247. {
  248. strID = pGridCtrl->GetItemText(i+iStart, 1);
  249. strName = pGridCtrl->GetItemText(i+iStart, 2);
  250. strDate = pGridCtrl->GetItemText(i+iStart, 3);
  251. strSID = pGridCtrl->GetItemText(i+iStart, 4);
  252. strTime = pGridCtrl->GetItemText(i+iStart, 5);
  253. strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
  254. strLate = pGridCtrl->GetItemText(i+iStart, 7);
  255. strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
  256. strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
  257. strLeave = pGridCtrl->GetItemText(i+iStart, 10);
  258. memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  259. memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  260. memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  261. memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  262. memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  263. memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  264. memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  265. memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  266. memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  267. memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  268. //下横线
  269. memDC.MoveTo(rc.left, rc.bottom);
  270. memDC.LineTo(rc.right, rc.bottom);
  271. memDC.MoveTo(rt1.right, rt1.top);
  272. memDC.LineTo(rt1.right, rt1.bottom);
  273. memDC.MoveTo(rt2.right, rt1.top);
  274. memDC.LineTo(rt2.right, rt1.bottom);
  275. memDC.MoveTo(rt3.right, rt1.top);
  276. memDC.LineTo(rt3.right, rt1.bottom);
  277. memDC.MoveTo(rt4.right, rt1.top);
  278. memDC.LineTo(rt4.right, rt1.bottom);
  279. memDC.MoveTo(rt5.right, rt1.top);
  280. memDC.LineTo(rt5.right, rt1.bottom);
  281. memDC.MoveTo(rt6.right, rt1.top);
  282. memDC.LineTo(rt6.right, rt1.bottom);
  283. memDC.MoveTo(rt7.right, rt1.top);
  284. memDC.LineTo(rt7.right, rt1.bottom);
  285. memDC.MoveTo(rt8.right, rt1.top);
  286. memDC.LineTo(rt8.right, rt1.bottom);
  287. memDC.MoveTo(rt9.right, rt1.top);
  288. memDC.LineTo(rt9.right, rt1.bottom);
  289. memDC.MoveTo(rc.left, rt1.bottom);
  290. memDC.LineTo(rc.right, rt1.bottom);
  291. rc.top += fAdd;
  292. rc.bottom += fAdd;
  293. rt1.top = rc.top;
  294. rt1.bottom = rc.bottom;
  295. rt2.top = rt1.top;
  296. rt2.bottom = rt1.bottom;
  297. rt3.top = rt1.top;
  298. rt3.bottom = rt1.bottom;
  299. rt4.top = rt1.top;
  300. rt4.bottom = rt1.bottom;
  301. rt5.top = rt1.top;
  302. rt5.bottom = rt1.bottom;
  303. rt6.top = rt1.top;
  304. rt6.bottom = rt1.bottom;
  305. rt7.top = rt1.top;
  306. rt7.bottom = rt1.bottom;
  307. rt8.top = rt1.top;
  308. rt8.bottom = rt1.bottom;
  309. rt9.top = rt1.top;
  310. rt9.bottom = rt1.bottom;
  311. rt10.top = rt1.top;
  312. rt10.bottom = rt1.bottom;
  313. if((i+iStart+1)>=nCountItem)
  314. break;
  315. }
  316. //结尾
  317. memDC.MoveTo(rc.left, nTop);
  318. memDC.LineTo(rc.left, rc.top);
  319. memDC.MoveTo(rc.right, nTop);
  320. memDC.LineTo(rc.right, rc.top);
  321. memDC.DrawText(csLFinality, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
  322. memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
  323. memDC.EndPage();
  324. memDC.SelectObject(oldfont);
  325. }
  326. }
  327. memDC.EndDoc();
  328. }
  329. }
  330. else
  331. {
  332. ////////////////////打印预览
  333. //边框线
  334. hPenOld = memDC.SelectObject(&cPen);
  335. rc.SetRect(0, 0, nPaperSize_X*xPix, nPaperSize_Y*yPix);
  336. memDC.Rectangle(&rc);
  337. memDC.SelectObject(hPenOld);
  338. //标题
  339. oldfont = memDC.SelectObject(&TitleFont);
  340. int nItem = nNextLines;
  341. if(nCurPage == 1)
  342. {
  343. nItem = nOneLines;
  344. rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
  345. memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  346. }
  347. //细节
  348. memDC.SelectObject(&DetailFont);
  349. rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
  350. //上横线
  351. memDC.MoveTo(rc.left, rc.top);
  352. memDC.LineTo(rc.right, rc.top);
  353. rt1.SetRect(nLeft, nTop, rc.right -12.2*nItemWide, nTop+fAdd);      //编 号
  354. rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
  355. rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
  356. rt4.SetRect(rt3.right, rt1.top, rt3.right + 2*nItemWide, rt1.bottom);   //班次
  357. rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //时段
  358. rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤时间
  359. rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //迟到(分)
  360. rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
  361. rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //旷工(分)
  362. rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //请假(分)
  363. memDC.DrawText(_T("编 号"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  364. memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  365. memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  366. memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  367. memDC.DrawText(_T("时 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  368. memDC.DrawText(_T("考勤时间"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  369. memDC.DrawText(_T("迟到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  370. memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  371. memDC.DrawText(_T("旷工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  372. memDC.DrawText(_T("请假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  373. memDC.MoveTo(rt1.right, rt1.top);
  374. memDC.LineTo(rt1.right, rt1.bottom);
  375. memDC.MoveTo(rt2.right, rt1.top);
  376. memDC.LineTo(rt2.right, rt1.bottom);
  377. memDC.MoveTo(rt3.right, rt1.top);
  378. memDC.LineTo(rt3.right, rt1.bottom);
  379. memDC.MoveTo(rt4.right, rt1.top);
  380. memDC.LineTo(rt4.right, rt1.bottom);
  381. memDC.MoveTo(rt5.right, rt1.top);
  382. memDC.LineTo(rt5.right, rt1.bottom);
  383. memDC.MoveTo(rt6.right, rt1.top);
  384. memDC.LineTo(rt6.right, rt1.bottom);
  385. memDC.MoveTo(rt7.right, rt1.top);
  386. memDC.LineTo(rt7.right, rt1.bottom);
  387. memDC.MoveTo(rt8.right, rt1.top);
  388. memDC.LineTo(rt8.right, rt1.bottom);
  389. memDC.MoveTo(rt9.right, rt1.top);
  390. memDC.LineTo(rt9.right, rt1.bottom);
  391. memDC.MoveTo(rc.left, rt1.bottom);
  392. memDC.LineTo(rc.right, rt1.bottom);
  393. CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
  394. rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
  395. rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.2*nItemWide, rc.bottom);
  396. rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
  397. rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
  398. rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2*nItemWide, rt1.bottom);
  399. rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom);
  400. rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
  401. rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
  402. rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
  403. rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
  404. rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
  405. int nCountItem = pGridCtrl->GetRowCount();
  406. for(int i=1;i<nItem; i++)
  407. {
  408. strID = pGridCtrl->GetItemText(i+iStart, 1);
  409. strName = pGridCtrl->GetItemText(i+iStart, 2);
  410. strDate = pGridCtrl->GetItemText(i+iStart, 3);
  411. strSID = pGridCtrl->GetItemText(i+iStart, 4);
  412. strTime = pGridCtrl->GetItemText(i+iStart, 5);
  413. strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
  414. strLate = pGridCtrl->GetItemText(i+iStart, 7);
  415. strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
  416. strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
  417. strLeave = pGridCtrl->GetItemText(i+iStart, 10);
  418. memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  419. memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  420. memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  421. memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  422. memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  423. memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  424. memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  425. memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  426. memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  427. memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  428. //下横线
  429. memDC.MoveTo(rc.left, rc.bottom);
  430. memDC.LineTo(rc.right, rc.bottom);
  431. memDC.MoveTo(rt1.right, rt1.top);
  432. memDC.LineTo(rt1.right, rt1.bottom);
  433. memDC.MoveTo(rt2.right, rt1.top);
  434. memDC.LineTo(rt2.right, rt1.bottom);
  435. memDC.MoveTo(rt3.right, rt1.top);
  436. memDC.LineTo(rt3.right, rt1.bottom);
  437. memDC.MoveTo(rt4.right, rt1.top);
  438. memDC.LineTo(rt4.right, rt1.bottom);
  439. memDC.MoveTo(rt5.right, rt1.top);
  440. memDC.LineTo(rt5.right, rt1.bottom);
  441. memDC.MoveTo(rt6.right, rt1.top);
  442. memDC.LineTo(rt6.right, rt1.bottom);
  443. memDC.MoveTo(rt7.right, rt1.top);
  444. memDC.LineTo(rt7.right, rt1.bottom);
  445. memDC.MoveTo(rt8.right, rt1.top);
  446. memDC.LineTo(rt8.right, rt1.bottom);
  447. memDC.MoveTo(rt9.right, rt1.top);
  448. memDC.LineTo(rt9.right, rt1.bottom);
  449. memDC.MoveTo(rc.left, rt1.bottom);
  450. memDC.LineTo(rc.right, rt1.bottom);
  451. rc.top += fAdd;
  452. rc.bottom += fAdd;
  453. rt1.top = rc.top;
  454. rt1.bottom = rc.bottom;
  455. rt2.top = rt1.top;
  456. rt2.bottom = rt1.bottom;
  457. rt3.top = rt1.top;
  458. rt3.bottom = rt1.bottom;
  459. rt4.top = rt1.top;
  460. rt4.bottom = rt1.bottom;
  461. rt5.top = rt1.top;
  462. rt5.bottom = rt1.bottom;
  463. rt6.top = rt1.top;
  464. rt6.bottom = rt1.bottom;
  465. rt7.top = rt1.top;
  466. rt7.bottom = rt1.bottom;
  467. rt8.top = rt1.top;
  468. rt8.bottom = rt1.bottom;
  469. rt9.top = rt1.top;
  470. rt9.bottom = rt1.bottom;
  471. rt10.top = rt1.top;
  472. rt10.bottom = rt1.bottom;
  473. if((i+iStart+1)>=nCountItem)
  474. break;
  475. }
  476. //结尾
  477. memDC.MoveTo(rc.left, nTop);
  478. memDC.LineTo(rc.left, rc.top);
  479. memDC.MoveTo(rc.right, nTop);
  480. memDC.LineTo(rc.right, rc.top);
  481. memDC.DrawText(csLFinality, &rc, DT_LEFT| DT_VCENTER | DT_SINGLELINE);
  482. memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
  483. memDC.SelectObject(oldfont);
  484. memDC.SelectObject(hPenOld);
  485. }
  486. TitleFont.DeleteObject();
  487. DetailFont.DeleteObject();
  488. cPen.DeleteObject();
  489. }

vc 实现打印功能的更多相关文章

  1. vc下打印透明背景图片

    一.前言 刚接到个任务,要把带有透明背景的章子图片打印出来,开始觉得不是很简单吗,直接用vc自动生成的打印功能不就ok了.不过问题却不是想像的那么简单! 二.窗口中显示透明图片 在窗口中显示图片,可以 ...

  2. MFC 实现打印机打印功能

    Visual C++6.0是开发Windows应用程序的强大工具,但是要通过它实现程序的打印功能,一直是初学者的一个难点,经常有朋友询问如何在VC中实现打印功能,他们往往感到在MFC提供的框架内实现这 ...

  3. jQuery:实现网页的打印功能

    实现的打印功能大致跟浏览器的 Ctrl+P 效果一样 一.直接上代码 <!DOCTYPE html> <head> <meta charset="utf-8&q ...

  4. C#程序调用CodeSoft预先设计好的标签模块实现打印功能

    if (this.tbSetLabel.Text.Trim() == "") { MessageBox.Show("请先 Enter 选择标签模板文件!", & ...

  5. 完美演绎DevExpress XtraPrinting Library 的打印功能

    完美演绎DevExpress XtraPrinting Library 的打印功能 2010-05-14 17:40:49|  分类: 默认分类|字号 订阅     设计报告不仅费时间,而且还乏味!但 ...

  6. web页面实现指定区域打印功能

    web页面实现指定区域打印功能 使用CSS,定义一个.noprint的class,将不打印的内容放入这个class内. 详细如下: <style media=print type="t ...

  7. 开源的javascript实现页面打印功能,兼容所有的浏览器(情况属实)

    这篇文章完全是属于技术文章,也是记录一下自己在项目当中遇到的坑爹问题啊,因为是B/S的程序,所以打印功能还是必须要有的,对于打印我选择了一个js插件,发现非常的简单和方便,所以这里拿出来和大家分享一下 ...

  8. IE下实现打印功能

    先贴代码: <html> <head> <style type="text/css"> *{margin:0px;padding:0px;} . ...

  9. DevExpress打印功能 z

    一.打印功能说明: 打印功能,我们有多种实现方式,可以根据需要自行选择,我简单的总结下两种方法. (1).使用微软.net框架自带的PrintDocument,这种方式是直接借助Graphics,自行 ...

随机推荐

  1. Tomcat部署方式

    tomcat中三种部署项目的方法 第一种方法:在tomcat中的conf目录中,在server.xml中的,<host/>节点中添加: <Context path="/he ...

  2. 关于MySql数据库设计表与查询耗时分析

    本地建一张表persons,使用脚本插入了1000万条数据 下面比较几种查询方法的耗时(查询9000000到9000005这中间5条数据) 查询结果: 1: SELECT * FROM test.pe ...

  3. java经典50编程题

    菲波拉契数列:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? package com.day2; public ...

  4. static, readonly, const

    static Use the static modifier to declare a static member, which belongs to the type itself rather t ...

  5. How to do logging in C# with log4net

    If you are writing server code in C# or to a lesser extent desktop/client then it's a good idea to i ...

  6. 热烈庆祝杨学明老师为苏宁、中兴、烽火、CNNIC、创维、金立、中航信等知名企业提供培训和咨询服务!

    在2015年三季度,研发资深顾问.资深讲师杨学明先生为国内多家名企提供了培训和咨询服务!由于杨学明老师在软件及互联网方面的管理经验极为丰富,被多家公司选为首席研发讲师!并聘为常年顾问!

  7. IIS 7.5 + asp.net MVC4 设置路由处理URL请求

    使用asp.net MVC4开发的网站,在本地的VS012环境下运行,一切正常.但当发布到Windows 2008 R2(IIS7.5 + Framework4.5)上时,访问相关网页时,出现有下面的 ...

  8. Entity Framework 4 数据事务操作

    利用数据库链接进行事务操作 var db = ConnectionHelper.GetConn(ConnectionType.Write);//获取上下文 var conn = db.Connecti ...

  9. Lambda应用设计模式

    前言 在使用 Lambda 表达式时,我们常会碰到一些典型的应用场景,而从常用场景中抽取出来的应用方式可以描述为应用模式.这些模式可能不全是新的模式,有的参考自 JavaScript 的设计模式,但至 ...

  10. 微软BI 之SSRS 系列 - 巧用 RunningValue 函数在分组中排序并设置 RANK 排名

    开篇介绍 经常有像类似于这样的排序需求,以及设置分组下的排序序号.比如此图中要求城市 City 在省份下按照 Internet Sales Amount 总销售额进行排序,并标识在各省份下的排名. 实 ...