VC打印机编程之两篇有用的文章获取打印机与打印作业的状态和设置打印机模式并预览打印

VC打印机编程之两篇有用的文章


vc设置打印机模式并预览打印  

调用打印属性对话框:
if(::OpenPrinter("Adobe PDF", &hPrint, NULL))
{
::PrinterProperties(m_hWnd, hPrint);
::ClosePrinter(hPrint);
}
注:通过EnumPrinters可以枚举全部的本地、网络打印机信息,通过指定以上的方法,可以打开打印机属性对话框,建议通过以上方法修改打印机固定属性,比较安全。
枚举打印机
需要调用两次EnumPrinters函数,第一次的到结构体的大小,第二次得到打印机列表
DWORD dwNeeded, dwReturn;
// 得到结构大小
BOOL bl = ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0,&dwNeeded, &dwReturn);


// 得到打印机设备列表
PRINTER_INFO_4* p4;
p4 = (PRINTER_INFO_4*)malloc(dwNeeded);
::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (PBYTE)p4, dwNeeded,&dwNeeded, &dwReturn);
for(int i=0;i< div> < dwNeeded;i++)
{
TRACE("This is printer name : %s\r\n", p4[i].pPrinterName);
}
// 注意以上代码,NT以上系统支持,98不支持
最简单的一段打印程序
流程:
1、得到默认打印机名称(如果你不打算更改打印机的话,就不需要保存该选项)
2、保存默认打印机名称
3、设定新的默认打印机
4、取得默认打印机的选项
5、修改属性,如纸张选择,横纵等。6、打印输出
7、还原默认打印设备
// 得到默认打印设备名称
CString strDefualtDev = TEXT("");
PRINTDLG pd;
LPDEVMODE lpDevMode;
if(AfxGetApp()->GetPrinterDeviceDefaults(&pd))
{
lpDevMode=(LPDEVMODE)GlobalLock(pd.hDevMode);
if(lpDevMode)

strDefualtDev = lpDevMode->dmDeviceName;
}
GlobalUnlock(pd.hDevMode);
}
// 指定的打印机名称
::SetDefaultPrinter("Adobe PDF");  // 在这里我选择的打印机是选定的Adobe虚拟打印机
// 得到刚刚设定的打印机名称
if(AfxGetApp()->GetPrinterDeviceDefaults(&pd))   
{
lpDevMode=(LPDEVMODE)GlobalLock(pd.hDevMode);       
if(lpDevMode)

lpDevMode->dmPaperSize=DMPAPER_A4;    // 设定打印纸张幅面
lpDevMode->dmOrientation=DMORIENT_LANDSCAPE; // 设定横向打印
lpDevMode->dmPrintQuality=600;     // 设定打印机分辨率
}  
GlobalUnlock(pd.hDevMode);
}
DOCINFO di;
memset( &di, 0, sizeof(DOCINFO) );
di.cbSize = sizeof(DOCINFO); 
di.lpszDocName = "Bitmap Printing Test"; // 设定打印文档名称
di.lpszOutput = (LPTSTR) NULL; 
di.fwType = 0; 
// Begin a print job by calling the StartDoc function. 
int nError;
HDC hdc = ::CreateDC(NULL, "Adobe PDF", NULL, lpDevMode); // 得到打印机设备句柄
if(hdc != NULL)
{
if((nError = StartDoc(hdc, &di)) > 0)
{
if(StartPage(hdc)>0)
{
int xPage = ::GetDeviceCaps(hdc, HORZRES); // 得到可打印纸张的高度
int yPage = ::GetDeviceCaps(hdc, VERTRES); // 得到可打印纸张的宽度
// 在一下地方进行打印输出
if(EndPage(hdc)>0) // 只有结束页成功了才可以关闭文档
EndDoc(hdc); // 关闭打印文档
}
}
}
/// 还原默认的打印设备设定
::SetDefaultPrinter(strDefualtDev); 


/////////////////////////开始调取打印机-operation 001 ////////////////////////////////////
PRINTDLG printInfo;
ZeroMemory(&printInfo,sizeof(printInfo));  //清空该结构
printInfo.lStructSize = sizeof(printInfo);   
printInfo.hwndOwner = 0;   
printInfo.hDevMode = 0;
printInfo.hDevNames = 0;
//这个是关键,PD_RETURNDC 如果不设这个标志,就拿不到hDC了
//            PD_RETURNDEFAULT 这个就是得到默认打印机,不需要弹设置对话框
printInfo.Flags = PD_RETURNDC | PD_RETURNDEFAULT;  


PrintDlg(&printInfo);//调用API拿出默认打印机
DWORD rst = CommDlgExtendedError();//看看出错没有
if(rst != 0)
{//出错了,清空标志再次调用API,此时就会弹出打印设置对话框供用户选择了
MessageBox("默认打印机调取失败,请手动选择!");
printInfo.Flags = 0;
PrintDlg(&printInfo);
}
////////////////////////////001- end ////////////////////////////////////////////
////////////////////自定义纸张大小//////////////////////////////////////////////////
/*
//首先得到DEVMODE结构,同时申请系统锁定,我们要修改它了
LPDEVMODE lpDevMode = (LPDEVMODE)::GlobalLock(printInfo.hDevMode);
if(lpDevMode)  //成功得到该结构了
{
lpDevMode->dmPaperSize = DMPAPER_USER;  //自定义纸张


  //设定自定义纸张标志
  lpDevMode->dmFields = lpDevMode ->dmFields | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH; 
  
lpDevMode->dmPaperWidth = (short)width; //纸宽多少
lpDevMode->dmPaperLength = (short)height; //纸高多少

 //顺便设定纸张走纸方向,横向还是纵向
 lpDevMode->dmOrientation = DMORIENT_PORTRAIT;
 }
 //记住要解锁
 GlobalUnlock(printInfo.hDevMode);
 
//这个也不能忘了,否则更改不会生效
ResetDC(printInfo.hDC, lpDevMode);
*/
HDC printDC=printInfo.hDC; //得到打印DC,输出到打印,
CDC cdc;
cdc.Attach(printDC);


得到了 dc之后就不用我再说了吧,自己搞定就是了,
————————————————————————————————————————————————
void   PrintTest()   
{   
CPrintDialog   pd(FALSE,   PD_ALLPAGES   |   PD_COLLATE   |   PD_NOPAGENUMS   |   
PD_HIDEPRINTTOFILE);   
if(pd.GetDefaults())   
{   
DOCINFO   di;   
memset(   &di,   0,   sizeof(DOCINFO)   );   
di.cbSize   =   sizeof(DOCINFO);     
di.lpszDocName   =   "Printing   Test";     
di.lpszOutput   =   (LPTSTR)   NULL;     
di.fwType   =   0;     
HDC   hDC=pd.CreatePrinterDC();   
CDC   dc;   
dc.Attach(hDC);   
dc.StartDoc(&di);     
dc.StartPage();     
dc.MoveTo(0,0);   
dc.LineTo(1000,1000);   
dc.EndPage();     
dc.EndDoc();       
dc.DeleteDC();     
}   



HDC hdcPrint = GetDefaultPrinterDC();
CPrintDialog pd(FALSE,PD_ALLPAGES|PD_ALLPAGES|PD_NOPAGENUMS,NULL);
pd.DoModal();
HDC hdcPrint = pd.CreatePrinterDC();
if(hdcPrint == NULL)
{
MessageBox("打印机初始化失败!", "错误", MB_ICONSTOP);
return;
}




/*   设置系统打印模式                 
#define   DMORIENT_PORTRAIT       1       //纵向   
#define   DMORIENT_LANDSCAPE     2       //横向                                           


*/   
/************************************************************************/   
void   CXTReportApp::SetLandscapeMode(int   PrintMode)   
{   
PRINTDLG   pd;   
pd.lStructSize=(DWORD)sizeof(PRINTDLG);   
BOOL   bRet=GetPrinterDeviceDefaults(&pd);   
if(bRet)   
{   
//   protect   memory   handle   with   ::GlobalLock   and   ::GlobalUnlock   
DEVMODE   FAR   *pDevMode=(DEVMODE   FAR   *)::GlobalLock(m_hDevMode);   
//   set   orientation   to   landscape   
if(PrintMode==1)//纵向打印   
pDevMode->dmOrientation=DMORIENT_PORTRAIT;   
else   if(PrintMode==2)//横向打印   
pDevMode->dmOrientation=DMORIENT_LANDSCAPE;       
::GlobalUnlock(m_hDevMode);   
}   





extern void DrawInfo(CDC &memDC, PRNINFO PrnInfo);


extern UINT m_nCxSelected ;


BOOL PrintSetup(HWND hParent, BOOL bDefault = FALSE);


BOOL Print(HWND hParent, LPCTSTR lpszDocName = "PrintListCtrl", BOOL bDefault = FALSE);


BOOL CPrintListCtrl::PrintSetup(HWND hParent, BOOL bDefault)
{
PRINTDLG stPD;

memset(&stPD, 0, sizeof(stPD));

stPD.lStructSize = sizeof(stPD);
stPD.hwndOwner   = hParent;
stPD.Flags       = PD_ALLPAGES | PD_DISABLEPRINTTOFILE |
PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
stPD.hDevNames   =  NULL;
stPD.hDevMode    = bDefault ? NULL : m_hDevMode;

if (bDefault)
{
stPD.Flags |= PD_RETURNDEFAULT;
}

BOOL bRet = PrintDlg(&stPD);

if (bRet == FALSE && CommDlgExtendedError()) return FALSE;

if (bRet == FALSE && !CommDlgExtendedError()) return TRUE;

ClearPrintDC();

m_hPrintDC = stPD.hDC;

return (m_hPrintDC != NULL);
}



第2篇

VC 获取打印机与打印作业的状态




#pragma comment(lib, "winspool.lib")
#include "stdafx.h"
#include <winspool.h>
#ifndef _MAX_PATH
#define _MAX_PATH 260
#endif
TCHAR m_tchPrinterMessage[_MAX_PATH];///< 打印结果的返回信息


/// 获取打印作业的状态
BOOL GetJobs(HANDLE hPrinter,
JOB_INFO_2 **ppJobInfo,
int *pcJobs,           
DWORD *pStatus)        
{
DWORD       cByteNeeded, nReturned, cByteUsed;
JOB_INFO_2          *pJobStorage = NULL;
PRINTER_INFO_2       *pPrinterInfo = NULL;

if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded))
{
DWORD dwErrorCode = ::GetLastError();
if (dwErrorCode != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
}
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
if (!(pPrinterInfo))
return FALSE;

if (!GetPrinter(hPrinter,
2,
(LPBYTE)pPrinterInfo,
cByteNeeded,
&cByteUsed))
{

free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}

if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
NULL,
0,
(LPDWORD)&cByteNeeded,
(LPDWORD)&nReturned))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
}
pJobStorage = (JOB_INFO_2 *)malloc(cByteNeeded);
if (!pJobStorage)
{

free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
ZeroMemory(pJobStorage, cByteNeeded);

if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
(LPBYTE)pJobStorage,
cByteNeeded,
(LPDWORD)&cByteUsed,
(LPDWORD)&nReturned))
{
free(pPrinterInfo);
free(pJobStorage);
pJobStorage = NULL;
pPrinterInfo = NULL;
return FALSE;
}

*pcJobs = nReturned;
*pStatus = pPrinterInfo->Status;
*ppJobInfo = pJobStorage;
free(pPrinterInfo);
return TRUE;
}


/// 检测打印机的状态
/// hPrinter表示打印机Handle
BOOL CheckPrinterStatus(HANDLE hPrinter)
{
BOOL bResult = PRINT_NOT_EXIST;
if(NULL == hPrinter)
{
_tcscpy(m_tchPrinterMessage,_TEXT("打印机不存在!"));
return bResult;
}
bResult = PRINT_FALSE;
JOB_INFO_2  *pJobs;
int         cJobs,i;
DWORD       dwPrinterStatus;

if (!GetJobs(hPrinter, &pJobs, &cJobs, &dwPrinterStatus))
{
_tcscpy(m_tchPrinterMessage,_TEXT("打印失败!"));
return bResult;
}
//
//if (dwPrinterStatus &
// (PRINTER_STATUS_ERROR |     //打印出错
// PRINTER_STATUS_PAPER_JAM |        //卡纸
// PRINTER_STATUS_PAPER_OUT |
// PRINTER_STATUS_PAPER_PROBLEM |   //打印纸出现问题
// PRINTER_STATUS_OUTPUT_BIN_FULL |  //打印输出已满
// PRINTER_STATUS_NOT_AVAILABLE |   //打印机不可用
// PRINTER_STATUS_NO_TONER |    //没有墨粉
// PRINTER_STATUS_OUT_OF_MEMORY |   //打印内存出错
// PRINTER_STATUS_OFFLINE |    //未联机
// PRINTER_STATUS_DOOR_OPEN))    //打印机的门是开的
//{
// free( pJobs );
// _tcscpy(m_tchPrinterMessage,_TEXT("打印出错!"));
// return bResult;
//}
/// 正在打印
if(dwPrinterStatus & PRINTER_STATUS_PRINTING)
{
_tcscpy(m_tchPrinterMessage,_TEXT("正在打印..."));
bResult = PRINT_GOING;
}
else if(dwPrinterStatus & PRINTER_STATUS_PAUSED)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印暂停中..."));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_BUSY)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机繁忙,/n被临时占用"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_WAITING)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印等待中..."));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_SERVER_OFFLINE)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("未连接打印机服务器"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_ERROR)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印出错!"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_PAPER_JAM)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机卡纸"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_PAPER_OUT)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印纸位置不正确"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_PAPER_PROBLEM)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印纸出现问题"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_OUTPUT_BIN_FULL)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印输出已满"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_NOT_AVAILABLE)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机不可用"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_TONER_LOW)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机墨粉不足"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_NO_TONER)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机没有墨粉"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_OUT_OF_MEMORY)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印内存溢出"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_OFFLINE)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("无法连接打印机,\n可能是打印机未启动"));
return bResult;
}
else if(dwPrinterStatus & PRINTER_STATUS_DOOR_OPEN)
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印机的门是开着的,\n请关闭"));
return bResult;
}

for (i = 0; i < cJobs; ++i)
{
/// 如果打印页正在打印
if (pJobs[i].Status & JOB_STATUS_PRINTING)
{
_tcscpy(m_tchPrinterMessage,_TEXT("正在打印..."));

if (pJobs[i].Status &
(JOB_STATUS_ERROR |
JOB_STATUS_OFFLINE |
JOB_STATUS_PAPEROUT |
JOB_STATUS_BLOCKED_DEVQ))
{
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印出错!"));
return bResult;
}
}
///// 如果打印页已经打印或删除
//if(pJobs[i].Status &
// (JOB_STATUS_PRINTED|
//  JOB_STATUS_DELETED))
//{
// free( pJobs );
// ::ClosePrinter(m_hPrintHandle);
// return PRINT_END;
//}
/// 如果打印页已经打印
if(pJobs[i].Status & JOB_STATUS_PRINTED)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
_tcscpy(m_tchPrinterMessage,_TEXT("打印成功!"));
bResult = PRINT_TRUE;
return bResult;
}
/// 如果已经删除打印作业
else if(pJobs[i].Status & JOB_STATUS_DELETED)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
_tcscpy(m_tchPrinterMessage,_TEXT("已取消打印"));
bResult = PRINT_TRUE;
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_PAUSED)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业暂停..."));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_ERROR)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业出错"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_SPOOLING)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业脱机"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_SPOOLING)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业脱机"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_OFFLINE)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业未连接"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_PAPEROUT)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印纸位置不正确"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_BLOCKED_DEVQ)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业出错"));
return bResult;
}
else if(pJobs[i].Status & JOB_STATUS_RESTART)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_FALSE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印作业重新启动"));
return bResult;
}
#if (NTDDI_VERSION >= NTDDI_WINXP)
else if(pJobs[i].Status & JOB_STATUS_COMPLETE)
{
free( pJobs );
::ClosePrinter(m_hPrintHandle);
bResult = PRINT_TRUE;
_tcscpy(m_tchPrinterMessage,_TEXT("打印完成"));
return bResult;
}
#endif // (NTDDI_VERSION >= NTDDI_WINXP)
 }
 /// 如果不存在打印任务
 if(0 == cJobs)
 {
free( pJobs );
_tcscpy(m_tchPrinterMessage,_TEXT("打印结束,\n当前无打印任务!"));
bResult = PRINT_TRUE;
return bResult;
 }
 
 free( pJobs );
 _tcscpy(m_tchPrinterMessage,_TEXT("打印成功!"));
 bResult = PRINT_TRUE;
 return bResult;
}



关于 打印机的一些操作函数和疑问:

根据打印机的名称可以打开打印机,并且获取打印机的名称。
OpenPrinter
The OpenPrinter function retrieves a handle identifying the specified printer or print server. 

BOOL OpenPrinter(
  LPTSTR pPrinterName, // pointer to printer or server name
  LPHANDLE phPrinter,  // pointer to printer or server handle
  LPPRINTER_DEFAULTS pDefault 
                       // pointer to printer defaults structure
);

GetPrinter
The GetPrinter function retrieves information about a specified printer. 
BOOL GetPrinter(
  HANDLE hPrinter,    // handle to printer of interest
  DWORD Level,        // version of printer info data structure
  LPBYTE pPrinter,    // pointer to array of bytes that receives 
                      // printer info structure
  DWORD cbBuf,        // size, in bytes, of the pPrinter buffer
  LPDWORD pcbNeeded   // pointer to variable with count of bytes 
                      // retrieved (or required)
);

但是操作过上面的两个函数后该怎么使用打印机呢?

关闭打印机
ClosePrinter
The ClosePrinter function closes the specified printer object. 

BOOL ClosePrinter(
  HANDLE hPrinter   // handle to printer object
);

你可能感兴趣的:(VC打印机编程之两篇有用的文章获取打印机与打印作业的状态和设置打印机模式并预览打印)