/////////////////////////////////////////////////////////////////////// // PrintRX.cpp: implementation of the CPrintRX class. // // It is written by Robin-Fox, (2004-03-03)it is free to use; // // I am glad it will give you some help in learning do printing. // // and i will also be glad that you make it works better though your // // rewrite.let the open sourse project make the world better. // // ----in BeiJing // /////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "YLGL.h" #include "PrintRX.h" #include "Barcode.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// /* Procedure for use : ========================================================================= 1. Declare an object of CPrintRX. 2. Call the member-function InitToPrint() to choose a Printer and initialize the object. 3. Call the member-function StartPrint(). This function MUST be called immediately after InitToPrint(), before other class-functions are be called. It creats the print-document in the printer-spooler (at the end EndPrint() will be called, in order to release it). 4. Add the fonts, which are needed, with the member-function AddFont(). Principle it is enough to generate one font. The function returns a handle of the type int, which is then needed from various other member-functions. For each necessary font the function must be called once. There are only 10 different fonts possible.After this function you should call SetFontFace() then. Default is m_Fonts[0][0]. 5. Adjust the margins and the line-space with the member-funktions SetMargins() and SetDistance(). MoveTo() set the point of the cursor aginst of m_Margnis. 6. MoveTo() set the point of the cursor aginst of m_Margnis. 7. Call member-function StartPage(), in order to begin a new page. If the page ends call EndPage(). Should it be necessary to print more lines between the call of these two functions, than on one page fits, the class ensures that that EndPage() is called followed by a StartPage() automaticaly. A possibly necessary head- and footingline are created. 8. Lines are printed with the function DrawHLine() and DrwawVLine(). etc. 9. Call the member-funktion EndPrint(), in order to release the document in the spooler. 10. there are some thing to do to better it, Draw BItamp, etc */ // Construction/Destruction ////////////////////////////////////////////////////////////////////// CPrintRX::CPrintRX() { for (int i=0; i<10; i++) { m_iFace[i] = 0; for (int j=0; j<4; j++) m_font[i][j] = new (CFont); } m_nFonts = 0; m_iFont = 0; m_pPrintDlg = NULL; m_Margins.SetRect(0, 0, 0, 0); m_yCur = 0; m_xCur = 0; m_iPage = 1; m_nCopies = 1; } CPrintRX::~CPrintRX() { deletePrinter(); } void CPrintRX::deletePrinter() // Jeff.add; { for (int i=0; i<10; i++) for (int j=0; j<4; j++) delete (m_font[i][j]); if (m_pPrintDlg) delete (m_pPrintDlg); if(m_newfont.GetSafeHandle()) m_newfont.DeleteObject (); } int CPrintRX::DrawText(char *str, int iFont, int iFace, int format) { m_DC.TextOut(m_xCur, m_yCur, str); m_memdc.TextOut(m_xCur, m_yCur, str); return 1; } void DrawPrintBit(HDC hdc, Image *img, CRect rc) { try { if(img) { Graphics graph(hdc); // SetPageUnit设置graphics对象的页面坐标系测量单位; // SetPageUnit将页面坐标系转换为设备坐标系; graph.SetPageUnit(UnitPixel); // UnitPixel每个页面单位为1个像素,此时页面单位与设备单位相同; // SetSmoothingMode设置graphics对象的渲染质量;SmoothingModeHighQuality平滑模式高质量; graph.SetSmoothingMode(SmoothingModeHighQuality); int width=img->GetWidth(); int height=img->GetHeight(); Rect destinationRect(rc.left , rc.top , rc.Width (), rc.Height ()); graph.DrawImage(img, destinationRect, 0,0,width,height,UnitPixel); } } catch(...) { } } void CPrintRX::SetColor(COLORREF col, COLORREF col2) { if(col==0 && col2==0) { m_DC.SetTextColor (col); m_DC.SetBkColor (0xffffff); m_memdc.SetTextColor (col); m_memdc.SetBkColor (0xffffff); } else { m_DC.SetTextColor (col); m_DC.SetBkColor (col2); m_memdc.SetTextColor (col); m_memdc.SetBkColor (col2); } } void CPrintRX::DrawImage(Image *pImg, CRect& m_rt) { DrawPrintBit( m_DC.GetSafeHdc (), pImg , CRect(CALCX(m_rt.left),CALCY(m_rt.top),CALCX(m_rt.right),CALCY(m_rt.bottom) )); DrawPrintBit( m_memdc.GetSafeHdc (), pImg , CRect(CALCX(m_rt.left),CALCY(m_rt.top),CALCX(m_rt.right),CALCY(m_rt.bottom) )); } void CPrintRX::DrawRect(CRect& m_rt, int col) { m_DC.FillSolidRect (CRect(CALCX(m_rt.left),CALCY(m_rt.top),CALCX(m_rt.right),CALCY(m_rt.bottom) ), col); m_memdc.FillSolidRect (CRect(CALCX(m_rt.left),CALCY(m_rt.top),CALCX(m_rt.right),CALCY(m_rt.bottom) ), col); } int CPrintRX::DrawText(char *str, CRect& m_rt, int iFont, int iFace, int format) { SIZE Size; GetTextExtentPoint32(m_DC.GetSafeHdc(), str, strlen(str), &Size); int left, top; if (format & FORMAT_HCENTER) // 水平居中; { left = CALCX(m_rt.left) + CALCX(m_rt.Width())/2 - Size.cx/2; if (left < CALCX(m_rt.left)) left = CALCX(m_rt.left); } else if(format & FORMAT_RIGHT) // 向右对齐; { left = CALCX(m_rt.left) + CALCX(m_rt.Width()) - Size.cx; if (left < CALCX(m_rt.left)) left = CALCX(m_rt.left); } else // 向左对齐; left = CALCX(m_rt.left); if (format & FORMAT_VCENTER) // 垂直居中 { top = CALCY(m_rt.top) + CALCY(m_rt.Height())/2 - Size.cy/2; if (top < CALCY(m_rt.top)) top = CALCY(m_rt.top); } else top = CALCY(m_rt.top); m_DC.TextOut(left, top, str); m_memdc.TextOut(left, top, str); return 1; } int CPrintRX::DrawHLine(int x_left, int y_left, int x_right, int y_right) { m_DC.MoveTo(CALCX(m_Margins.left + x_left), CALCY(m_Margins.top + y_left)); m_DC.LineTo(CALCX(m_Margins.left + x_right), CALCY(m_Margins.top + y_right)); m_memdc.MoveTo(CALCX(m_Margins.left + x_left), CALCY(m_Margins.top + y_left)); m_memdc.LineTo(CALCX(m_Margins.left + x_right), CALCY(m_Margins.top + y_right)); return 0; } int CPrintRX::DrawHLine(int x_left, int y_left, int x_right, int y_right, CPen &newpen) { CPen* oldPen = m_DC.SelectObject(&newpen); m_DC.MoveTo(CALCX(m_Margins.left + x_left), CALCY(m_Margins.top + y_left)); m_DC.LineTo(CALCX(m_Margins.left + x_right), CALCY(m_Margins.top + y_right)); m_DC.SelectObject(oldPen); oldPen = m_memdc.SelectObject(&newpen); m_memdc.MoveTo(CALCX(m_Margins.left + x_left), CALCY(m_Margins.top + y_left)); m_memdc.LineTo(CALCX(m_Margins.left + x_right), CALCY(m_Margins.top + y_right)); m_memdc.SelectObject(oldPen); return 0; } void CPrintRX::DrawRect2(CRect &rc, int mode) { if(mode==0)return; else if(mode==1) { DrawHLine(rc.left , rc.top , rc.right , rc.top ); DrawHLine(rc.left , rc.bottom , rc.right , rc.bottom ); DrawVLine(rc.left , rc.top , rc.left , rc.bottom ); DrawVLine(rc.right , rc.top , rc.right , rc.bottom ); } else if(mode==2) { DrawHLine(rc.left , rc.bottom , rc.right , rc.bottom ); } } int CPrintRX::DrawVLine(int x_up, int y_up, int x_bottom, int y_bottom) { m_DC.MoveTo(CALCX(m_Margins.left + x_up), CALCY(m_Margins.top + y_up)); m_DC.LineTo(CALCX(m_Margins.left + x_bottom), CALCY(m_Margins.top + y_bottom)); m_memdc.MoveTo(CALCX(m_Margins.left + x_up), CALCY(m_Margins.top + y_up)); m_memdc.LineTo(CALCX(m_Margins.left + x_bottom), CALCY(m_Margins.top + y_bottom)); return 0; } int CPrintRX::DrawVLine(int x_up, int y_up, int x_bottom, int y_bottom, CPen &newpen) { CPen* oldPen = m_DC.SelectObject(&newpen); m_DC.MoveTo(CALCX(m_Margins.left + x_up), CALCY(m_Margins.top + y_up)); m_DC.LineTo(CALCX(m_Margins.left + x_bottom), CALCY(m_Margins.top + y_bottom)); m_DC.SelectObject(oldPen); oldPen = m_memdc.SelectObject(&newpen); m_memdc.MoveTo(CALCX(m_Margins.left + x_up), CALCY(m_Margins.top + y_up)); m_memdc.LineTo(CALCX(m_Margins.left + x_bottom), CALCY(m_Margins.top + y_bottom)); m_memdc.SelectObject(oldPen); return 0; } int CPrintRX::DrawBarCode(IN LPCTSTR lpOrderNum, IN LPCTSTR lpCustomer1, IN LPCTSTR lpCustomer2, IN LPCTSTR lpProduct, IN LPCTSTR lpAutoId) { CString strtemp = _T(""); strtemp.Format(_T("#%s"), lpAutoId); printf("--------------\n\t条码:%s\n",strtemp); Barcode128 code; code.SetRatio(1); // Code128B code.Encode128B(strtemp); COLORREF clrBar = RGB(0,0,0); COLORREF clrSpace = RGB(255,255,255); int nStartX; // 打印区域的 x 坐标起始位置; int nStartY; // 打印区域的 y 坐标起始位置; int nBarHeight; // 打印条码的高度; int nBarHeight2; // 打印条码的高度2; int nPenWidth; // 打印条码的宽度; int nLineSpace; // 行间距; #if 1 // 30*20mm的卷标纸; nStartX = 5; nStartY = 5; nBarHeight = 40; nBarHeight2 = 40; nPenWidth = 2; nLineSpace = 3; #endif #if 0 // 40*50mm的卷标纸; nStartX = 2; nStartY = 2; nBarHeight = 40; nBarHeight2 = 40; nPenWidth = 2; nLineSpace= 20; #endif code.DrawBarcode(m_hPrinter, nStartX, nStartY, nBarHeight, nBarHeight2, clrBar, clrSpace, nPenWidth); LOGFONT log; // 设置为6号字体; log.lfHeight = -MulDiv(6, GetDeviceCaps(m_hPrinter, LOGPIXELSY), 72); log.lfWidth = 0; log.lfEscapement = 0; log.lfOrientation = 0; log.lfWeight = FW_REGULAR; log.lfItalic = false; log.lfUnderline = false; log.lfStrikeOut = 0; log.lfCharSet = ANSI_CHARSET; log.lfOutPrecision = OUT_DEFAULT_PRECIS; log.lfClipPrecision = CLIP_DEFAULT_PRECIS; log.lfQuality = DEFAULT_QUALITY; log.lfPitchAndFamily = DEFAULT_PITCH || FF_ROMAN; strcpy(log.lfFaceName,_T("Arial")); CFont cf; cf.CreateFontIndirect(&log); CFont *oldf = m_DC.SelectObject(&cf); CRect rt; #if 1 // 30*20mm的卷标纸; rt.left = nStartX; rt.top = nBarHeight + 5; rt.right = 300 - nStartX; rt.bottom = 200; #endif #if 0 // 50*40mm的卷标纸; rt.left = 2; rt.top = 45; rt.right = 450; rt.bottom = 100; #endif // 打印AutoId; strtemp.Format(_T("#%s"),lpAutoId); SIZE Size; GetTextExtentPoint32(m_DC.GetSafeHdc(), strtemp, strlen(strtemp), &Size); m_DC.TextOut(rt.left, rt.top, strtemp); m_memdc.TextOut(rt.left, rt.top, strtemp); // 打印订单号; rt.top += Size.cy + nLineSpace; rt.bottom = rt.top + Size.cy; strtemp.Format(_T("%s"),lpOrderNum); GetTextExtentPoint32(m_DC.GetSafeHdc(), strtemp, strlen(strtemp), &Size); m_DC.TextOut(rt.left, rt.top, strtemp); m_memdc.TextOut(rt.left, rt.top, strtemp); // 打印顾客信息; rt.top += Size.cy + nLineSpace; rt.bottom = rt.top + Size.cy; strtemp.Format(_T("%s,%s"),lpCustomer1, lpCustomer2); GetTextExtentPoint32(m_DC.GetSafeHdc(), strtemp, strlen(strtemp), &Size); m_DC.TextOut(rt.left, rt.top, strtemp); m_memdc.TextOut(rt.left, rt.top, strtemp); // 打印商品名; rt.top += Size.cy + nLineSpace; rt.bottom = rt.top + Size.cy; strtemp.Format(_T("%s"),lpProduct); GetTextExtentPoint32(m_DC.GetSafeHdc(), strtemp, strlen(strtemp), &Size); m_DC.TextOut(rt.left, rt.top, strtemp); m_memdc.TextOut(rt.left, rt.top, strtemp); return 0; } int CPrintRX::AddFont(CFont &newfont) { return -1; } int CPrintRX::AddFont(LOGFONT *lf) { if (m_nFonts == 10) return -1; m_font[m_nFonts][FACE_NORMAL]->CreateFontIndirect(lf); lf->lfWeight = FW_BLACK; m_font[m_nFonts][FACE_NORMALBOLD]->CreateFontIndirect(lf); lf->lfWeight = FW_REGULAR; lf->lfHeight = CALCF(25); m_font[m_nFonts][FACE_BIG]->CreateFontIndirect(lf); lf->lfWeight = FW_BLACK; m_font[m_nFonts][FACE_BIGBOLD]->CreateFontIndirect(lf); m_nFonts ++; return 0; } int CPrintRX::SetFontFace(int iFont, BOOL bWeight, CString name) { LOGFONT log; log.lfHeight = CALCF(iFont); //add a kind of fond,let height equles 13 log.lfWidth = 0; log.lfEscapement = 0; log.lfOrientation = 0; if(bWeight) log.lfWeight = FW_BLACK; else log.lfWeight = FW_REGULAR; log.lfItalic = false; log.lfUnderline = false; log.lfStrikeOut = 0; log.lfCharSet = ANSI_CHARSET; log.lfOutPrecision = OUT_DEFAULT_PRECIS; log.lfClipPrecision = CLIP_DEFAULT_PRECIS; log.lfQuality = DEFAULT_QUALITY; log.lfPitchAndFamily = DEFAULT_PITCH || FF_ROMAN; strcpy (log.lfFaceName,name); if(m_newfont.GetSafeHandle ()) m_newfont.DeleteObject (); m_newfont.CreateFontIndirect(&log); m_DC.SelectObject(&m_newfont); m_memdc.SelectObject(&m_newfont); return 0; } int CPrintRX::InitToPrint(char *PrinterName /*= NULL*/, int Copies/* = 1*/,const BOOL bNoShowDlg) { if (m_pPrintDlg == NULL) // delete it in ~CPrintRX() // m_pPrintDlg = new CPrintDialog(FALSE,PD_DISABLEPRINTTOFILE); m_pPrintDlg = new CPrintDialog(FALSE,PD_ALLPAGES|PD_NOPAGENUMS,NULL); //CPrintDialog printDialog(false,PD_ALLPAGES|PD_NOPAGENUMS,NULL); ASSERT(m_pPrintDlg != NULL); if (PrinterName == NULL) // which printer ist desired, and how much copies? { // if (m_pPrintDlg->DoModal() == IDCANCEL) //return (-1); if ( bNoShowDlg == FALSE ) { if(!m_pPrintDlg->GetDefaults()) { return -1; } m_hPrinter = m_pPrintDlg->GetPrinterDC(); m_nCopies = m_pPrintDlg->GetCopies(); } //else // 按默认方式打印; //{ // //m_pPrintDlg-> // m_hPrinter = m_pPrintDlg->GetPrinterDC(); // m_nCopies = m_pPrintDlg->GetCopies(); //} } else // a printer is given by name.. { if (m_PrinterDC.CreateDC(NULL, PrinterName, NULL, NULL) == 0) { m_LastErrNo = PRERR_CANTCREATEPRINTERDC; return (-1); // failed, then set the num of Last Error } m_hPrinter = m_PrinterDC; m_nCopies = Copies; } if (m_DC.Attach(m_hPrinter) == 0) return (-1); m_DC.m_bPrinting = TRUE; if (m_pPrintDlg) delete (m_pPrintDlg); m_pPrintDlg = NULL; LOGFONT log; log.lfHeight = CALCF(4); //add a kind of fond,let height equles 13 // log.lfHeight = CALCF(13); //add a kind of fond,let height equles 13 log.lfWidth = 0; log.lfEscapement = 0; log.lfOrientation = 0; log.lfWeight = FW_REGULAR; log.lfItalic = false; log.lfUnderline = false; log.lfStrikeOut = 0; log.lfCharSet = ANSI_CHARSET; log.lfOutPrecision = OUT_DEFAULT_PRECIS; log.lfClipPrecision = CLIP_DEFAULT_PRECIS; log.lfQuality = DEFAULT_QUALITY; log.lfPitchAndFamily = DEFAULT_PITCH || FF_ROMAN; strcpy (log.lfFaceName,"Arial"); AddFont(&log); m_iFont = 0; //set default font is index of 0 if(m_bmp.m_hObject ) { m_bmp.DeleteObject (); } if(m_memdc.m_hDC==NULL) m_memdc.CreateCompatibleDC (NULL); int width= m_DC.GetDeviceCaps(HORZRES); int height= m_DC.GetDeviceCaps(VERTRES); m_bmp.CreateCompatibleBitmap (&m_DC, width, height); m_memdc.SelectObject (&m_bmp); m_memdc.FillSolidRect (0,0,width, height,0xffffff); return 0; } int CPrintRX::StartPrint() { CString strTitle; // Get the application title DOCINFO di; // Initialise print document details strTitle.LoadString(AFX_IDS_APP_TITLE); ::ZeroMemory(&di, sizeof (DOCINFO)); di.cbSize = sizeof (DOCINFO); di.lpszDocName = strTitle; // Begin a new print job //"winerror.h" #define FAILED(Status) ((HRESULT)(Status)<0) if FAILED(m_DC.StartDoc(&di) == -1) return (-1); // Get the printing extents and store in the m_DimDraw fields m_WorkSize.cx = m_DC.GetDeviceCaps(HORZRES); m_WorkSize.cy = m_DC.GetDeviceCaps(VERTRES); return 0; } int CPrintRX::EndPrint() { m_DC.EndDoc(); // end a print job m_DC.Detach(); // detach the printer DC return 0; } int CPrintRX::SetMargins(int Top, int Bottom, int Left, int Right) { if (Top > 0) m_Margins.top = Top; if (Bottom > 0) m_Margins.bottom = Bottom; if (Left > 0) m_Margins.left = Left; if (Right > 0) m_Margins.right = Right; m_yCur = CALCY(m_Margins.top); m_xCur = CALCX(m_Margins.left); return 0; } void CPrintRX::SetDistance(int punkte) { m_Abstand = punkte; } int CPrintRX::StartPage() { if (m_DC.StartPage() < 0) { m_LastErrNo = PRERR_STARTPAGEFAILED; return (-1); } m_yCur = CALCY(m_Margins.top); m_xCur = CALCX(m_Margins.left); return 0; } void CPrintRX::EndPage() { /* DEVMODE* pDevMode; pDevMode=(DEVMODE*)m_pPrintDlg->GetDevMode(); pDevMode->dmCopies =2; m_DC.ResetDC(pDevMode); */ m_DC.EndPage(); } void CPrintRX::NewPage() { m_DC.EndPage(); m_DC.StartPage(); m_yCur = CALCY(m_Margins.top); m_xCur = CALCX(m_Margins.left); } int CPrintRX::GetWidth() { return MulDiv(m_WorkSize.cx, 72, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSX)); } int CPrintRX::GetStrSize(char *str, CSize &size) { GetTextExtentPoint32(m_DC.GetSafeHdc(), str, strlen(str), &size); size.cx = MulDiv(size.cx, 72, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSX)); size.cy = MulDiv(size.cy, 72, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY)); return 0; } void CPrintRX::MoveTo(int xCur, int yCur) { m_xCur = CALCX(m_Margins.left + xCur); m_yCur = CALCY(m_Margins.right + yCur); } void CPrintRX::CalcuRc(CRect &rc) { rc.left =CALCX(rc.left); rc.right =CALCX(rc.right); rc.top =CALCY(rc.top ); rc.bottom =CALCY(rc.bottom ); } CDC * CPrintRX::GetPDC() { return &m_memdc; } void CPrintRX::GetWidHei(int &w, int &h) { BITMAP bm; m_bmp.GetBitmap (&bm); w=bm.bmWidth ; h=bm.bmHeight ; }