SetPrinter 是新 API for Windows 95、 Windows NT、 Windows 2000 和 Windows XP,允许应用程序更改各种打印机属性。 但是,如本文中的代码所示某些量准备为正确调用 SetPrinter 所需。
SetPrinter() 参数如下:Printer
第一个参数是其设置为要更改的打印机句柄。 这应获取 OpenPrinter() 。dwLevel
第二个参数指定传递给 SetPrinter() 的数据的结构。 用于 Windows 95 这可以是 0、 2、 3、 4,或 5。 对于 Windows NT 这可以是 0、 2,或 3。 这些数字对应于通过第三个参数传递数据类型 (PRINTER_INFO_n)。pbPrinter
第三个参数是一个 PRINTER_INFO_n 结构 n 对应于第二个参数中数的位置。 此结构可以导致混淆,因为它不只是该结构的大小的缓冲区。 这些结构包含独立于设备的信息,但紧跟在内存中一由设备驱动程序的设备相关信息的变量段。 因此,一个小的工作涉及来确定此缓冲区应该有多大。 这是通过调用 GetPrinter() ,它将设置为所需的总大小的 pcbNeeded 来实现的。此外,缓冲区通常中包含大量的独立于设备和设备相关信息。 您的应用程序不会知道也不关心在大多数这些结构成员的值。 因此,感兴趣的更改时,您必须插入这些其他数据片段的所有正确的值。 第二次调用 GetPrinter() 时设置这些其他数据片段。
dwCommand
第四个参数用于暂停打印,继续打印,或清除所有打印作业。 它通常不用于在同一时间使用 lpbPrinter。 本文未涉及设置打印机状态,因此该示例代码将此参数设置为 0 中。有关 DEVMODE
通常,指向 pDevMode DEVMODE 结构的元素将被修改 (而不是 PRINTER_INFO_n 的元素)。 如果是这样,> dmFields 标志 pDevMode 会告诉应用程序可以更改哪些字段。 因为这提供给您的 GetPrinter() ,您可以尝试更改之前检查 dmFields 标志。此外,因为修改 DEVMODE 的独立于设备的部分中的字段也可能会影响设备相关部分中的更改,您希望以使一致的 DEVMODE 结构的 SetPrinter() 调用 SetPrinter() 之前调用 DocumentProperties() 。
示例代码
// MySetPrinter // // Demonstrates how to use the SetPrinter API. This particular function changes the orienation // for the printer specified in pPrinterName to the orientation specified in dmOrientation. // // Valid values for dmOrientation are: // DMORIENT_PORTRAIT (1) // or // DMORIENT_LANDSCAPE (2) BOOL MySetPrinter(LPTSTR pPrinterName, short dmOrientation) { HANDLE hPrinter = NULL; DWORD dwNeeded = 0; PRINTER_INFO_2 *pi2 = NULL; DEVMODE *pDevMode = NULL; PRINTER_DEFAULTS pd; BOOL bFlag; LONG lFlag; // Open printer handle (on Windows NT, you need full-access because you // will eventually use SetPrinter)... ZeroMemory(&pd, sizeof(pd)); pd.DesiredAccess = PRINTER_ALL_ACCESS; bFlag = OpenPrinter(pPrinterName, &hPrinter, &pd); if (!bFlag || (hPrinter == NULL)) return FALSE; // The first GetPrinter tells you how big the buffer should be in // order to hold all of PRINTER_INFO_2. Note that this should fail with // ERROR_INSUFFICIENT_BUFFER. If GetPrinter fails for any other reason // or dwNeeded isn't set for some reason, then there is a problem... SetLastError(0); bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded); if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0)) { ClosePrinter(hPrinter); return FALSE; } // Allocate enough space for PRINTER_INFO_2... pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded); if (pi2 == NULL) { ClosePrinter(hPrinter); return FALSE; } // The second GetPrinter fills in all the current settings, so all you // need to do is modify what you're interested in... bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded); if (!bFlag) { GlobalFree(pi2); ClosePrinter(hPrinter); return FALSE; } // If GetPrinter didn't fill in the DEVMODE, try to get it by calling // DocumentProperties... if (pi2->pDevMode == NULL) { dwNeeded = DocumentProperties(NULL, hPrinter, pPrinterName, NULL, NULL, 0); if (dwNeeded <= 0) { GlobalFree(pi2); ClosePrinter(hPrinter); return FALSE; } pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded); if (pDevMode == NULL) { GlobalFree(pi2); ClosePrinter(hPrinter); return FALSE; } lFlag = DocumentProperties(NULL, hPrinter, pPrinterName, pDevMode, NULL, DM_OUT_BUFFER); if (lFlag != IDOK || pDevMode == NULL) { GlobalFree(pDevMode); GlobalFree(pi2); ClosePrinter(hPrinter); return FALSE; } pi2->pDevMode = pDevMode; } // Driver is reporting that it doesn't support this change... if (!(pi2->pDevMode->dmFields & DM_ORIENTATION)) { GlobalFree(pi2); ClosePrinter(hPrinter); if (pDevMode) GlobalFree(pDevMode); return FALSE; } // Specify exactly what we are attempting to change... pi2->pDevMode->dmFields = DM_ORIENTATION; pi2->pDevMode->dmOrientation = dmOrientation; // Do not attempt to set security descriptor... pi2->pSecurityDescriptor = NULL; // Make sure the driver-dependent part of devmode is updated... lFlag = DocumentProperties(NULL, hPrinter, pPrinterName, pi2->pDevMode, pi2->pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); if (lFlag != IDOK) { GlobalFree(pi2); ClosePrinter(hPrinter); if (pDevMode) GlobalFree(pDevMode); return FALSE; } // Update printer information... bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0); if (!bFlag) // The driver doesn't support, or it is unable to make the change... { GlobalFree(pi2); ClosePrinter(hPrinter); if (pDevMode) GlobalFree(pDevMode); return FALSE; } // Tell other apps that there was a change... SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L, (LPARAM)(LPCSTR)pPrinterName, SMTO_NORMAL, 1000, NULL); // Clean up... if (pi2) GlobalFree(pi2); if (hPrinter) ClosePrinter(hPrinter); if (pDevMode) GlobalFree(pDevMode); return TRUE; }