13.1 打印基础
13.1.1 打印和后台处理
说明:
(1)此图的GDI模块的程序是16位的,打印驱动程序也是16位的。
(2)spooler为windows提供的后台打印处理程序。可能用户有更好硬件或后台打印处理程序,那么可以去掉Windows自带的spooler,以加快打印速度,因为打印机输出可以不被存储在硬盘上,而是直接输出到打印机,或被硬件或软件后台打印处理程序截获。
(3)如果不使用Windows后台打印处理程序,GDI模块不会把来自设备驱动的打印输出存在文件。而是直接传到打印机并口或串口。
(4)如果打印机驱动程序不要求分带,图元文件也不会被创建,GDI只是把绘图函数直接传给驱动程序。或者也可能是应用程序承担起打印机输出分带的责任,但这样的打印代码将变得非常复杂,这样做的好处是不用产生图元文件,GDI只是负责把每条带的函数传给打印机驱动程序。
13.1.2 打印机设备环境
(1)获取设备环境句柄:
①hdc = Create(NULL,szDeviceName,NULL,pInitializationData);
A、szDeviceName是打印机设备名称
B、pInitializationData一般为NULL
②调用PrintDlg(lppd)产生打印对话框并从结构体的PRINTDLG可获设备环境句柄。
(2)“默认”或“当前”打印机:只能有一台打印机被设为默认打印机。
(3)枚举打印机:EnumPrinters,结果放在PRINTER_INFO_x(x为数字)结构数组中。
参数 |
含义 |
Flags |
PRINTER_ENUM_LOCAL:枚举本地打印机 PRINTER_ENUM_NAME:枚举由name参数指定的打印机。NULL时为可用打印机 PRINTER_ENUM_SHARE:共享打印机 PRINTER_ENUM_DEFAULT:Win95默认的打印机 PRINTER_ENUM_CONNECTIONS:网络连接列表中的打印机 PRINTER_ENUM_NETWORK:枚举通过网络连接的打印机——Level为1 PRINTER_ENUM_REMOTE:通过网络连接的打印机和打印服务器。Level为1 |
Name |
vbNullString表示枚举同本机连接的打印机。否则由标志和级别决定 |
Level |
指定欲枚举结构的类型 1:由name参数标志设置决定 2或5:name为欲对其打印机进行枚举的服务器的名字或为vbNullString 4:PRINTER_ENUM_LOCA、PRINTER_ENUM_CONNECTIONS有效,name须为vbNullString |
pPrinterEnum |
是一个包含PRINTER_ENUM_x结构的缓冲区 |
cbBuf |
pPrinterEnum缓冲区中的字符数量 |
pcbNeeded |
用于保存请求的缓冲区长度,或者实际读入的字节数量 |
pcReturned |
返回pPtrinterEnum缓冲区中PRINTER_ENUM_x结构体的数量。 |
【GetPrinterDC程序】
/*---------------------------------------------------------------------------------- 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)
【效果图】
/*--------------------------------------------------------- DEVCAPS2.C -- Displays Device Capabilities Information(Version 2) (c) Charles Petzold, 1998 ---------------------------------------------------------*/ #include <windows.h> #include "resource.h" #include <VersionHelpers.h> #define IDM_DEVMODE 1000 typedef struct { int iMask; TCHAR* szDesc; } BITS; void DoBaseInfo(HDC, HDC, int, int); void DoOtherInfo(HDC, HDC, int, int); void DoBitCodeCaps(HDC, HDC, int, int, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("DevCaps2"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szDevice[32], szWindowText[64]; static int cxChar, cxCaps, cyChar; static int nCurrentDevice = IDM_SCREEN, nCurrentInfo = IDM_BASIC; DWORD dwNeeded, dwReturned; PRINTER_INFO_4 * pinfo4; PRINTER_INFO_5 * pinfo5; HMENU hMenu; HANDLE hPrint; HDC hdc, hdcInfo; PAINTSTRUCT ps; TEXTMETRIC tm; switch (message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); case WM_SETTINGCHANGE: hMenu = GetSubMenu(GetMenu(hwnd), 0); while (GetMenuItemCount(hMenu) > 1) DeleteMenu(hMenu, 1, MF_BYPOSITION); //获取所有本地和远程打印机 if (!IsWindowsXPOrGreater()) //XP以下 { EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &dwNeeded, &dwReturned); pinfo5 = malloc(dwNeeded); EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, (PBYTE)pinfo5, dwNeeded, &dwNeeded, &dwReturned); for (int i = 0; i < (int)dwReturned; i++) { AppendMenu(hMenu, (i + 1) % 16 ? 0 : MF_MENUBARBREAK, i + 1, pinfo5[i].pPrinterName); } 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); for (int i = 0; i < (int)dwReturned; i++) { AppendMenu(hMenu, (i + 1) % 16 ? 0 : MF_MENUBARBREAK, i + 1, pinfo4[i].pPrinterName); } AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); AppendMenu(hMenu, 0, IDM_DEVMODE, TEXT("Properties")); free(pinfo4); } wParam = IDM_SCREEN; //默认选项 //继续执行下云 case WM_COMMAND: hMenu = GetMenu(hwnd); if (LOWORD(wParam) == IDM_SCREEN || LOWORD(wParam) <IDM_DEVMODE) //选择屏幕或打印机 { CheckMenuItem(hMenu, nCurrentDevice, MF_UNCHECKED); nCurrentDevice = LOWORD(wParam); CheckMenuItem(hMenu, nCurrentDevice, MF_CHECKED); } else if (LOWORD(wParam) == IDM_DEVMODE) //选择属性菜单项 { GetMenuString(hMenu, nCurrentDevice, szDevice, sizeof(szDevice) / sizeof(TCHAR), MF_BYCOMMAND); if (OpenPrinter(szDevice, &hPrint, NULL)) //获取打印机句柄 { PrinterProperties(hwnd, hPrint); ClosePrinter(hPrint); } } //Capabilities 下的菜单项设置 else { CheckMenuItem(hMenu, nCurrentInfo, MF_UNCHECKED); nCurrentInfo = LOWORD(wParam); CheckMenuItem(hMenu, nCurrentInfo, MF_CHECKED); } InvalidateRect(hwnd, NULL, TRUE); return 0; case WM_INITMENUPOPUP: //lParam菜单ID if (lParam == 0) //Device菜单 { EnableMenuItem(GetMenu(hwnd), IDM_DEVMODE, (nCurrentDevice == IDM_SCREEN) ? MF_GRAYED : MF_ENABLED); } return 0; case WM_PAINT: lstrcpy(szWindowText, TEXT("Device Capabilities:")); if (nCurrentDevice == IDM_SCREEN) { lstrcpy(szDevice, TEXT("Display")); hdcInfo = CreateIC(szDevice, NULL, NULL, NULL); } else { hMenu = GetMenu(hwnd); GetMenuString(hMenu, nCurrentDevice, szDevice, sizeof(szDevice), MF_BYCOMMAND); hdcInfo = CreateIC(NULL, szDevice, NULL, NULL); } lstrcat(szWindowText, szDevice); SetWindowText(hwnd, szWindowText); hdc = BeginPaint(hwnd, &ps); SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT)); if (hdcInfo) { switch (nCurrentInfo) { case IDM_BASIC: DoBaseInfo(hdc, hdcInfo, cxChar, cyChar); break; case IDM_OTHER: DoOtherInfo(hdc, hdcInfo, cxChar, cyChar); break; case IDM_CURVE: case IDM_LINE: case IDM_POLY: case IDM_TEXT: DoBitCodeCaps(hdc, hdcInfo, cxChar, cyChar, nCurrentInfo - IDM_CURVE); break; } DeleteDC(hdcInfo); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } void DoBaseInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar) { struct { int iIndex; TCHAR * szDesc; } info[] = { HORZSIZE, TEXT("HORZSIZE Width in millimeters:"), //显示的宽度(mm) VERTSIZE, TEXT("VERTSIZE Height in millimeters:"), //显示的高度(mm) HORZRES, TEXT("HORZRES Width in pixels:"), //(显示的宽度(像素) VERTRES, TEXT("VERTRES Height in raster lines:"), //显示的高度(像素) BITSPIXEL, TEXT("BITSPIXEL Color bits per pixel:"), //每像素的颜色位数(位/像素) PLANES, TEXT("PLANES Number of color planes:"), //调色板的个数 NUMBRUSHES, TEXT("NUMBRUSHES Number of device brushes:"), //设备内置画刷的数量 NUMPENS, TEXT("NUMPENS Number of device pens:"), //设备内置画笔的数量 NUMMARKERS, TEXT("NUMMARKERS Number of device markers:"), //设备内置标记数 NUMFONTS, TEXT("NUMFONTS Number of device fonts:"), //设备内置字体数 NUMCOLORS, TEXT("NUMCOLORS Number of device colors:"), //设备色彩深度(>8位/像素)? PDEVICESIZE, TEXT("PDEVICESIZE Size of device structure:"), //PDEVICE内部结构的大小 ASPECTX, TEXT("ASPECTX Relative width of pixel:"), //用于画线的设备像素的相对宽度 ASPECTY, TEXT("ASPECTY Relative height of pixel:"), //用于画线的设备像素的相对高度 ASPECTXY, TEXT("ASPECTXY Relative diagonal of pixel:"), //画线设备对角线长度 LOGPIXELSX, TEXT("LOGPIXELSX Horizontal dots per inch:"), //每逻辑英寸的水平像素数 LOGPIXELSY, TEXT("LOGPIXELSY Vertical dots per inch:"), //每逻辑英寸的垂直像素数 SIZEPALETTE, TEXT("SIZEPALETTE Number of palette entries:"), //调色板中的入口数 NUMRESERVED, TEXT("NUMRESERVED Reserved palette entries:"), //系统调色板中保留的入口数目 COLORRES, TEXT("COLORRES Actual color resolution:"), //设备的实际颜色分辨率(位/像素) PHYSICALWIDTH, TEXT("PHYSICALWIDTH Printer page pixel width:"), //页面的物理宽度(dpi) PHYSICALHEIGHT, TEXT("PHYSICALHEIGHT Printer page pixel height:"), //页面的物理高度(dpi) PHYSICALOFFSETX, TEXT("PHYSICALOFFSETX Printer page x offset:"), //可打印区的水平偏移 PHYSICALOFFSETY, TEXT("PHYSICALOFFSETY Printer page y offset:") //可打印区的垂直偏移 }; TCHAR szBuffer[80]; for (int i = 0; i<sizeof(info) / sizeof(info[0]); i++) { TextOut(hdc, cxChar, cyChar*(i + 1), szBuffer, wsprintf(szBuffer, TEXT("%-45s%8d"), info[i].szDesc, GetDeviceCaps(hdcInfo, info[i].iIndex))); } } void DoOtherInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar) { static BITS clip[] = { CP_RECTANGLE, TEXT("CP_RECTANGLE Can Clip To Rectangle:") //设备是否支持剪切为一个矩形 }; static BITS raster[] = { RC_BITBLT, TEXT("RC_BITBLT Capable of simple BitBlt:"), //支持BitBlt传送位图函数 RC_BANDING, TEXT("RC_BANDING Requires banding support:"), //需要联合支持 RC_SCALING, TEXT("RC_SCALING Requires scaling support:"), //支持缩放 RC_BITMAP64, TEXT("RC_BITMAP64 Supports bitmaps >64k:"), //支持大于64K位图 RC_GDI20_OUTPUT, TEXT("RC_GDI20_OUTPUT Has 2.0 output calls:"), //支持16位Windows 2.0特征 RC_DI_BITMAP, TEXT("RC_DI_BITMAP Supports DIB to memory:"), //支持SetDIBits和GetDIBits函数 RC_PALETTE, TEXT("RC_PALETTE Supports a palette:"), //支持指定一个基于调色板的设备 RC_DIBTODEV, TEXT("RC_DIBTODEV Supports bitmap conversion:"), //支持SetDIBitsToDevice函数 RC_BIGFONT, TEXT("RC_BIGFONT Supports fonts >64k:"), //字体可大于64K RC_STRETCHBLT, TEXT("RC_STRECTCHBLT Supports StretchBlt:"), //支持StrectBlt函数 RC_FLOODFILL, TEXT("RC_FLOODFILL Supports FloodFill:"), //支持连续填充 RC_STRETCHDIB, TEXT("RC_STRETCHEDIB Supports StretchDIBits:") //支持StretchDIBits函数 }; static TCHAR * szTech[] = { TEXT("DT_PLOTTER(Vector plotter)"), //矢量绘图仪 TEXT("DT_RASDISPLAY (Raster display)"), //光栅显示器 TEXT("DT_RASPRINTER (Raster printer)"), //光栅打印机 TEXT("DT_RASCAMERA (Raster camera)"), //光栅照相机 TEXT("DT_CHARSTREAM (Character stream)"), //字符流 TEXT("DT_METAFILE (Metafile)"), //图元文件 TEXT("DT_DISPFILE (Display file)"), //显示器文件 }; TCHAR szBuffer[80]; //在第1行显示驱动程序版本: TextOut(hdc, cxChar, cyChar, szBuffer, wsprintf(szBuffer, TEXT("%-24s %04XH"), TEXT("DriverVersion:"), GetDeviceCaps(hdcInfo, DRIVERVERSION))); //在第2行设备技术: TextOut(hdc, cxChar, 2 * cyChar, szBuffer, wsprintf(szBuffer, TEXT("%-24s %-40s"), TEXT("Technology:"), szTech[GetDeviceCaps(hdcInfo, TECHNOLOGY)])); //第4行显示设备支持剪切性能的标志 TextOut(hdc, cxChar, 4 * cyChar, szBuffer, wsprintf(szBuffer, TEXT("CLIPCAPS(Clipping capabilities)"))); //第6行开始显示是否支持Clipping capabilities for (int i = 0; i < sizeof(clip) / sizeof(clip[0]); i++) TextOut(hdc, 9 * cxChar, (i + 6)*cyChar, szBuffer, wsprintf(szBuffer, TEXT("%-45s %3s"), clip[i].szDesc, GetDeviceCaps(hdcInfo, CLIPCAPS)&clip[i].iMask ? TEXT("Yes") : TEXT("No"))); //第8行 TextOut(hdc, cxChar, 8 * cyChar, szBuffer, wsprintf(szBuffer, TEXT("RASTERCAPS(Raster capabilities)"))); //第10行显示光栅性能 for (int i = 0; i < sizeof(raster) / sizeof(raster[0]); i++) TextOut(hdc, 9 * cxChar, (i + 10)*cyChar, szBuffer, wsprintf(szBuffer, TEXT("%-45s %3s"), raster[i].szDesc, GetDeviceCaps(hdcInfo, RASTERCAPS)&raster[i].iMask ? TEXT("Yes") : TEXT("No"))); } void DoBitCodeCaps(HDC hdc, HDC hdcInfo, int cxChar, int cyChar, int iType) { static BITS curves[] = { CC_NONE, TEXT("CC_NONE No support to curve:"), //是否支持绘制曲线 CC_CIRCLES, TEXT("CC_CIRCLES Can do circles:"), //支持绘制圆 CC_PIE, TEXT("CC_PIE Can do pie wedges:"), //支持绘制扇形 CC_CHORD, TEXT("CC_CHORD Can do chord arcs:"), //支持绘制弦 CC_ELLIPSES, TEXT("CC_ELLIPSES Can do ellipses:"), //支持绘制椭圆 CC_WIDE, TEXT("CC_WIDE Can do wide borders : "), //支持绘制宽边框 CC_STYLED, TEXT("CC_STYLED Can do styled borders:"), //支持绘制带风格的边界 CC_WIDESTYLED, TEXT("CC_WIDESTYLED Can do wide and styled borders:"),//支持绘制宽且带风格的边界 CC_INTERIORS, TEXT("CC_INTERIORS Can do interiors:"), //支持内部填充 CC_ROUNDRECT, TEXT("CC_ROUNDRECT Can do round rect:") //支持绘制圆角矩形 }; static BITS lines[] = { LC_POLYLINE, TEXT("LC_POLYLINE Can do polyline:"), //是否支持绘制折线 LC_MARKER, TEXT("LC_MARKER Can do markers:"), //是否支持绘制标记符 LC_POLYMARKER, TEXT("LC_POLYMARKER Can do polymarkers:"), //是否支持绘制多种标记符 LC_WIDE, TEXT("LC_WIDE Can do wide lines:"), //是否支持绘制宽线 LC_STYLED, TEXT("LC_STYLED Can do styled lines:"), //是否支持绘制带风格的线段 LC_WIDESTYLED, TEXT("LC_WIDESTYLED Can do wide and styled lines:"), //是否支持绘制宽的且带风格的线段 LC_INTERIORS, TEXT("LC_INTERIORS Can do interiors:") //是否支持内部填充 }; static BITS poly[] = { PC_POLYGON, TEXT("PC_POLYGON Can do alternate fill polygon:"), //支持绘制交错填充多边形 PC_RECTANGLE, TEXT("PC_RECTANGLE Can do rectangle:"), //支持绘制矩形 PC_WINDPOLYGON, TEXT("PC_WINDPOLYGON Can do winding number fill polygon:"), //支持绘制折线式填充多边形 PC_SCANLINE, TEXT("PC_SCANLINE Can do scanlines:"), //支持绘制扫描线 PC_WIDE, TEXT("PC_WIDE Can do wide borders:"), //支持宽边界 PC_STYLED, TEXT("PC_STYLED Can do styled borders:"), //支持带风格的边界 PC_WIDESTYLED, TEXT("PC_WIDESTYLED Can do wide and styled borders:"), //支持宽的且带风格的边界 PC_INTERIORS, TEXT("PC_INTERIORS Can do interiors:") //支持内部填充 }; static BITS text[] = { TC_OP_CHARACTER, TEXT("TC_OP_CHARACTER Can do character output precision:"), //支持字符输出精度 TC_OP_STROKE, TEXT("TC_OP_STROKE Can do stroke output precision:"), //支持笔画输出精度 TC_CP_STROKE, TEXT("TC_CP_STROKE Can do stroke clip precision:"), //支持笔画剪切精度 TC_CR_90, TEXT("TC_CP_90 Can do 90 degree character rotation:"), //支持字符作90旋转 TC_CR_ANY, TEXT("TC_CR_ANY Can do any character rotation:"), //支持字符任意角度旋转 TC_SF_X_YINDEP, TEXT("TC_SF_X_YINDEP Can do scaling independent of X and Y:"), //支持x和y方向的独立缩放 TC_SA_DOUBLE, TEXT("TC_SA_DOUBLE Can do doubled character for scaling:"), //支持把字符放大一倍 TC_SA_INTEGER, TEXT("TC_SA_INTEGER Can do integer multiples for scaling:"), //支持整数倍缩放 TC_SA_CONTIN, TEXT("TC_SA_CONTIN Can do any multiples for exact scaling:"),//支持任何倍数的严格缩放 TC_EA_DOUBLE, TEXT("TC_EA_DOUBLE Can do double weight characters:"), //支持字符加重 TC_IA_ABLE, TEXT("TC_IA_ABLE Can do italicizing:"), //支持斜字体 TC_UA_ABLE, TEXT("TC_UA_ABLE Can do underlining:"), //支持下划线 TC_SO_ABLE, TEXT("TC_SO_ABLE Can do strikeouts:"), //支持删除线 TC_RA_ABLE, TEXT("TC_RA_ABLE Can do raster fonts:"), //支持光栅字体 TC_VA_ABLE, TEXT("TC_VA_ABLE Can do vector fonts:") //支持矢量字体 }; static struct { int iIndex; TCHAR* szTitle; BITS(*pbits)[]; //pbits为一个数组的指针,元素类型为BTIS,本例中pbits指向curves\lines\poly\text等数组。 int iSize; } bitinfo[] = { CURVECAPS, TEXT("CURVCAPS(Curve Capabiities)"), (BITS(*)[])curves, sizeof(curves) / sizeof(curves[0]), LINECAPS, TEXT("LINECAPS(Line Capabiities)"), (BITS(*)[])lines, sizeof(lines) / sizeof(lines[0]), POLYGONALCAPS, TEXT("POLYGONALCAPS(Polygonal Capabiities)"), (BITS(*)[])poly, sizeof(poly) / sizeof(poly[0]), TEXTCAPS, TEXT("TEXTCAPS(Curve Capabiities)"), (BITS(*)[])text, sizeof(text) / sizeof(text[0]) }; static TCHAR szBuffer[80]; BITS(*pbits)[] = bitinfo[iType].pbits; int iDevCaps = GetDeviceCaps(hdcInfo, bitinfo[iType].iIndex); TextOut(hdc, cxChar, cyChar, bitinfo[iType].szTitle, lstrlen(bitinfo[iType].szTitle)); for (int i = 0; i < bitinfo[iType].iSize; i++) { TextOut(hdc, cxChar, (i + 3)*cyChar, szBuffer, wsprintf(szBuffer, TEXT("%-55s %3s"), (*pbits)[i].szDesc, iDevCaps&(*pbits)[i].iMask ? TEXT("Yes") : TEXT("No"))); } }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 DevCaps2.rc 使用 // #define IDM_SCREEN 40001 #define IDM_BASIC 40002 #define IDM_OTHER 40003 #define IDM_CURVE 40004 #define IDM_LINE 40005 #define IDM_POLY 40006 #define IDM_TEXT 40007 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40013 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//DevCaps2.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Menu // DEVCAPS2 MENU BEGIN POPUP "&Device" BEGIN MENUITEM "&Screen", IDM_SCREEN END POPUP "&Capabilities" BEGIN MENUITEM "&Basic Information", IDM_BASIC MENUITEM "&Other Information", IDM_OTHER MENUITEM "&Curve Capabilities", IDM_CURVE MENUITEM "&Line Capabilities", IDM_LINE MENUITEM "&Polygonal Capabilities", IDM_POLY MENUITEM "&Text Capabilities", IDM_TEXT END END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
13.1.4 PrinterProperties函数调用
(1)获取指定的打印机句柄:OpenPrinter (szDevice, &hPrint, NULL)
(2)生成打印机属性对话框:PrinterProperties
(2)关闭指定的打印机对象:ClosePrinter:
13.1.5 检查BitBlt能力——视频显示器与打印机在使用GDI上的最重要区别!
(1)GetDeviceCaps(hdc,RC_BITBLT);检测是否具备位块传送能力。
(2)大多数点阵、激光或喷墨打印机具备这种能力,但绘图仪不具备
(3)不具备位块传送能力的设备,也就不支持以下这些GDI函数:CreateCompatibleDC、CreateCompatibleBitmap、PatBlt、BitBlt、StretchBlt、GrayString、DrawIcon、SetPixel、GetPixel、FloodFill、ExtFloodFill、FillRgn、FrameRgn、InvertRgn、PaintRgn、FillRect、FrameRect、InvertRect等。
13.1.6 最简单的打印程序
(1)DOCINFO结构体
字段 |
含义 |
cbSize |
结构体的字节大小 |
lpszDocName |
要打印的文档名称,会出现在打印机作业队列中。 |
lpszOutput |
输出文件的名称。如果为NULL,会弹出保存对话框 |
lpszDatatype |
代表某种数据类型的字符串 |
fwType |
打印工作的其它信息 |
(2)打印流程
①CreateDC或PrintDlg获得打印机设备环境句柄,并确保打印驱动库模块载入内存。
②StartDoc; //打印作业开始
StartPage //第1页
//GDI绘图(如TextOut):GDI函数会被存储在硬盘的图元文件上
EndPage //把硬盘的上图元文件读入设备驱动程序中,并根据技术“分带”技术将
//绘图函数通过打印机驱动程序中OutPut函数转化为打印机的输出,同
//时创建临时打印文件,在此过程中会频繁调用异常终止过程,以判断是
//否有异常或是否要中止打印。
StartPage //第2页
EndPage
…… //第n页
EndDoc //打印作业结束
【FormFeed 程序】
/*----------------------------------------------------- FORMFEED.C —— Advances printer to next page (c) Charles Petzold,1998 -------------------------------------------------------*/ #include <windows.h> HDC GetPrinterDC(void); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow) { static DOCINFO di = { sizeof(DOCINFO), TEXT("FormFeed") }; HDC hdcPrint = GetPrinterDC(); if (hdcPrint != NULL) { if (StartDoc(hdcPrint, &di)>0) //开始一个打印作业 if (StartPage(hdcPrint)>0 && EndPage(hdcPrint)>0) //StartPage标记一页的开始 //EndPage标记一页的结束 EndDoc(hdcPrint); //结束打印作业 DeleteDC(hdcPrint); } }