SetPrinter 是新 API for Windows 95、 Windows NT、 Windows 2000 和 Windows XP,允许应用程序更改各种打印机属性。 但是,如本文中的代码所示某些量准备为正确调用 SetPrinter 所需。
SetPrinter() 参数如下:
hPrinter
第一个参数是其设置为要更改的打印机句柄。 这应获取 OpenPrinter() 。
dwLevel
第二个参数指定传递给 SetPrinter() 的数据的结构。 用于 Windows 95 这可以是 0、 2、 3、 4,或 5。 对于 Windows NT 这可以是 0、 2,或 3。 这些数字对应于通过第三个参数传递数据类型 (PRINTER_INFO_n)。
lpbPrinter
第三个参数是一个 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;
}
http://support.microsoft.com/kb/140285/zh-cn