通过系统提供的打印接口和gdi绘图,实现一个简单的打印类,驱动打印机,可以打印文字,设置文字字体和下划线,用'\n'控制换行。可以在这个基础上添加打印图片、打印一维码和二维码接口。使用如下,
CSystemPrinter Printer;
Printer.StartPrint();
//打印操作,PrintString() or DrawUnderLine();
//以‘\n’结束一行。
Printer.EndPrint();
类的实现
//CSystemPrinter.h
#ifdef __CSYSTEMPRINTER_H__
#define __CSYSTEMPRINTER_H__
//define font param
/*nWeight range in:
*#define FW_DONTCARE 0
#define FW_THIN 100
#define FW_EXTRALIGHT 200
#define FW_LIGHT 300
#define FW_NORMAL 400
#define FW_MEDIUM 500
#define FW_SEMIBOLD 600
#define FW_BOLD 700
#define FW_EXTRABOLD 800
#define FW_HEAVY 900
#define FW_ULTRALIGHT FW_EXTRALIGHT
#define FW_REGULAR FW_NORMAL
#define FW_DEMIBOLD FW_SEMIBOLD
#define FW_ULTRABOLD FW_EXTRABOLD
#define FW_BLACK FW_HEAVY
*/
typedef struct _tagFontParam
{
int nWidth;
int nHeight;
int nWeight;
bool bItalic;
bool bUnderLine;
LPCTSTR szFontName;
_tagFontParam()
{
nWidth=20;
nHeight=30;
nWeight=FW_THIN;
bItalic=false;
bUnderLine=false;
szFontName=_T("宋体");
}
}FontParam;
typedef struct _tagPoint2f
{
double x;
double y;
Point2f()
{
x=0.0;
y=0.0;
}
}Point2f;
class CSystemPrinter
{
public:
CSystemPrinter();
~CSystemPrinter();
protected:
CDC m_PrtDC;
FontParam m_fontParam;
LPCTSTR m_szDocName;
Point2f m_ptInitPos,m_ptCurrentPos;//初始坐标,和目前所在的坐标
SHORT m_nPageWidth;
SHORT m_nPageLength;
protected:
double Cm2UnitH(float yScale, double h);//物理长度转换为设备长度,高cm-->pix
double Cm2UnitW(float xScale, double w);//宽cm-->pix
double RvtCm2UnitH(float yScale, double h);//设备长度转换为物理长度
double RvtCm2UnitW(float xScale, double w);
float GetXScale() ;//水平方向比例
float GetYScale() ;//垂直方向比例
CSize getCharSize();//得到字尺寸
double getTextLength(LPCTSTR szText);//得到字符串的物理宽度
void DrawUnderLine(double xCm,double yCm,double lineWidth=3.5);//画下划线
public:
int GetFontWidth(){return m_fontParam.nWidth;}
void SetFontWidth(int nWidth){m_fontParam.nWidth=nWidth;}
int GetFontHeight(){return m_fontParam.nHeight;}
void SetFontHeight(int nHeight){m_fontParam.nHeight=nHeight;}
void SetFontWeight(int nWeight){m_fontParam.nWeight=nWeight;}
void SetItalic(bool bSet){m_fontParam.bItalic=bSet;}
void SetUnderLine(bool bSet){m_fontParam.bUnderLine=bSet;}
void SetFontFontName(LPCTSTR szFontName){m_fontParam.szFontName=szFontName;}
void SetDocName(LPCTSTR szDocName){m_szDocName=szDocName;}
int StartPrint();
void EndPrint();
void PrintString(double xCm,double yCm,LPCSTR szPrintTxt,int nLineHeight=1,bool bCenterAlign=false);
void SetInitPos(double dX,double dy);
void SetPrintRect(SHORT nPageWidth,SHORT nPageHeight);
Point2f GetCurrentPos(){return m_ptCurrentPos;}
};
#endif
//CSystemPrinter.cpp
CSystemPrinter::CSystemPrinter()
{
}
CSystemPrinter::~CSystemPrinter()
{
}
double CSystemPrinter::Cm2UnitH(float yScale, double h)
{
return h*100/yScale;
}
double CSystemPrinter::Cm2UnitW(float xScale, double w)
{
return w*100/xScale;
}
double CSystemPrinter::RvtCm2UnitH(float yScale, double h)
{
return h*yScale/100;
}
double CSystemPrinter::RvtCm2UnitW(float xScale, double w)
{
return w*xScale/100;
}
float CSystemPrinter::GetXScale()
{
//得到打印机水平方向的DPI
int xDPI = GetDeviceCaps(m_PrtDC.GetSafeHdc(), LOGPIXELSX);
//254.0: 每英寸25.4毫米
return (float)(254.0 / xDPI);
}
float CSystemPrinter::GetYScale()
{
int yDPI = GetDeviceCaps(m_PrtDC.GetSafeHdc(), LOGPIXELSY);
return (float)(254.0 / yDPI);
}
CSize CSystemPrinter::GetCharSize()
{
return m_PrtDC.GetTextExtent(_T("A"), 1);
}
double CSystemPrinter::GetTextLength(LPCTSTR szText)
{
CString strText=szText;
CFont font;
font.CreateFont(m_fontParam.nHeight,m_fontParam.nWidth,
0,0,m_fontParam.nWeight,
m_fontParam.bItalic,m_fontParam.bUnderLine,false,
CHINESEBIG5_CHARSET,OUT_CHARACTER_PRECIS,
CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
FF_MODERN,m_fontParam.szFontName);
CFont *oldFont=m_PrtDC.SelectObject(&font);
int dis=strText.GetLength()*GetCharSize(m_PrtDC).cx;
float xScale=GetXScale(m_PrtDC.GetSafeHdc());
double szLen=RvtCm2UnitW(xScale,dis);
m_PrtDC.SelectObject(oldFont);
font.DeleteObject();
return szLen;
}
void CSystemPrinter::DrawUnderLine(double xCm,double yCm,double lineWidth=3.5)
{
float xScale=GetXScale(m_PrtDC.GetSafeHdc());
float yScale=GetYScale(m_PrtDC.GetSafeHdc());
double x=Cm2UnitW(xScale,xCm);//物理尺寸转换为设备尺寸pix
double y=Cm2UnitH(yScale,yCm);
int width=Cm2UnitW(xScale,lineWidth);//线的长度
//int penWidth=2;
CPen pen(PS_SOLID,5,RGB(0,0,0));
CPen *pOldPen=m_PrtDC.SelectObject(&pen);
m_PrtDC.MoveTo(x,y);
m_PrtDC.LineTo(width,y);
m_PrtDC.SelectObject(pOldPen);
m_ptCurrentPos.x=RvtCm2UnitW(xScale,x);
m_ptCurrentPos.y+=RvtCm2UnitH(yScale,lineWidth);//重新计算行的位置
}
void CSystemPrinter::SetInitPos(double dX,double dy)
{
m_ptInitPos.x=dX;
m_ptInitPos.y=dy;
}
void CSystemPrinter::SetPrintRect(SHORT nPageWidth,SHORT nPageLength)
{
m_nPageWidth=nPageWidth;
m_nPageLength=nPageLength;
}
int CSystemPrinter::StartPrint()
{
CPrintDialog printDlg(FALSE/*,dwflags,NULL*/);
printDlg.GetDefaults();
LPDEVMODE dev = printDlg.GetDevMode();
dev->dmPaperSize=DMPAPER_USER; //用户自定义纸张大小
dev->dmPaperLength=m_nPageLength*10;
dev->dmPaperWidth=m_nPageWidth*10;
dev->dmOrientation=DMORIENT_PORTRAIT;//横向打印
dev->dmScale=100;
dev->dmFields |= DM_PAPERSIZE | DM_PAPERWIDTH
| DM_PAPERLENGTH|DM_ORIENTATION|DM_SCALE;
HDC hPrintDc=printDlg.GetPrinterDC();
if (hPrintDc==NULL)
{
AfxMessageBox(_T("No Printer!"));
return -1;
}
m_PrtDC.Attach(hPrintDc);
m_PrtDC.ResetDC(dev);
m_PrtDC.m_bPrinting=TRUE;
DOCINFO docInfo;
memset(&docInfo, 0, sizeof(docInfo));
docInfo.cbSize = sizeof(docInfo);
docInfo.lpszDocName=m_szDocName;
if (m_PrtDC.StartDoc(&docInfo) < 0)
{
AfxMessageBox(_T("Printer wouldn't initalize"));
return -1;
}
else
{
if (m_PrtDC.StartPage() < 0)
{
AfxMessageBox(_T("Could not start page"));
m_PrtDC.AbortDoc();
return -1;
}
return 0;
}
}
void CSystemPrinter::EndPrint()
{
ASSERT(m_PrtDC.m_hDC!=NULL);
m_PrtDC.EndPage();
m_PrtDC.EndDoc();
}
void CSystemPrinter::PrintString(double xCm,double yCm,LPCSTR szPrintTxt,int nLineHeight,bool bCenterAlign)
{
CString szPrintText=szPrintTxt;
CFont font;
font.CreateFont(m_fontParam.nHeight,m_fontParam.nWidth,
0,0,m_fontParam.nWeight,
m_fontParam.bItalic,m_fontParam.bUnderLine,false,
GB2312_CHARSET,OUT_CHARACTER_PRECIS,
CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
FF_MODERN,m_fontParam.szFontName);
CFont *oldFont=m_PrtDC.SelectObject(&font);
m_PrtDC.SetTextAlign(TA_BOTTOM | TA_LEFT);//设置对齐方式
CSize charSize=GetCharSize(m_PrtDC);//字体尺寸
int textHight=charSize.cy;//字高行距行距
int textWidth=charSize.cx;//字宽
float xScale=GetXScale(m_PrtDC.GetSafeHdc());
float yScale=GetYScale(m_PrtDC.GetSafeHdc());
double x=Cm2UnitW(xScale,xCm);//物理尺寸转换为设备尺寸(像素)
double y=Cm2UnitH(yScale,yCm);
if (bCenterAlign)//中心对齐
{
double lenCm=GetTextLength(m_PrtDC,m_fontParam,strPrintTxt);//字体长度物理尺寸
double len=Cm2UnitW(xScale,lenCm);//转换为像素
int leftMargin=GetDeviceCaps(m_PrtDC.GetSafeHdc(), PHYSICALOFFSETX );//边距
int width=GetDeviceCaps(m_PrtDC.GetSafeHdc(),HORZRES);//dc 宽度
x=(width-leftMargin-len)/2;//中心坐标
}
int nIndex=-1;
while (TRUE) //
{
nIndex = szPrintText.Find(_T("\n"));
if (nIndex>-1)
{
CString strPrint = szPrintText.Left(nIndex);
CString strMessage = szPrintText.Mid(nIndex+1);
m_PrtDC.TextOut(x,y,strPrint);
y += nLineHeight*textHight; //下移一行,行高为字体高度
szPrintText=strMessage;
}
else
{
m_PrtDC.TextOut(x,y,szPrintText);
m_ptCurrentPos.x=RvtCm2UnitW(xScale,x);
m_ptCurrentPos.y=RvtCm2UnitH(yScale,y);
break;
}
}
m_PrtDC.SelectObject(oldFont);
font.DeleteObject();
}