Visual C++6.0是開發Windows應用程序的強大工具,但是要通過它實現程序的打印功能,一直是初學者的一個難點,經常有朋友詢問如何在VC中實現打印功能,他們往往感到在MFC提供的框架內實現這個問題很復雜,不知道如何下手。本例針對這個問題,介紹一種簡單的方法實現文字串的打印功能,讀者朋友可以在此基礎上稍微改動一下,就可以實現文件、圖像的打印功能。
一、實現方法
在Windows操作系統下,顯示器、打印機和繪圖儀都被視為輸出設備,正常情況下,系統默認的輸出設備是顯示器。要使用打印機,首先需要創建一個指向打印機的設備環境句柄,然后通過該句柄調用相關的繪圖函數把所需的文字和圖形輸出至打印機上。當打印結束后,刪除這個設備環境句柄即可。
當Windows系統中安裝好打印機后,系統總是自動設置一個打印機為系統的默認打印機,在Windows的啟動配置文件Win.ini中的[window]段中列出了帶有關鍵字device的默認打印機。下面是某一機器中Win.ini中的[Windows]字段的內容:
| [windows] |
在上述關鍵字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 { |
信息,一般情況下為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、添加代碼,編譯運行程序。
==========================================================================================================================
在打印預覽對話框類中
- extern int nPaperSize_X ;
- extern int nPaperSize_Y ;
- extern int nOneLines;
- extern int nNextLines;
- //打印結構
- typedef struct
- {
- int nMaxLine; //最大行數
- int nCountPage; //一共頁數
- int nCurPage; //當前頁碼
- BOOL IsPrint; //是否打印
- HWND hWnd; //窗口句柄
- HWND hListView; //列表控件句柄
- TCHAR szTag[256]; //其它數據
- int nTag; //其它數據
- LPVOID lpVoid; //其它數據
- CGridCtrlEx *pObj; //區分是月報表還是日報表
- }PRNINFO, *PPRNINFO;
extern int nPaperSize_X ;
extern int nPaperSize_Y ;
extern int nOneLines;
extern int nNextLines;
//打印結構
typedef struct
{
int nMaxLine; //最大行數
int nCountPage; //一共頁數
int nCurPage; //當前頁碼
BOOL IsPrint; //是否打印
HWND hWnd; //窗口句柄
HWND hListView; //列表控件句柄
TCHAR szTag[256]; //其它數據
int nTag; //其它數據
LPVOID lpVoid; //其它數據
CGridCtrlEx *pObj; //區分是月報表還是日報表
}PRNINFO, *PPRNINFO;
- //回調函數,設置打印屬性
- void CPreviewParentDlg::SetCallBackFun( PRINTPREVIEW pFun, PRNINFO &sPrnInfo )
- {
- memcpy(&m_PrnInfo, &sPrnInfo, sizeof(PRNINFO));
- m_pDrawInfoFun = pFun;
- m_nCount = m_PrnInfo.nMaxLine; // 總的行數
- m_nCountPage = 1;
- int m = m_nCount-m_OneCount;
- int n = m/m_NextCount;
- m_nCountPage += n;
- n = m%m_NextCount;
- if(n>0)
- m_nCountPage++; // 頁數
- m_PrnInfo.nCountPage = m_nCountPage;
- sPrnInfo.nCountPage = m_nCountPage;
- }
//回調函數,設置打印屬性
void CPreviewParentDlg::SetCallBackFun( PRINTPREVIEW pFun, PRNINFO &sPrnInfo )
{
memcpy(&m_PrnInfo, &sPrnInfo, sizeof(PRNINFO));
m_pDrawInfoFun = pFun;
m_nCount = m_PrnInfo.nMaxLine; // 總的行數
m_nCountPage = 1;
int m = m_nCount-m_OneCount;
int n = m/m_NextCount;
m_nCountPage += n;
n = m%m_NextCount;
if(n>0)
m_nCountPage++; // 頁數
m_PrnInfo.nCountPage = m_nCountPage;
sPrnInfo.nCountPage = m_nCountPage;
}
- void CPreviewChildDlg::PrintDoc()
- {
- NotifyDlg Ndlg(_T("決定打印當前報表嗎?"), TRUE);
- if (Ndlg.DoModal() == IDCANCEL)
- return;
- PRINTDLG printInfo;
- ZeroMemory(&printInfo,sizeof(printInfo)); //清空該結構
- printInfo.lStructSize = sizeof(printInfo);
- printInfo.hwndOwner = 0;
- printInfo.hDevMode = 0;
- printInfo.hDevNames = 0;
- //這個是關鍵,PD_RETURNDC 如果不設這個標志,就拿不到hDC了
- // PD_RETURNDEFAULT 這個就是得到默認打印機,不需要彈設置對話框
- printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
- PrintDlg(&printInfo);//調用API拿出默認打印機
- DWORD rst = CommDlgExtendedError();//看看出錯沒有
- if(rst != 0)
- {//出錯了,清空標志再次調用API,此時就會彈出打印設置對話框供用戶選擇了
- printInfo.Flags = 0;
- PrintDlg(&printInfo);
- }
- HDC printDC=printInfo.hDC; //得到打印DC,輸出到打印,
- CDC MemDc;
- MemDc.Attach(printDC);
- if(m_pDrawInfoFun!= NULL)
- {
- m_PrnInfo.IsPrint = TRUE; // 用打印機打印
- m_PrnInfo.nCurPage = m_CurPage;
- m_PrnInfo.nCountPage = m_CountPage;
- m_pDrawInfoFun(MemDc, m_PrnInfo);
- }
- MemDc.DeleteDC();}
void CPreviewChildDlg::PrintDoc()
{
NotifyDlg Ndlg(_T("決定打印當前報表嗎?"), TRUE);
if (Ndlg.DoModal() == IDCANCEL)
return;
PRINTDLG printInfo;
ZeroMemory(&printInfo,sizeof(printInfo)); //清空該結構
printInfo.lStructSize = sizeof(printInfo);
printInfo.hwndOwner = 0;
printInfo.hDevMode = 0;
printInfo.hDevNames = 0;
//這個是關鍵,PD_RETURNDC 如果不設這個標志,就拿不到hDC了
// PD_RETURNDEFAULT 這個就是得到默認打印機,不需要彈設置對話框
printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
PrintDlg(&printInfo);//調用API拿出默認打印機
DWORD rst = CommDlgExtendedError();//看看出錯沒有
if(rst != 0)
{//出錯了,清空標志再次調用API,此時就會彈出打印設置對話框供用戶選擇了
printInfo.Flags = 0;
PrintDlg(&printInfo);
}
HDC printDC=printInfo.hDC; //得到打印DC,輸出到打印,
CDC MemDc;
MemDc.Attach(printDC);
if(m_pDrawInfoFun!= NULL)
{
m_PrnInfo.IsPrint = TRUE; // 用打印機打印
m_PrnInfo.nCurPage = m_CurPage;
m_PrnInfo.nCountPage = m_CountPage;
m_pDrawInfoFun(MemDc, m_PrnInfo);
}
MemDc.DeleteDC();}
- //刷新預覽區
- void CPreviewChildDlg::OnPaint()
- {
- CPaintDC dc(this); // device context for painting
- // TODO: Add your message handler code here
- CClientDC dlgDC(this);
- SetWindowOrgEx(dlgDC.m_hDC, m_xPt, m_yPt, NULL);
- CDC MemDc;
- MemDc.CreateCompatibleDC(NULL);
- CBitmap cBitmap;
- int xP = dlgDC.GetDeviceCaps(LOGPIXELSX);
- int yP = dlgDC.GetDeviceCaps(LOGPIXELSY);
- DOUBLE xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
- DOUBLE yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
- cBitmap.CreateCompatibleBitmap(&dlgDC, nPaperSize_X*xPix, nPaperSize_Y*yPix);
- MemDc.SelectObject(&cBitmap);
- if(m_pDrawInfoFun!= NULL)
- {
- m_PrnInfo.IsPrint = FALSE; //顯示的是 預覽窗口
- m_PrnInfo.nCurPage = m_CurPage;
- m_pDrawInfoFun(MemDc, m_PrnInfo); //調用回調函數
- }
- dlgDC.BitBlt(xP/2, yP/2, nPaperSize_X*xPix+xP/2, nPaperSize_Y*yPix+yP/2, &MemDc, 0, 0, SRCCOPY);
- MemDc.DeleteDC();
- cBitmap.DeleteObject();
- // Do not call CDialog::OnPaint() for painting messages
- }
//刷新預覽區
void CPreviewChildDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CClientDC dlgDC(this);
SetWindowOrgEx(dlgDC.m_hDC, m_xPt, m_yPt, NULL);
CDC MemDc;
MemDc.CreateCompatibleDC(NULL);
CBitmap cBitmap;
int xP = dlgDC.GetDeviceCaps(LOGPIXELSX);
int yP = dlgDC.GetDeviceCaps(LOGPIXELSY);
DOUBLE xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
DOUBLE yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
cBitmap.CreateCompatibleBitmap(&dlgDC, nPaperSize_X*xPix, nPaperSize_Y*yPix);
MemDc.SelectObject(&cBitmap);
if(m_pDrawInfoFun!= NULL)
{
m_PrnInfo.IsPrint = FALSE; //顯示的是 預覽窗口
m_PrnInfo.nCurPage = m_CurPage;
m_pDrawInfoFun(MemDc, m_PrnInfo); //調用回調函數
}
dlgDC.BitBlt(xP/2, yP/2, nPaperSize_X*xPix+xP/2, nPaperSize_Y*yPix+yP/2, &MemDc, 0, 0, SRCCOPY);
MemDc.DeleteDC();
cBitmap.DeleteObject();
// Do not call CDialog::OnPaint() for painting messages
}
=============調用打印功能類
- void CAttendReportDlg::PrintData()
- {
- CGridCtrlEx *pGridCtrl = NULL;
- BOOL bDay = FALSE;
- if ( ((CButton*)GetDlgItem(IDC_RADIO_DAY))->GetCheck() )
- {
- pGridCtrl = m_pDayGridCtrl;
- bDay = TRUE;
- }
- else if ( ((CButton*)GetDlgItem(IDC_RADIO_MONTH))->GetCheck() )
- {
- pGridCtrl = m_pMonGridCtrl;
- }
- if( pGridCtrl->GetRowCount() <= 1 ) // 沒有記錄
- return;
- ///選擇打印機對話框
- CDC MemDc;
- HDC hdcPrint = NULL;
- CPrintDialog dlg(FALSE);
- if (m_bPrint) //打印按鈕,不彈出選擇對話框,獲取默認打印設備
- {
- PRINTDLG printInfo;
- ZeroMemory(&printInfo,sizeof(printInfo)); //清空該結構
- printInfo.lStructSize = sizeof(printInfo);
- printInfo.hwndOwner = 0;
- printInfo.hDevMode = 0;
- printInfo.hDevNames = 0;
- //這個是關鍵,PD_RETURNDC 如果不設這個標志,就拿不到hDC了
- //PD_RETURNDEFAULT 這個就是得到默認打印機,不需要彈出設置對話框
- printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
- PrintDlg(&printInfo);//調用API拿出默認打印機
- DWORD rst = CommDlgExtendedError();//看看出錯沒有
- if(rst != 0)
- {//出錯了,清空標志再次調用API,此時就會彈出打印設置對話框供用戶選擇了
- printInfo.Flags = 0;
- PrintDlg(&printInfo);
- }
- hdcPrint=printInfo.hDC; //得到打印DC,輸出到打印
- }
- else //彈出對話框選擇打印設備
- {
- dlg.DoModal();
- hdcPrint = dlg.GetPrinterDC();
- }
- if(hdcPrint == NULL)
- {
- NotifyDlg Ndlg(_T("打印機初始化失敗!"));
- Ndlg.DoModal();
- return;
- }
- MemDc.Attach(hdcPrint);
- nPaperSize_X = MemDc.GetDeviceCaps(HORZSIZE); // 紙張寬度
- nPaperSize_Y = MemDc.GetDeviceCaps(VERTSIZE); // 紙張高度
- int xP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSX); //x方向每英寸像素點數
- int yP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSY); //y方向每英寸像素點數
- int xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
- int yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
- DOUBLE fAdd = 5*yPix; //每格遞增量
- nOneLines = (nPaperSize_Y * 0.85*yPix)/fAdd;
- nNextLines = (nPaperSize_Y * 0.85*yPix)/fAdd+1;
- PRNINFO PrnInfo = {0};
- PrnInfo.hListView = NULL;
- PrnInfo.hWnd = this->m_hWnd;
- PrnInfo.IsPrint = m_bPrint;
- PrnInfo.nCurPage = 1;
- PrnInfo.nMaxLine = pGridCtrl->GetRowCount()-1;
- PrnInfo.pObj = pGridCtrl;
- CPreviewParentDlg DlgPreView;
- CPreviewChildDlg DlgChildPreView;
- if (bDay)
- {
- DlgPreView.SetCallBackFun(PrintDayInfo, PrnInfo); //回調函數,設置打印或預覽函數,及紙張排版信息
- DlgChildPreView.SetCallBackFun(PrintDayInfo, PrnInfo);
- }
- else
- {
- DlgPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
- DlgChildPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
- }
- if (!m_bPrint)
- {
- DlgPreView.DoModal();
- }
- else
- {
- DlgChildPreView.PrintDoc();
- }
- MemDc.DeleteDC();
- }
- void CAttendReportDlg::PrintDayInfo( CDC &memDC, PRNINFO PrnInfo )
- {
- if(memDC.m_hDC == NULL)
- return;
- int nCurPage = PrnInfo.nCurPage; //當前頁
- BOOL IsPrint = PrnInfo.IsPrint; //是否打印
- int nMaxPage = PrnInfo.nCountPage; //最大頁碼
- HWND hWnd = PrnInfo.hWnd;
- CString csLFinality, csRFinality;
- CGridCtrlEx *pGridCtrl = PrnInfo.pObj;
- CTime time = CTime::GetCurrentTime();
- csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
- csLFinality = _T("報表日期:") + csLFinality;
- csRFinality.Format(_T("第 %i 頁/共 %i 頁"), nCurPage, nMaxPage);
- TCHAR szTitle[] = _T("考 勤 日 報 表");
- CRect rc, rt1, rt2, rt3, rt4, rt5, rt6, rt7, rt8, rt9, rt10;
- CPen *hPenOld;
- CPen cPen;
- CFont TitleFont, DetailFont, *oldfont;
- //標題字體
- TitleFont.CreateFont(-MulDiv(14,memDC.GetDeviceCaps(LOGPIXELSY),72),
- 0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
- OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
- VARIABLE_PITCH|FF_SWISS,_T("黑體"));
- //細節字體
- DetailFont.CreateFont(-MulDiv(10,memDC.GetDeviceCaps(LOGPIXELSY),92),
- 0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
- OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
- VARIABLE_PITCH|FF_SWISS,_T("宋體"));
- //粗筆
- cPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
- int xP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSX); //x方向每英寸像素點數
- int yP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSY); //y方向每英寸像素點數
- DOUBLE xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
- DOUBLE yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
- DOUBLE fAdd = 5*yPix; //每格遞增量
- DOUBLE nTop = 30*yPix; //第一頁最上線
- int iStart = 0; //從第幾行開始讀取
- DOUBLE nBottom = nTop+nOneLines*fAdd;
- if(nCurPage != 1)
- nTop = 30*yPix-fAdd; //非第一頁最上線
- if(nCurPage == 2)
- iStart = nOneLines;
- if(nCurPage>2)
- iStart = nOneLines+(nCurPage - 2)*nNextLines;
- DOUBLE nLeft = 15*xPix; //最左線
- DOUBLE nRight = xPix*(nPaperSize_X-15); //最右線
- DOUBLE nItemWide = ((nPaperSize_X-30)/14)*xPix;
- DOUBLE nTextAdd = 1.5*xPix;
- if(IsPrint)
- {
- //真正打印部分
- static DOCINFO di = {sizeof (DOCINFO), szTitle} ;
- //開始文檔打印///////////////////////////////////////// start print
- //////////////////////////////////////////////////////////
- if(memDC.StartDoc( &di ) < 0) // startdoc-----enddoc
- {
- NotifyDlg dlg(_T("連接到打印機化敗!"));
- dlg.DoModal();
- }
- else
- {
- iStart = 0;
- nTop = 30*yPix; //第一頁最上線
- for(int iTotalPages = 1; iTotalPages<=nMaxPage; iTotalPages++)
- {
- int nCurPage = iTotalPages;
- csRFinality.Format(_T("第 %i 頁/共 %i 頁"), nCurPage, nMaxPage);
- time=CTime::GetCurrentTime();
- csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
- csLFinality = _T("報表日期:") + csLFinality;
- if(nCurPage != 1)
- nTop = 30*yPix-fAdd; //非第一頁最上線
- if(nCurPage == 2)
- iStart = nOneLines;
- if(nCurPage>2)
- iStart = nOneLines+(nCurPage - 2)*nNextLines;
- //開始頁
- if(memDC.StartPage() < 0)
- {
- NotifyDlg dlg(_T("打印失敗!"));
- dlg.DoModal();
- memDC.AbortDoc();
- return;
- }
- else
- {
- //打印
- //標題
- oldfont = memDC.SelectObject(&TitleFont);
- int nItem = nNextLines;
- if(nCurPage == 1)
- {
- nItem = nOneLines;
- rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
- memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- }
- //細節
- memDC.SelectObject(&DetailFont);
- rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
- //上橫線
- memDC.MoveTo(rc.left, rc.top);
- memDC.LineTo(rc.right, rc.top);
- rt1.SetRect(nLeft, nTop, rc.right -12.4*nItemWide , nTop+fAdd); //編 號
- rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
- rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
- rt4.SetRect(rt3.right, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom); //班次
- rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //時段
- rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤時間
- rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //遲到(分)
- rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
- rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //曠工(分)
- rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //請假(分)
- memDC.DrawText(_T("編 號"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("時 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("考勤時間"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("遲到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("曠工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("請假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.MoveTo(rt1.right, rt1.top);
- memDC.LineTo(rt1.right, rt1.bottom);
- memDC.MoveTo(rt2.right, rt1.top);
- memDC.LineTo(rt2.right, rt1.bottom);
- memDC.MoveTo(rt3.right, rt1.top);
- memDC.LineTo(rt3.right, rt1.bottom);
- memDC.MoveTo(rt4.right, rt1.top);
- memDC.LineTo(rt4.right, rt1.bottom);
- memDC.MoveTo(rt5.right, rt1.top);
- memDC.LineTo(rt5.right, rt1.bottom);
- memDC.MoveTo(rt6.right, rt1.top);
- memDC.LineTo(rt6.right, rt1.bottom);
- memDC.MoveTo(rt7.right, rt1.top);
- memDC.LineTo(rt7.right, rt1.bottom);
- memDC.MoveTo(rt8.right, rt1.top);
- memDC.LineTo(rt8.right, rt1.bottom);
- memDC.MoveTo(rt9.right, rt1.top);
- memDC.LineTo(rt9.right, rt1.bottom);
- memDC.MoveTo(rc.left, rt1.bottom);
- memDC.LineTo(rc.right, rt1.bottom);
- CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
- rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
- rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.4*nItemWide, rc.bottom);
- rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
- rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
- rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom);
- rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right +1.6*nItemWide, rt1.bottom);
- rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
- rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
- rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
- rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
- rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
- int nCountItem = pGridCtrl->GetRowCount();
- for(int i=1;i<nItem; i++)
- {
- strID = pGridCtrl->GetItemText(i+iStart, 1);
- strName = pGridCtrl->GetItemText(i+iStart, 2);
- strDate = pGridCtrl->GetItemText(i+iStart, 3);
- strSID = pGridCtrl->GetItemText(i+iStart, 4);
- strTime = pGridCtrl->GetItemText(i+iStart, 5);
- strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
- strLate = pGridCtrl->GetItemText(i+iStart, 7);
- strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
- strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
- strLeave = pGridCtrl->GetItemText(i+iStart, 10);
- memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- //下橫線
- memDC.MoveTo(rc.left, rc.bottom);
- memDC.LineTo(rc.right, rc.bottom);
- memDC.MoveTo(rt1.right, rt1.top);
- memDC.LineTo(rt1.right, rt1.bottom);
- memDC.MoveTo(rt2.right, rt1.top);
- memDC.LineTo(rt2.right, rt1.bottom);
- memDC.MoveTo(rt3.right, rt1.top);
- memDC.LineTo(rt3.right, rt1.bottom);
- memDC.MoveTo(rt4.right, rt1.top);
- memDC.LineTo(rt4.right, rt1.bottom);
- memDC.MoveTo(rt5.right, rt1.top);
- memDC.LineTo(rt5.right, rt1.bottom);
- memDC.MoveTo(rt6.right, rt1.top);
- memDC.LineTo(rt6.right, rt1.bottom);
- memDC.MoveTo(rt7.right, rt1.top);
- memDC.LineTo(rt7.right, rt1.bottom);
- memDC.MoveTo(rt8.right, rt1.top);
- memDC.LineTo(rt8.right, rt1.bottom);
- memDC.MoveTo(rt9.right, rt1.top);
- memDC.LineTo(rt9.right, rt1.bottom);
- memDC.MoveTo(rc.left, rt1.bottom);
- memDC.LineTo(rc.right, rt1.bottom);
- rc.top += fAdd;
- rc.bottom += fAdd;
- rt1.top = rc.top;
- rt1.bottom = rc.bottom;
- rt2.top = rt1.top;
- rt2.bottom = rt1.bottom;
- rt3.top = rt1.top;
- rt3.bottom = rt1.bottom;
- rt4.top = rt1.top;
- rt4.bottom = rt1.bottom;
- rt5.top = rt1.top;
- rt5.bottom = rt1.bottom;
- rt6.top = rt1.top;
- rt6.bottom = rt1.bottom;
- rt7.top = rt1.top;
- rt7.bottom = rt1.bottom;
- rt8.top = rt1.top;
- rt8.bottom = rt1.bottom;
- rt9.top = rt1.top;
- rt9.bottom = rt1.bottom;
- rt10.top = rt1.top;
- rt10.bottom = rt1.bottom;
- if((i+iStart+1)>=nCountItem)
- break;
- }
- //結尾
- memDC.MoveTo(rc.left, nTop);
- memDC.LineTo(rc.left, rc.top);
- memDC.MoveTo(rc.right, nTop);
- memDC.LineTo(rc.right, rc.top);
- memDC.DrawText(csLFinality, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
- memDC.EndPage();
- memDC.SelectObject(oldfont);
- }
- }
- memDC.EndDoc();
- }
- }
- else
- {
- ////////////////////打印預覽
- //邊框線
- hPenOld = memDC.SelectObject(&cPen);
- rc.SetRect(0, 0, nPaperSize_X*xPix, nPaperSize_Y*yPix);
- memDC.Rectangle(&rc);
- memDC.SelectObject(hPenOld);
- //標題
- oldfont = memDC.SelectObject(&TitleFont);
- int nItem = nNextLines;
- if(nCurPage == 1)
- {
- nItem = nOneLines;
- rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
- memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- }
- //細節
- memDC.SelectObject(&DetailFont);
- rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
- //上橫線
- memDC.MoveTo(rc.left, rc.top);
- memDC.LineTo(rc.right, rc.top);
- rt1.SetRect(nLeft, nTop, rc.right -12.2*nItemWide, nTop+fAdd); //編 號
- rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
- rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
- rt4.SetRect(rt3.right, rt1.top, rt3.right + 2*nItemWide, rt1.bottom); //班次
- rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //時段
- rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤時間
- rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //遲到(分)
- rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
- rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //曠工(分)
- rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //請假(分)
- memDC.DrawText(_T("編 號"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("時 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("考勤時間"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("遲到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("曠工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(_T("請假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.MoveTo(rt1.right, rt1.top);
- memDC.LineTo(rt1.right, rt1.bottom);
- memDC.MoveTo(rt2.right, rt1.top);
- memDC.LineTo(rt2.right, rt1.bottom);
- memDC.MoveTo(rt3.right, rt1.top);
- memDC.LineTo(rt3.right, rt1.bottom);
- memDC.MoveTo(rt4.right, rt1.top);
- memDC.LineTo(rt4.right, rt1.bottom);
- memDC.MoveTo(rt5.right, rt1.top);
- memDC.LineTo(rt5.right, rt1.bottom);
- memDC.MoveTo(rt6.right, rt1.top);
- memDC.LineTo(rt6.right, rt1.bottom);
- memDC.MoveTo(rt7.right, rt1.top);
- memDC.LineTo(rt7.right, rt1.bottom);
- memDC.MoveTo(rt8.right, rt1.top);
- memDC.LineTo(rt8.right, rt1.bottom);
- memDC.MoveTo(rt9.right, rt1.top);
- memDC.LineTo(rt9.right, rt1.bottom);
- memDC.MoveTo(rc.left, rt1.bottom);
- memDC.LineTo(rc.right, rt1.bottom);
- CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
- rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
- rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.2*nItemWide, rc.bottom);
- rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
- rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
- rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2*nItemWide, rt1.bottom);
- rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom);
- rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
- rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
- rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
- rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
- rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
- int nCountItem = pGridCtrl->GetRowCount();
- for(int i=1;i<nItem; i++)
- {
- strID = pGridCtrl->GetItemText(i+iStart, 1);
- strName = pGridCtrl->GetItemText(i+iStart, 2);
- strDate = pGridCtrl->GetItemText(i+iStart, 3);
- strSID = pGridCtrl->GetItemText(i+iStart, 4);
- strTime = pGridCtrl->GetItemText(i+iStart, 5);
- strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
- strLate = pGridCtrl->GetItemText(i+iStart, 7);
- strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
- strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
- strLeave = pGridCtrl->GetItemText(i+iStart, 10);
- memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
- //下橫線
- memDC.MoveTo(rc.left, rc.bottom);
- memDC.LineTo(rc.right, rc.bottom);
- memDC.MoveTo(rt1.right, rt1.top);
- memDC.LineTo(rt1.right, rt1.bottom);
- memDC.MoveTo(rt2.right, rt1.top);
- memDC.LineTo(rt2.right, rt1.bottom);
- memDC.MoveTo(rt3.right, rt1.top);
- memDC.LineTo(rt3.right, rt1.bottom);
- memDC.MoveTo(rt4.right, rt1.top);
- memDC.LineTo(rt4.right, rt1.bottom);
- memDC.MoveTo(rt5.right, rt1.top);
- memDC.LineTo(rt5.right, rt1.bottom);
- memDC.MoveTo(rt6.right, rt1.top);
- memDC.LineTo(rt6.right, rt1.bottom);
- memDC.MoveTo(rt7.right, rt1.top);
- memDC.LineTo(rt7.right, rt1.bottom);
- memDC.MoveTo(rt8.right, rt1.top);
- memDC.LineTo(rt8.right, rt1.bottom);
- memDC.MoveTo(rt9.right, rt1.top);
- memDC.LineTo(rt9.right, rt1.bottom);
- memDC.MoveTo(rc.left, rt1.bottom);
- memDC.LineTo(rc.right, rt1.bottom);
- rc.top += fAdd;
- rc.bottom += fAdd;
- rt1.top = rc.top;
- rt1.bottom = rc.bottom;
- rt2.top = rt1.top;
- rt2.bottom = rt1.bottom;
- rt3.top = rt1.top;
- rt3.bottom = rt1.bottom;
- rt4.top = rt1.top;
- rt4.bottom = rt1.bottom;
- rt5.top = rt1.top;
- rt5.bottom = rt1.bottom;
- rt6.top = rt1.top;
- rt6.bottom = rt1.bottom;
- rt7.top = rt1.top;
- rt7.bottom = rt1.bottom;
- rt8.top = rt1.top;
- rt8.bottom = rt1.bottom;
- rt9.top = rt1.top;
- rt9.bottom = rt1.bottom;
- rt10.top = rt1.top;
- rt10.bottom = rt1.bottom;
- if((i+iStart+1)>=nCountItem)
- break;
- }
- //結尾
- memDC.MoveTo(rc.left, nTop);
- memDC.LineTo(rc.left, rc.top);
- memDC.MoveTo(rc.right, nTop);
- memDC.LineTo(rc.right, rc.top);
- memDC.DrawText(csLFinality, &rc, DT_LEFT| DT_VCENTER | DT_SINGLELINE);
- memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
- memDC.SelectObject(oldfont);
- memDC.SelectObject(hPenOld);
- }
- TitleFont.DeleteObject();
- DetailFont.DeleteObject();
- cPen.DeleteObject();
- }
void CAttendReportDlg::PrintData()
{
CGridCtrlEx *pGridCtrl = NULL;
BOOL bDay = FALSE;
if ( ((CButton*)GetDlgItem(IDC_RADIO_DAY))->GetCheck() )
{
pGridCtrl = m_pDayGridCtrl;
bDay = TRUE;
}
else if ( ((CButton*)GetDlgItem(IDC_RADIO_MONTH))->GetCheck() )
{
pGridCtrl = m_pMonGridCtrl;
}
if( pGridCtrl->GetRowCount() <= 1 ) // 沒有記錄
return;
///選擇打印機對話框
CDC MemDc;
HDC hdcPrint = NULL;
CPrintDialog dlg(FALSE);
if (m_bPrint) //打印按鈕,不彈出選擇對話框,獲取默認打印設備
{
PRINTDLG printInfo;
ZeroMemory(&printInfo,sizeof(printInfo)); //清空該結構
printInfo.lStructSize = sizeof(printInfo);
printInfo.hwndOwner = 0;
printInfo.hDevMode = 0;
printInfo.hDevNames = 0;
//這個是關鍵,PD_RETURNDC 如果不設這個標志,就拿不到hDC了
//PD_RETURNDEFAULT 這個就是得到默認打印機,不需要彈出設置對話框
printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT | PD_ALLPAGES;
PrintDlg(&printInfo);//調用API拿出默認打印機
DWORD rst = CommDlgExtendedError();//看看出錯沒有
if(rst != 0)
{//出錯了,清空標志再次調用API,此時就會彈出打印設置對話框供用戶選擇了
printInfo.Flags = 0;
PrintDlg(&printInfo);
}
hdcPrint=printInfo.hDC; //得到打印DC,輸出到打印
}
else //彈出對話框選擇打印設備
{
dlg.DoModal();
hdcPrint = dlg.GetPrinterDC();
}
if(hdcPrint == NULL)
{
NotifyDlg Ndlg(_T("打印機初始化失敗!"));
Ndlg.DoModal();
return;
}
MemDc.Attach(hdcPrint);
nPaperSize_X = MemDc.GetDeviceCaps(HORZSIZE); // 紙張寬度
nPaperSize_Y = MemDc.GetDeviceCaps(VERTSIZE); // 紙張高度
int xP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSX); //x方向每英寸像素點數
int yP = GetDeviceCaps(MemDc.m_hDC, LOGPIXELSY); //y方向每英寸像素點數
int xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
int yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
DOUBLE fAdd = 5*yPix; //每格遞增量
nOneLines = (nPaperSize_Y * 0.85*yPix)/fAdd;
nNextLines = (nPaperSize_Y * 0.85*yPix)/fAdd+1;
PRNINFO PrnInfo = {0};
PrnInfo.hListView = NULL;
PrnInfo.hWnd = this->m_hWnd;
PrnInfo.IsPrint = m_bPrint;
PrnInfo.nCurPage = 1;
PrnInfo.nMaxLine = pGridCtrl->GetRowCount()-1;
PrnInfo.pObj = pGridCtrl;
CPreviewParentDlg DlgPreView;
CPreviewChildDlg DlgChildPreView;
if (bDay)
{
DlgPreView.SetCallBackFun(PrintDayInfo, PrnInfo); //回調函數,設置打印或預覽函數,及紙張排版信息
DlgChildPreView.SetCallBackFun(PrintDayInfo, PrnInfo);
}
else
{
DlgPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
DlgChildPreView.SetCallBackFun(PrintMonInfo, PrnInfo);
}
if (!m_bPrint)
{
DlgPreView.DoModal();
}
else
{
DlgChildPreView.PrintDoc();
}
MemDc.DeleteDC();
}
void CAttendReportDlg::PrintDayInfo( CDC &memDC, PRNINFO PrnInfo )
{
if(memDC.m_hDC == NULL)
return;
int nCurPage = PrnInfo.nCurPage; //當前頁
BOOL IsPrint = PrnInfo.IsPrint; //是否打印
int nMaxPage = PrnInfo.nCountPage; //最大頁碼
HWND hWnd = PrnInfo.hWnd;
CString csLFinality, csRFinality;
CGridCtrlEx *pGridCtrl = PrnInfo.pObj;
CTime time = CTime::GetCurrentTime();
csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
csLFinality = _T("報表日期:") + csLFinality;
csRFinality.Format(_T("第 %i 頁/共 %i 頁"), nCurPage, nMaxPage);
TCHAR szTitle[] = _T("考 勤 日 報 表");
CRect rc, rt1, rt2, rt3, rt4, rt5, rt6, rt7, rt8, rt9, rt10;
CPen *hPenOld;
CPen cPen;
CFont TitleFont, DetailFont, *oldfont;
//標題字體
TitleFont.CreateFont(-MulDiv(14,memDC.GetDeviceCaps(LOGPIXELSY),72),
0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
VARIABLE_PITCH|FF_SWISS,_T("黑體"));
//細節字體
DetailFont.CreateFont(-MulDiv(10,memDC.GetDeviceCaps(LOGPIXELSY),92),
0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
VARIABLE_PITCH|FF_SWISS,_T("宋體"));
//粗筆
cPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
int xP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSX); //x方向每英寸像素點數
int yP = GetDeviceCaps(memDC.m_hDC, LOGPIXELSY); //y方向每英寸像素點數
DOUBLE xPix = (DOUBLE)xP*10/254; //每 mm 寬度的像素
DOUBLE yPix = (DOUBLE)yP*10/254; //每 mm 高度的像素
DOUBLE fAdd = 5*yPix; //每格遞增量
DOUBLE nTop = 30*yPix; //第一頁最上線
int iStart = 0; //從第幾行開始讀取
DOUBLE nBottom = nTop+nOneLines*fAdd;
if(nCurPage != 1)
nTop = 30*yPix-fAdd; //非第一頁最上線
if(nCurPage == 2)
iStart = nOneLines;
if(nCurPage>2)
iStart = nOneLines+(nCurPage - 2)*nNextLines;
DOUBLE nLeft = 15*xPix; //最左線
DOUBLE nRight = xPix*(nPaperSize_X-15); //最右線
DOUBLE nItemWide = ((nPaperSize_X-30)/14)*xPix;
DOUBLE nTextAdd = 1.5*xPix;
if(IsPrint)
{
//真正打印部分
static DOCINFO di = {sizeof (DOCINFO), szTitle} ;
//開始文檔打印///////////////////////////////////////// start print
//////////////////////////////////////////////////////////
if(memDC.StartDoc( &di ) < 0) // startdoc-----enddoc
{
NotifyDlg dlg(_T("連接到打印機化敗!"));
dlg.DoModal();
}
else
{
iStart = 0;
nTop = 30*yPix; //第一頁最上線
for(int iTotalPages = 1; iTotalPages<=nMaxPage; iTotalPages++)
{
int nCurPage = iTotalPages;
csRFinality.Format(_T("第 %i 頁/共 %i 頁"), nCurPage, nMaxPage);
time=CTime::GetCurrentTime();
csLFinality = time.Format(_T("%Y-%m-%d %H:%M:%S"));
csLFinality = _T("報表日期:") + csLFinality;
if(nCurPage != 1)
nTop = 30*yPix-fAdd; //非第一頁最上線
if(nCurPage == 2)
iStart = nOneLines;
if(nCurPage>2)
iStart = nOneLines+(nCurPage - 2)*nNextLines;
//開始頁
if(memDC.StartPage() < 0)
{
NotifyDlg dlg(_T("打印失敗!"));
dlg.DoModal();
memDC.AbortDoc();
return;
}
else
{
//打印
//標題
oldfont = memDC.SelectObject(&TitleFont);
int nItem = nNextLines;
if(nCurPage == 1)
{
nItem = nOneLines;
rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
//細節
memDC.SelectObject(&DetailFont);
rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
//上橫線
memDC.MoveTo(rc.left, rc.top);
memDC.LineTo(rc.right, rc.top);
rt1.SetRect(nLeft, nTop, rc.right -12.4*nItemWide , nTop+fAdd); //編 號
rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
rt4.SetRect(rt3.right, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom); //班次
rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //時段
rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤時間
rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //遲到(分)
rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //曠工(分)
rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //請假(分)
memDC.DrawText(_T("編 號"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("時 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("考勤時間"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("遲到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("曠工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("請假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.MoveTo(rt1.right, rt1.top);
memDC.LineTo(rt1.right, rt1.bottom);
memDC.MoveTo(rt2.right, rt1.top);
memDC.LineTo(rt2.right, rt1.bottom);
memDC.MoveTo(rt3.right, rt1.top);
memDC.LineTo(rt3.right, rt1.bottom);
memDC.MoveTo(rt4.right, rt1.top);
memDC.LineTo(rt4.right, rt1.bottom);
memDC.MoveTo(rt5.right, rt1.top);
memDC.LineTo(rt5.right, rt1.bottom);
memDC.MoveTo(rt6.right, rt1.top);
memDC.LineTo(rt6.right, rt1.bottom);
memDC.MoveTo(rt7.right, rt1.top);
memDC.LineTo(rt7.right, rt1.bottom);
memDC.MoveTo(rt8.right, rt1.top);
memDC.LineTo(rt8.right, rt1.bottom);
memDC.MoveTo(rt9.right, rt1.top);
memDC.LineTo(rt9.right, rt1.bottom);
memDC.MoveTo(rc.left, rt1.bottom);
memDC.LineTo(rc.right, rt1.bottom);
CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.4*nItemWide, rc.bottom);
rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2.2*nItemWide, rt1.bottom);
rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right +1.6*nItemWide, rt1.bottom);
rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
int nCountItem = pGridCtrl->GetRowCount();
for(int i=1;i<nItem; i++)
{
strID = pGridCtrl->GetItemText(i+iStart, 1);
strName = pGridCtrl->GetItemText(i+iStart, 2);
strDate = pGridCtrl->GetItemText(i+iStart, 3);
strSID = pGridCtrl->GetItemText(i+iStart, 4);
strTime = pGridCtrl->GetItemText(i+iStart, 5);
strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
strLate = pGridCtrl->GetItemText(i+iStart, 7);
strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
strLeave = pGridCtrl->GetItemText(i+iStart, 10);
memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
//下橫線
memDC.MoveTo(rc.left, rc.bottom);
memDC.LineTo(rc.right, rc.bottom);
memDC.MoveTo(rt1.right, rt1.top);
memDC.LineTo(rt1.right, rt1.bottom);
memDC.MoveTo(rt2.right, rt1.top);
memDC.LineTo(rt2.right, rt1.bottom);
memDC.MoveTo(rt3.right, rt1.top);
memDC.LineTo(rt3.right, rt1.bottom);
memDC.MoveTo(rt4.right, rt1.top);
memDC.LineTo(rt4.right, rt1.bottom);
memDC.MoveTo(rt5.right, rt1.top);
memDC.LineTo(rt5.right, rt1.bottom);
memDC.MoveTo(rt6.right, rt1.top);
memDC.LineTo(rt6.right, rt1.bottom);
memDC.MoveTo(rt7.right, rt1.top);
memDC.LineTo(rt7.right, rt1.bottom);
memDC.MoveTo(rt8.right, rt1.top);
memDC.LineTo(rt8.right, rt1.bottom);
memDC.MoveTo(rt9.right, rt1.top);
memDC.LineTo(rt9.right, rt1.bottom);
memDC.MoveTo(rc.left, rt1.bottom);
memDC.LineTo(rc.right, rt1.bottom);
rc.top += fAdd;
rc.bottom += fAdd;
rt1.top = rc.top;
rt1.bottom = rc.bottom;
rt2.top = rt1.top;
rt2.bottom = rt1.bottom;
rt3.top = rt1.top;
rt3.bottom = rt1.bottom;
rt4.top = rt1.top;
rt4.bottom = rt1.bottom;
rt5.top = rt1.top;
rt5.bottom = rt1.bottom;
rt6.top = rt1.top;
rt6.bottom = rt1.bottom;
rt7.top = rt1.top;
rt7.bottom = rt1.bottom;
rt8.top = rt1.top;
rt8.bottom = rt1.bottom;
rt9.top = rt1.top;
rt9.bottom = rt1.bottom;
rt10.top = rt1.top;
rt10.bottom = rt1.bottom;
if((i+iStart+1)>=nCountItem)
break;
}
//結尾
memDC.MoveTo(rc.left, nTop);
memDC.LineTo(rc.left, rc.top);
memDC.MoveTo(rc.right, nTop);
memDC.LineTo(rc.right, rc.top);
memDC.DrawText(csLFinality, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
memDC.EndPage();
memDC.SelectObject(oldfont);
}
}
memDC.EndDoc();
}
}
else
{
////////////////////打印預覽
//邊框線
hPenOld = memDC.SelectObject(&cPen);
rc.SetRect(0, 0, nPaperSize_X*xPix, nPaperSize_Y*yPix);
memDC.Rectangle(&rc);
memDC.SelectObject(hPenOld);
//標題
oldfont = memDC.SelectObject(&TitleFont);
int nItem = nNextLines;
if(nCurPage == 1)
{
nItem = nOneLines;
rc.SetRect(0, yPix*15, nPaperSize_X*xPix, yPix*25);
memDC.DrawText(szTitle, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
//細節
memDC.SelectObject(&DetailFont);
rc.SetRect(nLeft, nTop, nRight, nTop+fAdd);
//上橫線
memDC.MoveTo(rc.left, rc.top);
memDC.LineTo(rc.right, rc.top);
rt1.SetRect(nLeft, nTop, rc.right -12.2*nItemWide, nTop+fAdd); //編 號
rt2.SetRect(rt1.right, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom); //姓名
rt3.SetRect(rt2.right, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom); //考勤日期
rt4.SetRect(rt3.right, rt1.top, rt3.right + 2*nItemWide, rt1.bottom); //班次
rt5.SetRect(rt4.right, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom); //時段
rt6.SetRect(rt5.right, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom); //考勤時間
rt7.SetRect(rt6.right, rt1.top, rt6.right + nItemWide, rt1.bottom); //遲到(分)
rt8.SetRect(rt7.right, rt1.top, rt7.right + nItemWide, rt1.bottom); //早退(分)
rt9.SetRect(rt8.right, rt1.top, rt8.right + nItemWide, rt1.bottom); //曠工(分)
rt10.SetRect(rt9.right, rt1.top, rc.right, rt1.bottom); //請假(分)
memDC.DrawText(_T("編 號"), &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("姓 名"), &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("考勤日期"), &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("班 次"), &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("時 段"), &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("考勤時間"), &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("遲到(分)"), &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("早退(分)"), &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("曠工(分)"), &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(_T("請假(分)"), &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.MoveTo(rt1.right, rt1.top);
memDC.LineTo(rt1.right, rt1.bottom);
memDC.MoveTo(rt2.right, rt1.top);
memDC.LineTo(rt2.right, rt1.bottom);
memDC.MoveTo(rt3.right, rt1.top);
memDC.LineTo(rt3.right, rt1.bottom);
memDC.MoveTo(rt4.right, rt1.top);
memDC.LineTo(rt4.right, rt1.bottom);
memDC.MoveTo(rt5.right, rt1.top);
memDC.LineTo(rt5.right, rt1.bottom);
memDC.MoveTo(rt6.right, rt1.top);
memDC.LineTo(rt6.right, rt1.bottom);
memDC.MoveTo(rt7.right, rt1.top);
memDC.LineTo(rt7.right, rt1.bottom);
memDC.MoveTo(rt8.right, rt1.top);
memDC.LineTo(rt8.right, rt1.bottom);
memDC.MoveTo(rt9.right, rt1.top);
memDC.LineTo(rt9.right, rt1.bottom);
memDC.MoveTo(rc.left, rt1.bottom);
memDC.LineTo(rc.right, rt1.bottom);
CString strID, strName, strDate, strSID, strTime, strAttTime, strLate, strEarlier, strAbsent, strLeave;
rc.SetRect(nLeft, nTop+fAdd, nRight, nTop+2*fAdd);
rt1.SetRect(nLeft+nTextAdd, rc.top, rc.right-12.2*nItemWide, rc.bottom);
rt2.SetRect(rt1.right+nTextAdd, rt1.top, rt1.right + 1.5*nItemWide, rt1.bottom);
rt3.SetRect(rt2.right+nTextAdd, rt1.top, rt2.right + 1.5*nItemWide, rt1.bottom);
rt4.SetRect(rt3.right+nTextAdd, rt1.top, rt3.right + 2*nItemWide, rt1.bottom);
rt5.SetRect(rt4.right+nTextAdd, rt1.top, rt4.right + 1.6*nItemWide, rt1.bottom);
rt6.SetRect(rt5.right+nTextAdd, rt1.top, rt5.right + 1.6*nItemWide, rt1.bottom);
rt7.SetRect(rt6.right+nTextAdd, rt1.top, rt6.right + nItemWide, rt1.bottom);
rt8.SetRect(rt7.right+nTextAdd, rt1.top, rt7.right + nItemWide, rt1.bottom);
rt9.SetRect(rt8.right+nTextAdd, rt1.top, rt8.right + nItemWide, rt1.bottom);
rt10.SetRect(rt9.right+nTextAdd, rt1.top, rc.right, rt1.bottom);
int nCountItem = pGridCtrl->GetRowCount();
for(int i=1;i<nItem; i++)
{
strID = pGridCtrl->GetItemText(i+iStart, 1);
strName = pGridCtrl->GetItemText(i+iStart, 2);
strDate = pGridCtrl->GetItemText(i+iStart, 3);
strSID = pGridCtrl->GetItemText(i+iStart, 4);
strTime = pGridCtrl->GetItemText(i+iStart, 5);
strAttTime = pGridCtrl->GetItemText(i+iStart, 6);
strLate = pGridCtrl->GetItemText(i+iStart, 7);
strEarlier = pGridCtrl->GetItemText(i+iStart, 8);
strAbsent = pGridCtrl->GetItemText(i+iStart, 9);
strLeave = pGridCtrl->GetItemText(i+iStart, 10);
memDC.DrawText(strID, &rt1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strName, &rt2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strDate, &rt3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strSID, &rt4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strTime, &rt5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strAttTime, &rt6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strLate, &rt7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strEarlier, &rt8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strAbsent, &rt9, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(strLeave, &rt10, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
//下橫線
memDC.MoveTo(rc.left, rc.bottom);
memDC.LineTo(rc.right, rc.bottom);
memDC.MoveTo(rt1.right, rt1.top);
memDC.LineTo(rt1.right, rt1.bottom);
memDC.MoveTo(rt2.right, rt1.top);
memDC.LineTo(rt2.right, rt1.bottom);
memDC.MoveTo(rt3.right, rt1.top);
memDC.LineTo(rt3.right, rt1.bottom);
memDC.MoveTo(rt4.right, rt1.top);
memDC.LineTo(rt4.right, rt1.bottom);
memDC.MoveTo(rt5.right, rt1.top);
memDC.LineTo(rt5.right, rt1.bottom);
memDC.MoveTo(rt6.right, rt1.top);
memDC.LineTo(rt6.right, rt1.bottom);
memDC.MoveTo(rt7.right, rt1.top);
memDC.LineTo(rt7.right, rt1.bottom);
memDC.MoveTo(rt8.right, rt1.top);
memDC.LineTo(rt8.right, rt1.bottom);
memDC.MoveTo(rt9.right, rt1.top);
memDC.LineTo(rt9.right, rt1.bottom);
memDC.MoveTo(rc.left, rt1.bottom);
memDC.LineTo(rc.right, rt1.bottom);
rc.top += fAdd;
rc.bottom += fAdd;
rt1.top = rc.top;
rt1.bottom = rc.bottom;
rt2.top = rt1.top;
rt2.bottom = rt1.bottom;
rt3.top = rt1.top;
rt3.bottom = rt1.bottom;
rt4.top = rt1.top;
rt4.bottom = rt1.bottom;
rt5.top = rt1.top;
rt5.bottom = rt1.bottom;
rt6.top = rt1.top;
rt6.bottom = rt1.bottom;
rt7.top = rt1.top;
rt7.bottom = rt1.bottom;
rt8.top = rt1.top;
rt8.bottom = rt1.bottom;
rt9.top = rt1.top;
rt9.bottom = rt1.bottom;
rt10.top = rt1.top;
rt10.bottom = rt1.bottom;
if((i+iStart+1)>=nCountItem)
break;
}
//結尾
memDC.MoveTo(rc.left, nTop);
memDC.LineTo(rc.left, rc.top);
memDC.MoveTo(rc.right, nTop);
memDC.LineTo(rc.right, rc.top);
memDC.DrawText(csLFinality, &rc, DT_LEFT| DT_VCENTER | DT_SINGLELINE);
memDC.DrawText(csRFinality, &rc, DT_RIGHT| DT_VCENTER | DT_SINGLELINE);
memDC.SelectObject(oldfont);
memDC.SelectObject(hPenOld);
}
TitleFont.DeleteObject();
DetailFont.DeleteObject();
cPen.DeleteObject();
}
