12.4 实 战
本章前面几节介绍了打印的相关知识。为了帮助大家进一步掌握打印的应用,本节提供了两个完整模块演示打印在实际开发中的作用。
12.4.1 实现工作证打印
视频讲解:光盘/TM/Video/12/实现工作证打印.exe
本节需要实现打印工作证的功能。通常数据表中会存储许多员工信息,为了方便进行工作证的填写操作,首先需要从数据表中选择要打印的员工信息,然后再进行打印。下面介绍实例的详细实现过程。
例12.5 实现工作证打印。(实例位置:光盘/TM/Instances/12/例12.5)
(1)创建一个基于对话框的工程,工程名称为PrintWork。向对话框中添加按钮、编辑框、列表视图控件,如图12.7所示。
图12.7 对话框资源设计
(2)在工程的StdAfx.h头文件中使用#import指令导入ADO对象,由于程序中需要对数据库进行操作,因此需要使用ADO对象来操作数据库。
#import "C:/Program Files/Common Files/System/ado/msado15.dll" no_namespace/
rename("EOF","adoEOF")rename("BOF","adoBOF") //导入ADO动态链接库
(3)在应用程序类CDelStudentApp的InitInstance方法中初始化Com库。
::CoInitialize(NULL); //初始化COM环境
(4)在对话框的头文件中定义ADO智能指针和字体对象。
_ConnectionPtr m_pConnection; //连接对象指针
_RecordsetPtr m_pRecordset; //记录集对象指针
CFont m_Font; //字体对象
(5)在对话框初始化时连接数据库,并将数据库中的数据插入到列表中。
BOOL CPrintWorkDlg::OnInitDialog()
{
m_List.SetExtendedStyle(LVS_EX_FLATSB //扁平风格显示滚动条
|LVS_EX_FULLROWSELECT //允许整行选中
|LVS_EX_HEADERDRAGDROP //允许整列拖动
|LVS_EX_ONECLICKACTIVATE //单击选中项
|LVS_EX_GRIDLINES); //画出网格线
//设置列标题及列宽度
m_List.InsertColumn(0,"姓名",LVCFMT_LEFT,120,0);
m_List.InsertColumn(1,"部门",LVCFMT_LEFT,120,1);
m_List.InsertColumn(2,"职务",LVCFMT_LEFT,120,2);
try
{
m_pConnection.CreateInstance("ADODB.Connection"); //创建连接对象实例
bstr_t strConnect="DRIVER={Microsoft Access Driver (*.mdb)};/
uid=;pwd=;DBQ=Database.mdb;";
m_pConnection->Open(strConnect,"","",adModeUnknown); //打开数据库
}
catch (_com_error e) //捕捉错误
{
AfxMessageBox(e.Description()); //弹出错误
}
CString sql = "select * from workcard";
m_pRecordset.CreateInstance(__uuidof(Recordset)); //记录集对象实例化
m_pRecordset->Open(_bstr_t(sql), m_pConnection.GetInterfacePtr(),
adOpenDynamic, adLockOptimistic, adCmdText); //执行SQL得到记录集
while (!m_pRecordset->adoEOF) //记录集不为空时循环
{
m_List.InsertItem(0,""); //向列表视图控件中插入行
//向列表视图控件中插入列
m_List.SetItemText(0,0,(char*)(_bstr_t)m_pRecordset->GetCollect("姓名"));
m_List.SetItemText(0,1,(char*)(_bstr_t)m_pRecordset->GetCollect("部门"));
m_List.SetItemText(0,2,(char*)(_bstr_t)m_pRecordset->GetCollect("职务"));
m_pRecordset->MoveNext(); //将记录集指针移动到下一条记录
}
m_pRecordset->Close(); //关闭记录集
m_pConnection->Close(); //断开数据库连接
m_Font.CreatePointFont(200,"宋体"); //创建字体
m_Static1.SetFont(&m_Font); //设置控件字体
return TRUE;
}
(6)处理列表视图控件的单击事件,在该事件的处理函数中将用户选中的列表项信息插入到编辑框中。
void CPrintWorkDlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
int pos = m_List.GetSelectionMark(); //获得当前选中列表项索引
//获得列表项数据,显示到对应的编辑框中
m_Edit1 = m_List.GetItemText(pos,0);
m_Edit2 = m_List.GetItemText(pos,1);
m_Edit3 = m_List.GetItemText(pos,2);
UpdateData(FALSE);
*pResult = 0;
}
(7)处理“打印”按钮的单击事件,在该事件的处理函数中获得控件的位置和显示文本,并根据位置打印显示文本。
void CPrintWorkDlg::OnButprint()
{
// TODO: Add your control notification handler code here
CDC* pDC = GetDC();
CPrintDialog dlg(false); //定义打印机对话框
dlg.GetDefaults(); //获取打印机默认值
CDC dc;
dc.Attach(dlg.GetPrinterDC()); //关联打印机
double ratex = dc.GetDeviceCaps(LOGPIXELSX) /
pDC->GetDeviceCaps(LOGPIXELSX); //屏幕与打印机分辨率比率(水平方向)
double ratey = dc.GetDeviceCaps(LOGPIXELSY) /
pDC->GetDeviceCaps(LOGPIXELSY); //屏幕与打印机分辨率比率(垂直方向)
dc.StartDoc("print"); //开始打印
CRect rect,framerect;
m_Frame.GetWindowRect(&framerect);
dc.Rectangle(10*ratex,10*ratey,(framerect.Width()+10)*ratex
,(framerect.Height()+10)*ratey); //打印矩形边框
char classname[255];
for (int i=1000;i<1007;i++) //循环控件标识符
{
CWnd *control = this->GetDlgItem(i); //获取控件
if (NULL != control)
{
CString str;
control->GetWindowText(str); //获取显示文本
control->GetWindowRect(&rect); //获取位置
GetClassName(control->GetSafeHwnd(),classname,255);//获取类名
if (strcmp(classname,"Edit") == 0) //判断类型
{
//绘制直线
dc.MoveTo((rect.left-framerect.left+10)*ratex,
(rect.bottom-framerect.top+10)*ratey);
dc.LineTo((rect.right-framerect.left+10)*ratex,
(rect.bottom-framerect.top+10)*ratey);
}
if (str == "工作证")
{
CFont font;
font.CreatePointFont(200*ratex,"宋体"); //创建字体
dc.SelectObject(&font); //选入字体
dc.TextOut((rect.left-framerect.left+10)*ratex
,(rect.top-framerect.top+10)*ratey,str); //输出内容
font.DeleteObject();
}
else
{
CFont font;
font.CreatePointFont(120*ratex,"宋体"); //创建字体
dc.SelectObject(&font); //选入字体
dc.TextOut((rect.left-framerect.left+10)*ratex
,(rect.top-framerect.top+10)*ratey,str); //输出内容
font.DeleteObject();
}
}
}
dc.EndDoc(); //结束打印
}
(8)运行程序,效果如图12.8所示。
图12.8 实现工作证打印
12.4.2 打印对话框及其控件中的数据
视频讲解:光盘/TM/Video/12/打印对话框及其控件中的数据.exe
要实现打印对话框,首先需要获得打印机的设备上下文CDC对象,其次需要将对话框界面存入位图结构中。最后调用API函数中的StretchDIBits函数即可。
获取打印机的设备上下文可以通过打印对话框实现,调用打印对话框的GetPrinterDC方法即可。
例 12.6 打印对话框及其控件中的数据。(实例位置:光盘/ TM/Instances/12/例12.6)
(1)创建一个基于对话框的工程,工程名称为PrintForm。向对话框中添加静态文本、按钮、编辑框和进度条控件,如图12.9所示。
图12.9 对话框设计
(2)处理“打印”按钮单击事件,将对话框保存为位图,并进行打印。
void CPrintFormDlg::OnButprint()
{
CRect m_rect,framerect;
//获取对话框的大小
GetWindowRect(m_rect);
//获取图片控件大小
m_Frame.GetWindowRect(framerect);
int x,y;
x = framerect.left - m_rect.left;
CDC* pImageDC = GetDC();
int formx,formy;
//获得屏幕分辨率
formx = pImageDC->GetDeviceCaps(LOGPIXELSX);
formy = pImageDC->GetDeviceCaps(LOGPIXELSY);
ReleaseDC(pImageDC);
CPrintDialog m_printdlg (FALSE,PD_RETURNDEFAULT); //构造打印对话框
if (m_printdlg.DoModal()==IDOK)
{
CDC pdc;
pdc.Attach(m_printdlg.GetPrinterDC()); //获得打印机设备上下文
//获取打印机与屏幕的分辨率比率
int printerx,printery;
printerx = pdc.GetDeviceCaps(LOGPIXELSX);
printery = pdc.GetDeviceCaps(LOGPIXELSY);
double ratex,ratey;
ratex = (double)printerx/formx;
ratey = (double)printery/formy;
CClientDC dc(this);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc,framerect.Width()+x,framerect.Height()+x);//创建位图
CDC imagedc;
imagedc.CreateCompatibleDC(&dc); //创建兼容画布
imagedc.SelectObject(&bmp);
imagedc.BitBlt(0,0,framerect.Width()+x,framerect.Height()+x,&dc,0,0,SRCCOPY);//绘制位图
BITMAP bmap;
bmp.GetBitmap(&bmap); //获得位图大小
int panelsize = 0;
//非真彩色位图
if (bmap.bmBitsPixel <16)
panelsize = pow(2,bmap.bmBitsPixel*sizeof(RGBQUAD));
//设置BITMAPINFO结构
BITMAPINFO* bInfo = (BITMAPINFO*)LocalAlloc(LPTR,sizeof(BITMAPINFO)+panelsize);
bInfo->bmiHeader.biClrImportant = 0;
bInfo->bmiHeader.biBitCount = bmap.bmBitsPixel;
bInfo->bmiHeader.biCompression = 0;
bInfo->bmiHeader.biHeight = bmap.bmHeight;
bInfo->bmiHeader.biPlanes = bmap.bmPlanes;
bInfo->bmiHeader.biSize = sizeof(BITMAPINFO);
bInfo->bmiHeader.biSizeImage = bmap.bmWidthBytes*bmap.bmHeight;
bInfo->bmiHeader.biWidth = bmap.bmWidth;
bInfo->bmiHeader.biXPelsPerMeter = 0;
bInfo->bmiHeader.biYPelsPerMeter = 0;
char* pData = new char[bmap.bmWidthBytes*bmap.bmHeight];
::GetDIBits(imagedc.m_hDC,bmp,0,bmap.bmHeight,pData,bInfo,DIB_RGB_COLORS);
//打印图像
pdc.StartDoc("print"); //开始打印
::StretchDIBits(pdc.m_hDC,50,50,(int)((framerect.Width()*ratex)+x)
,(int)((framerect.Height()+x)*ratey),0,0,framerect.Width()+x
,framerect.Height()+x,pData,bInfo,DIB_RGB_COLORS,SRCCOPY);
pdc.EndDoc(); //结束打印
LocalFree(bInfo);
delete[] pData;
bmp.DeleteObject();
}
}
(3)运行程序,效果如图12.10所示。
图12.10 打印对话框及其控件中的数据