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