vc 實現打印功能

 Visual C++6.0是開發Windows應用程序的強大工具,可是要經過它實現程序的打印功能,一直是初學者的一個難點,常常有朋友詢問如何在VC中實現打印功能,他們每每感到在MFC提供的框架內實現這個問題很複雜,不知道如何下手。本例針對這個問題,介紹一種簡單的方法實現文字串的打印功能,讀者朋友能夠在此基礎上稍微改動一下,就能夠實現文件、圖像的打印功能。

  1、實現方法

  在Windows操做系統下,顯示器、打印機和繪圖儀都被視爲輸出設備,正常狀況下,系統默認的輸出設備是顯示器。要使用打印機,首先須要建立一個指向打印機的設備環境句柄,而後經過該句柄調用相關的繪圖函數把所需的文字和圖形輸出至打印機上。當打印結束後,刪除這個設備環境句柄便可。

  當Windows系統中安裝好打印機後,系統老是自動設置一個打印機爲系統的默認打印機,在Windows的啓動配置文件Win.ini中的[window]段中列出了帶有關鍵字device的默認打印機。下面是某一機器中Win.ini中的[Windows]字段的內容:

編程

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


  在上述關鍵字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; //用來支持打印工做的額外ide

信息,通常狀況下爲NULL;
} DOCINFO, *LPDOCINFO; 
  開始一個打印任務後,再調用StartPage(hdcprint)函數讓打印機走紙,通知打印機有文檔將要打印;接下來的工做就是輸出數據了,這部分工做對於開發人員來講就象往計算機屏幕上輸出文字、圖像同樣容易,只不過是計算機根據當前的設備環境句柄自動將數據輸出到打印機罷了。數據打印完後,須要做一些善後處理工做,使用RestoreDC(hdcprint,-1)函數恢復打印機設備句柄、EndPage(hdcprint)函數讓打印機中止打印,最後調用EndDoc(hdcprint)函數結束上述的打印做業。

  2、編程步驟

  一、啓動Visual C++6.0,新建一個基於對話框的應用程序Test,在程序的對話框窗體中加入一個按鈕(Button),設置這個Button的屬性:ID=IDC_PRINT,CAPTION="打印";

  二、使用Class Wizard類嚮導爲該按鈕添加一個鼠標單擊處理函數OnPrint()

  三、修改TestDlg.cpp文件中的OnPrint()函數;

  四、添加代碼,編譯運行程序。函數

 

==========================================================================================================================工具

在打印預覽對話框類中字體

[cpp]  view plain copy
 
  1. extern int nPaperSize_X ;  
  2. extern int nPaperSize_Y ;  
  3. extern int nOneLines;  
  4. extern int nNextLines;  
  5.   
  6. //打印結構  
  7. typedef struct  
  8. {  
  9.  int  nMaxLine;   //最大行數  
  10.  int  nCountPage;   //一共頁數  
  11.  int  nCurPage;   //當前頁碼  
  12.  BOOL IsPrint;   //是否打印  
  13.  HWND hWnd;    //窗口句柄  
  14.  HWND hListView;   //列表控件句柄  
  15.  TCHAR szTag[256];   //其它數據  
  16.  int  nTag;    //其它數據  
  17.  LPVOID lpVoid;    //其它數據  
  18.  CGridCtrlEx *pObj;   //區分是月報表仍是日報表  
  19. }PRNINFO, *PPRNINFO;  
[cpp]  view plain copy
 
  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. }  
[cpp]  view plain copy
 
  1. void CPreviewChildDlg::PrintDoc()  
  2. {  
  3.     NotifyDlg Ndlg(_T("決定打印當前報表嗎?"), TRUE);  
  4.     if (Ndlg.DoModal() == IDCANCEL)  
  5.         return;  
  6.   
  7.     PRINTDLG printInfo;  
  8.     ZeroMemory(&printInfo,sizeof(printInfo));  //清空該結構  
  9.     printInfo.lStructSize = sizeof(printInfo);     
  10.     printInfo.hwndOwner = 0;     
  11.     printInfo.hDevMode = 0;  
  12.     printInfo.hDevNames = 0;  
  13.     //這個是關鍵,PD_RETURNDC 若是不設這個標誌,就拿不到hDC了  
  14.     //            PD_RETURNDEFAULT 這個就是獲得默認打印機,不須要彈設置對話框  
  15.     printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;    
  16.       
  17.     PrintDlg(&printInfo);//調用API拿出默認打印機  
  18.     DWORD rst = CommDlgExtendedError();//看看出錯沒有  
  19.     if(rst != 0)  
  20.     {//出錯了,清空標誌再次調用API,此時就會彈出打印設置對話框供用戶選擇了  
  21.         printInfo.Flags = 0;  
  22.         PrintDlg(&printInfo);  
  23.     }  
  24.   
  25.     HDC printDC=printInfo.hDC; //獲得打印DC,輸出到打印,  
  26.   
  27.     CDC MemDc;  
  28.     MemDc.Attach(printDC);  
  29.       
  30.     if(m_pDrawInfoFun!= NULL)  
  31.     {  
  32.         m_PrnInfo.IsPrint = TRUE;  // 用打印機打印  
  33.         m_PrnInfo.nCurPage = m_CurPage;  
  34.         m_PrnInfo.nCountPage = m_CountPage;  
  35.         m_pDrawInfoFun(MemDc, m_PrnInfo);  
  36.     }  
  37.   
  38.     MemDc.DeleteDC();}  
[cpp]  view plain copy
 
  1. //刷新預覽區  
  2. void CPreviewChildDlg::OnPaint()   
  3. {  
  4.     CPaintDC dc(this); // device context for painting  
  5.       
  6.     // TODO: Add your message handler code here  
  7.       
  8.     CClientDC dlgDC(this);  
  9.     SetWindowOrgEx(dlgDC.m_hDC, m_xPt, m_yPt, NULL);  
  10.     CDC MemDc;  
  11.     MemDc.CreateCompatibleDC(NULL);  
  12.     CBitmap cBitmap;  
  13.     int xP = dlgDC.GetDeviceCaps(LOGPIXELSX);  
  14.     int yP = dlgDC.GetDeviceCaps(LOGPIXELSY);  
  15.       
  16.     DOUBLE xPix = (DOUBLE)xP*10/254;    //每 mm 寬度的像素  
  17.     DOUBLE yPix = (DOUBLE)yP*10/254;    //每 mm 高度的像素  
  18.       
  19.     cBitmap.CreateCompatibleBitmap(&dlgDC, nPaperSize_X*xPix, nPaperSize_Y*yPix);  
  20.     MemDc.SelectObject(&cBitmap);  
  21.     if(m_pDrawInfoFun!= NULL)  
  22.     {  
  23.         m_PrnInfo.IsPrint = FALSE;  //顯示的是 預覽窗口  
  24.         m_PrnInfo.nCurPage = m_CurPage;  
  25.         m_pDrawInfoFun(MemDc, m_PrnInfo);   //調用回調函數  
  26.     }  
  27.     dlgDC.BitBlt(xP/2, yP/2, nPaperSize_X*xPix+xP/2, nPaperSize_Y*yPix+yP/2, &MemDc, 0, 0, SRCCOPY);  
  28.       
  29.     MemDc.DeleteDC();  
  30.     cBitmap.DeleteObject();  
  31.     // Do not call CDialog::OnPaint() for painting messages  
  32. }  


=============調用打印功能類this

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