打印

来源:互联网 发布:东莞淘宝美工培训机构 编辑:程序博客网 时间:2024/06/02 17:03

///////////////////////////////////////////////////////////////////////.CPP文件////////////////////////////////////////////
// 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 "Printer.h"
#include "PrintRX.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()
{
 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);
}

int CPrintRX::DrawText(char *str, int iFont, int iFace, int format)
{
 m_DC.TextOut(m_xCur, m_yCur, str);
 return 1;
}

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);

 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));
 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);
#ifdef _DEBUG
 int ii=GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY);
 int jj=MulDiv(x_left, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY), 72);
 jj=MulDiv(x_right, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY), 72);
#endif
 return 0;
}

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));
 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);
 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, int iFace)
{
 ASSERT(iFont < 10);
 ASSERT(iFace < 4);
 m_iFont = iFont;
 m_iFace[m_iFont] = iFace;
 m_DC.SelectObject(m_font[m_iFont][m_iFace[m_iFont]]);
 return 0;
}

int CPrintRX::InitToPrint(char *PrinterName = NULL, int Copies = 1)
{
 if (m_pPrintDlg == NULL)    // delete it in ~CPrintRX()
        m_pPrintDlg = new CPrintDialog(FALSE,PD_DISABLEPRINTTOFILE);

    ASSERT(m_pPrintDlg != NULL);
 
 if (PrinterName == NULL)    // which printer ist desired, and how much copies?
 {
  if (m_pPrintDlg->DoModal() == IDCANCEL)
   return (-1);
  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(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

 return 0;
}

int CPrintRX::StartPrint()
{
 CString   strTitle; // Get the application title
    DOCINFO   di;         // Initialize 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);

 //int i = m_DC.GetDeviceCaps(HORZSIZE);
 //int j=  m_DC.GetDeviceCaps(VERTSIZE);
 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()
{
  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);
}
/////////////////////////////////////.H文件///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// PrintRX.h: interface for the CPrintRX class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PRINTRX_H__592C1902_0E73_4C23_A133_350A66362613__INCLUDED_)
#define AFX_PRINTRX_H__592C1902_0E73_4C23_A133_350A66362613__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//////////////////////////////////////////////////////////////////////////
// caculate the logic x and y, change into physics x and y.(int printer DC)
#define CALCF(x)  (-MulDiv(x, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY), 72))
#define CALCY(y)  (MulDiv(y, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSY), 72))
#define CALCX(x)  (MulDiv(x, GetDeviceCaps(m_DC.m_hDC, LOGPIXELSX), 72))

// each added font can have 4 attributes
#define  FACE_NORMAL   0 
#define  FACE_NORMALBOLD  1
#define  FACE_BIG   2
#define  FACE_BIGBOLD  3

// for Print text, you should let it by left or right, and up or bottom
// these formats can be combined with the | operator
#define FORMAT_NORMAL 0         //default should be by left and top
#define FORMAT_HCENTER 1
#define FORMAT_VCENTER  2
#define FORMAT_RIGHT 4
#define FORMAT_LEFT  8 
#define FORMAT_UP       16
#define FORMAT_BOTTOM   32


// Error-codes
#define PRERR_OK     0
#define PRERR_NOIMAGES    1
#define PRERR_LOADBITMAPFAILED  2
#define PRERR_NOGETOBJECT   3
#define PRERR_NOCOMPATIBLEDC  4
#define PRERR_NOSELECTOBJECT  5
#define PRERR_STRETCHBLTFAILED  6
#define PRERR_STARTPAGEFAILED  7
#define PRERR_CANTCREATEPRINTERDC 8
#define PRERR_NOBITBLT    9
///////////////////////////////////////////////////////////////////////
class CPrintRX 
{
public:
 void MoveTo(int xCur, int yCur);
 int GetStrSize(char *str, CSize& size);
 int GetWidth();
 void NewPage();
 void EndPage();
 int StartPage();
 void SetDistance (int punkte);
 int SetMargins(int Top, int Bottom, int Left, int Right);
 int EndPrint();
 int StartPrint();
 int InitToPrint(char *PrinterName, int Copies);
 int SetFontFace(int iFont, int iFace);
 int AddFont(LOGFONT *lf);
 int AddFont(CFont &newfont);
 int DrawVLine(int x_up, int y_up, int x_bottom, int y_bottom, CPen &newpen);
 int DrawVLine(int x_up, int y_up, int x_bottom, int y_bottom);
 int DrawHLine(int x_left, int y_left, int x_right, int y_right, CPen & newpen);
 int DrawHLine(int x_left, int y_left, int x_right, int y_right);
 int DrawText(char *str, CRect& m_rt, int iFont = 0, int iFace = 0, int format = FORMAT_NORMAL);
 int DrawText(char *str, int iFont = 0, int iFace = 0, int format = FORMAT_NORMAL);
 CPrintRX();
 virtual ~CPrintRX();

private:
 CDC  m_DC;   // device-context for printing
 HDC  m_hPrinter;     // used when given a printer name that chosed
 CDC  m_PrinterDC; // used when no given a printer chosed, you should create it youeself

 CFont* m_font[10][4];  // 10 different fonts with 4 different apperances for each
 int  m_nFonts;  // number of added fonts, max. 10 possible
 int     m_iFont;        // the index of fonts now
 int     m_iFace[10];    // the index of faces in each font now

 int  m_nCopies;     // number of copies, which should printed
 CSize m_WorkSize;  // max width/height, which the printer allowes on the paper
 CRect m_Margins;  // desired margins
 int  m_yCur;   // cursor-position at page during the printing
 int     m_xCur;         // cursor-position at page during the printing
 int  m_Abstand;  // distance of lines in points
 int  m_iPage;  // actual page-number
 int  m_LastErrNo; // contains in error-case the error-number. can get with GetErrorCode()
 CPrintDialog    *m_pPrintDlg; // pointer to a various dialog-class, if desired
};

#endif // !defined(AFX_PRINTRX_H__592C1902_0E73_4C23_A133_350A66362613__INCLUDED_)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CPrinterDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
 CPrintRX m_Print;
 m_Print.InitToPrint(NULL, 1);
 m_Print.StartPrint();
 m_Print.StartPage();
 // start printing the lines
    //二维点阵
 int x_pos[8];
 int y_pos[30];

 int i;
 //设置横坐标
 for (i=0; i<30; i++)
  y_pos[i] = 80 + (24 * i);

    //设置纵坐标
 x_pos[0] = 45;
 x_pos[1] = x_pos[0] + 84;
 x_pos[2] = x_pos[1] + 68;
 x_pos[3] = x_pos[2] + 48;
 x_pos[4] = x_pos[3] + 53;
 x_pos[5] = x_pos[4] + 58;
 x_pos[6] = x_pos[5] + 84;
 x_pos[7] = x_pos[6] + 75;
 
 CPen newPen;
 newPen.CreatePen (PS_SOLID, 3, RGB(0,0,0));
 //打印30行
 for (i = 0; i < 30; i++)
 {
  m_Print.DrawHLine(x_pos[0], y_pos[i], x_pos[7], y_pos[i], newPen);
 }
 //打印8列,其中0和7还有中间的要单独打
 for (i = 0; i<7; i++)
 {
  m_Print.DrawVLine(x_pos[i], y_pos[0], x_pos[i], y_pos[29], newPen);

 }
 m_Print.DrawVLine(x_pos[0], y_pos[0], x_pos[0], y_pos[29], newPen);
 m_Print.DrawVLine(x_pos[7], y_pos[0], x_pos[7], y_pos[29], newPen);
// m_Print.DrawVLine((x_pos[0] + x_pos[7])/ 2, y_pos[1], (x_pos[0] + x_pos[7]) / 2, y_pos[2], newPen);

 CSize Size;
 char m_str[7][10];
 CRect StrRect;              //Draw text in Rect
 strcpy(m_str[0], "发往方向");
 strcpy(m_str[1], "发送手段");
 strcpy(m_str[2], "发者");
 strcpy(m_str[3], "网号");
 strcpy(m_str[4], "收者");
 strcpy(m_str[5], "收时");
 strcpy(m_str[6], "备注");
 for (i=0; i<7; i++)
 {
  StrRect.SetRect(x_pos[i], y_pos[0], x_pos[i+1], y_pos[1]);
  m_Print.DrawText(m_str[i], StrRect, 0, 0, FORMAT_HCENTER | FORMAT_VCENTER);
 }
 // now end the page
 CString FileName;      //发送文件名
 CString SendTime;      //发送时间
 CString Agent;         //代理发送单位
 CString HeaderLeft;    //发送清单名
 CString HeaderRight;   //需发单位表
 CString Title;         //标题

 Title.Format("信息查询一览表");
 m_Print.SetFontFace(0, 3);
 StrRect.SetRect(x_pos[0] + 1, 20, x_pos[7], 56);
 m_Print.DrawText((LPTSTR)(LPCTSTR)Title, StrRect, 0, 0, FORMAT_HCENTER | FORMAT_VCENTER);
 
 //结束打印
 m_Print.EndPage();
 m_Print.EndPrint();
 
}