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 #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 );
|