13.2 打印图形和文字
(1)注册打印异常终止过程 SetAbortProc(hdcPrn,AbortProc);//在StartDoc前注册
(2)异常终止过程——取消打印
①调用时间:当调用EndPage之前,程序每次调用一个GDI函数时,GDI模块会把另一个记录追加到磁盘上的图元文件。当调用EndPage时(也就是把图元文件送设备驱动程序和创建临时打印文件时),GDI会频繁地调用异常终止过程。(如生成临时文件导致磁盘空间不足,会调用该过程,并传入iCode为SP_OUTOFDISK的参数)
②异常终止过程
BOOL CALLBACK AbortProc(HDC hdcPrn, int iCode) { MSG msg; while(!bUserAbort && PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(!hDlgPrint || !IsDialogMessage(hDlgPrint,&msg)) { TranslateMessage(&msg);//本例主窗口被Disable,收不到键盘和鼠标消息,该句可省略 DispatchMessage(&msg); } } return !bUserAbort; }
说明: A、因本例开始打印时,会出现产生自定义的“取消对话框”(非模态的),为了在GDI模块将图元文件送给设备驱动程序时,用户能随时点击“取消”按钮终止打印,得在异常终止过程中用“消息循环”(因为这时程序己进入异常中止过程的处理,要在这个过程中能处理对话框的消息,这时就必须从消息队列中获取消息,并分配出去!),如果用户点击了“取消”,则会把全局变量bUserAbort设为TRUE,从而退出打印。 B、PeekMessage查看消息,可立即返回,而不用等待消息的出现。 C、异常处理过程中当返回TRUE时,继续打印,返回FALSE时终止打印。 D、为防止用户在打印作业开始以后,又选择主菜单中的“Print”菜单项,甚至选择退 |
③打印结束不必去除异常终止过程
【获取打印机设备环境——程序】
/*---------------------------------------------------------------------------------- GETPNTDC.C ——GetPrinterDC function ----------------------------------------------------------------------------------*/ //#pragma warning(disable: 4996) //win8.1以上GetVersion己过时,加上这句关闭句 #include <windows.h> #include <VersionHelpers.h> //VS2013用来判断系统版本的头文件 HDC GetPrinterDC(void) { DWORD dwNeeded, dwReturned; HDC hdc; PRINTER_INFO_4 *pinfo4; PRINTER_INFO_5 *pinfo5; if (!IsWindowsXPOrGreater()) // if (GetVersion() && 0x80000000) //Windows98 { EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, NULL, 0, &dwNeeded, &dwReturned); //获取所需缓冲区的字节数和所需结构体的数量 pinfo5 = malloc(dwNeeded); //分配所需的字节数 EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, (PBYTE)pinfo5, dwNeeded, &dwNeeded, &dwReturned); hdc = CreateDC(NULL, pinfo5->pPrinterName, NULL, NULL); //pinfo5为打1个打印机,pinfo5+1为第2个打印机 free(pinfo5); } else { EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned); pinfo4 = malloc(dwNeeded); EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE)pinfo4, dwNeeded, &dwNeeded, &dwReturned); hdc = CreateDC(NULL, pinfo4->pPrinterName, NULL, NULL); free(pinfo4); } return hdc; } //#pragma warning (default : 4996)
【打印程序框架】
/*------------------------------------------------------------ PRINT.C -- Common routines for Print1,Print2,and Print3 (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL PrintMyPage(HWND); extern HINSTANCE hInst; extern TCHAR szAppName[]; extern TCHAR szCaption[]; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hInst = hInstance; hwnd = CreateWindow(szAppName, // window class name szCaption, // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void PageGDICalls(HDC hdcPrn, int cxPage, int cyPage) { static TCHAR szTextStr[] = TEXT("Hello Printer!"); //画边框 Rectangle(hdcPrn, 0, 0, cxPage, cyPage); //画对角线 MoveToEx(hdcPrn, 0, 0, NULL); LineTo(hdcPrn, cxPage, cyPage); MoveToEx(hdcPrn, cxPage, 0, NULL); LineTo(hdcPrn, 0, cyPage); SaveDC(hdcPrn); SetMapMode(hdcPrn, MM_ISOTROPIC);//各向同性 //将坐标系改为坐标系原点在客户区中心,y向上为正,x、y均为范围(-1000,1000) SetWindowExtEx(hdcPrn, 1000, 1000, NULL); SetViewportExtEx(hdcPrn, cxPage / 2, -cyPage / 2, NULL); //y轴向上为正 SetViewportOrgEx(hdcPrn, cxPage / 2, cyPage / 2, NULL); //画圆(因为是各向同性的) Ellipse(hdcPrn, -500, 500, 500, -500); SetTextAlign(hdcPrn, TA_BASELINE | TA_CENTER); //对齐的基准点要对准基线 TextOut(hdcPrn, 0, 0, szTextStr, lstrlen(szTextStr)); RestoreDC(hdcPrn, -1); } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static int cxClient, cyClient; HMENU hMenu; switch (message) { case WM_CREATE: //在系统菜单中增加"Print"菜单项,菜单ID为1; hMenu = GetSystemMenu(hwnd, FALSE); AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); AppendMenu(hMenu, 0, 1, TEXT("&Print")); //菜单ID=1; return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_SYSCOMMAND: //wParam为菜单ID if (wParam == 1) { if (!PrintMyPage(hwnd)) MessageBox(hwnd, TEXT("Could not print page!"), szAppName, MB_OK | MB_ICONEXCLAMATION); return 0; } break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); PageGDICalls(hdc, cxClient, cyClient); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
【Print1程序】
/*------------------------------------------------------------------ PRINT1.C —— Bare Bones Printing (c) Charles Petzold, 1998 -------------------------------------------------------------------*/ #include <windows.h> HDC GetPrinterDC(void); // in GETPRNDC.C void PageGDICalls(HDC, int, int); // in PRINT.C HINSTANCE hInst; TCHAR szAppName[] = TEXT("Print1"); TCHAR szCaption[] = TEXT("Print Program 1"); BOOL PrintMyPage(HWND hwnd) { static DOCINFO di = { sizeof(DOCINFO), TEXT("Print1:Printing"), TEXT("Print1.prn") }; BOOL bSuccess = TRUE; HDC hdcPrn; int xPage, yPage; if (NULL == (hdcPrn = GetPrinterDC())) { return FALSE; } xPage = GetDeviceCaps(hdcPrn, HORZRES); //水平像素规模 yPage = GetDeviceCaps(hdcPrn, VERTRES); //垂直像素规模 if (StartDoc(hdcPrn, &di)>0) //打印作业开始 { if (StartPage(hdcPrn)>0) //一页的开始 { PageGDICalls(hdcPrn, xPage, yPage); //打印内容 if (EndPage(hdcPrn) > 0) //一页的结束 EndDoc(hdcPrn); //作业完成 else bSuccess = FALSE; } } else bSuccess = FALSE; DeleteDC(hdcPrn); return TRUE; }
【Print2程序】
/*------------------------------------------- PRINT2.C -- Printing with Abort Procedure (c) Charles Petzold, 1998 -------------------------------------------*/ #include <windows.h> HDC GetPrinterDC(void); //in GETPRNDC.C void PageGDICalls(HDC, int, int); //in PRINT.C HINSTANCE hInst; TCHAR szAppName[] = TEXT("Print2"); TCHAR szCaption[] = TEXT("Print Program 2(Abort Procedure)"); BOOL CALLBACK AbortProc(HDC hdcPrn, int iCode) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } return TRUE; } BOOL PrintMyPage(HWND hwnd) { static DOCINFO di = { sizeof(DOCINFO), TEXT("Print2:Printing") }; HDC hdcPrn; BOOL bSuccess = TRUE; short xPage, yPage; if (NULL == (hdcPrn = GetPrinterDC())) { return FALSE; } xPage = GetDeviceCaps(hdcPrn, HORZRES); yPage = GetDeviceCaps(hdcPrn, VERTRES); EnableWindow(hwnd, FALSE); SetAbortProc(hdcPrn, AbortProc); if (StartDoc(hdcPrn, &di) > 0) { if (StartPage(hdcPrn) > 0) { PageGDICalls(hdcPrn, xPage, yPage); if (EndPage(hdcPrn) > 0) EndDoc(hdcPrn); else bSuccess = FALSE; } } else bSuccess = FALSE; EnableWindow(hwnd, TRUE); DeleteDC(hdcPrn); return bSuccess; }
时间: 2024-10-22 02:23:08