www.gusucode.com > VC++直接传输数据到打印机-源码程序 > VC++直接传输数据到打印机-源码程序/code/func.cpp
// Filename: OutPrn.cpp #include "stdafx.h" #include <ctype.h> #include <string.h> #include <winspool.h> // Download by http://www.NewXing.com // *******定义变量******** // 定义实际上指向ADDJOB_INFO_1 // 结构的指针 LPBYTE pJob=0; //打印机句柄 HANDLE m_hPrinter=NULL; //********函数定义**************** //获得打印作业的临时文件名和ID号 //并保存在变量pJob所在的空间,成功返 //回true,失败返回false bool GetSpoolFileName( ); //通知系统数据准备就绪,可以输出, //同时释放函数运行中占用的内存 void EndPrint( ) ; //主函数演示怎样调用上面的函数来 //完成将一个文件完整的不变 //的传给外部设备 void Demo( ); bool GetDefaultPrinterName(CString &name) { CPrintDialog pd(TRUE); if(pd.GetDefaults()==FALSE) { AfxMessageBox("Windows系统没有安装缺省打印机"); return false; } name=pd.GetDeviceName(); if (pd.m_pd.hDevNames) { ::GlobalUnlock(pd.m_pd.hDevNames); ::GlobalFree(pd.m_pd.hDevNames); pd.m_pd.hDevNames=NULL; } if (pd.m_pd.hDevMode) { ::GlobalFree(pd.m_pd.hDevMode); pd.m_pd.hDevMode=NULL; } return true; } //********* 函数具体实现 *********** bool GetSpoolFileName() { //定义一些临时变量 DWORD dwNeeded=0; DWORD dwReturned=0; LPBYTE pPrinterEnum=0; BOOL nRet=FALSE; CString name; //获得系统缺省打印机名称首先调用EnumPrinters获得需要 //多大的存储空间来放获得的信息, //该大小写入变量dwNeeded 中 if(GetDefaultPrinterName(name)==false) return false; ::EnumPrinters(PRINTER_ENUM_NAME,NULL,2,NULL,0,&dwNeeded,&dwReturned); if(dwNeeded<=0) return false; //根据前面结果来分配存储空间 pPrinterEnum=new BYTE[dwNeeded]; //再一次调用函数EnumPrinters, //将获得系统缺省打印机 //信息放入pPrinterEnum中。 nRet=::EnumPrinters(PRINTER_ENUM_NAME,NULL,2,pPrinterEnum ,dwNeeded,&dwNeeded,&dwReturned); if(nRet==FALSE ||dwReturned==0) { //没有找到所需要的缺省打印机,函数返回 delete pPrinterEnum; return false; } // 将pPrinterEnum转换为结构 PRINTER_INFO_2的指针 PRINTER_INFO_2 *pInfo=(PRINTER_INFO_2 *)pPrinterEnum; for(DWORD num=0L;num<dwReturned;num++) { if(lstrcmp((LPTSTR)(&(pInfo[num].pDevMode->dmDeviceName[0])),name)==0){ break;} } if(num>=dwReturned) return false; //根据结构PRINTER_INFO_2中包含的打印机名称来打开该打印机并 //将获得的句柄保存在变量 m_hPrinter中 if(!::OpenPrinter(pInfo[num].pPrinterName,&m_hPrinter,NULL)) { //打开打印机失败,函数返回 AfxMessageBox("打开打印机失败"); //释放内存 delete pPrinterEnum; m_hPrinter=NULL; return false; } //下面不再需要,释放所占用的内存 delete pPrinterEnum; //使用函数AddJob 来获得新添加的打印作业的临时文件名和对应的ID号 dwNeeded=0; ASSERT(pJob==NULL); //分配空间用来存放结构 ADDJOB_INFO_1所包含的信息注意不要利用AddJob函数自动检 //测需要多大的空间来存 pJob=new BYTE[2048]; //放ADDJOB_INFO_1所包含的信息,该函数的返回值本人测试了几次 //都不正确自己给它分配2K的内存足够了。 BOOL flag=::AddJob( m_hPrinter,1,pJob,2048,&dwNeeded); if(!flag) {//函数不成功返回 delete []pJob;//释放内存 pJob=0; AfxMessageBox("分配内存失败"); ::ClosePrinter( m_hPrinter); m_hPrinter=NULL; return false; } return true; } // *************************** void EndPrint( ) { ASSERT(pJob); //发送消息给打印管理服务器,当 //前的作业可以输出了 ::ScheduleJob( m_hPrinter,((ADDJOB_INFO_1 *)pJob)->JobId ); //释放打印句柄 ClosePrinter( m_hPrinter); m_hPrinter=0; delete []pJob;//释放内存 pJob=0; m_hPrinter=0; } // **************************** void Demo( ) { //调用文件对话框选择一个文件 CFileDialog aDlg(TRUE,NULL,"*.*"); if(aDlg.DoModal()==IDCANCEL ) return; //调用函数生成临时文件和JOB if(!GetSpoolFileName()) return; //将原始数据放入临时文件中 CopyFile(aDlg.GetPathName(), ((ADDJOB_INFO_1 *)pJob)->Path,FALSE); //通知服务器作业准备就绪 EndPrint( ); }