ASP.net技术学习

.net初学者

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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

 

posted on 2009-06-14 00:34  C#初学者009  阅读(4466)  评论(0编辑  收藏  举报