在 DEVMODE 结构如记录由 Win 32 SDK 包含公共或"设备独立数据"和专用或"设备相关数据。 在 DEVMODE 的专用部分存在紧跟公共由 DEVMODE 结构的内存的连续缓冲区中定义的部分。
程序不能预测此缓冲区的大小,因为它是打印机驱动程序的不同打印机并从版本的打印机。 此外,一个程序只是声明的 DEVMODE 结构没有足够空间的专用设备数据。 如果缺少专用数据的 DEVMODE 缓冲区传递给函数 (如 CreateDC() 、 ResetDC() 和 DocumentProperties() ,可能会失败,函数。
若要可靠地的设备驱动程序中使用一个 DEVMODE,创建,并按以下步骤修改:
- 确定所需从该的设备缓冲区的大小,并且然后会为其分配足够的内存。
DocumentProperties() 返回最后一个参数设置为 0 时所需的 DEVMODE 缓冲区字节的数。 本文中的示例代码使用此技术确定正确缓冲区的大小。 然后,示例代码使用 C 运行时内存分配函数的 malloc() 分配足够大的缓冲区。 因为 DocumentProperties() 和功能 (如 ResetDC() 和 CreateDC() 采取作为参数的 DEVMODE 的指针,大多数应用程序可以分配的指针的内存。
但是,函数如常见 PrintDlg() 接受所需为全局内存的句柄参数。 如果程序使用最终的 DEVMODE 缓冲区为这些函数的参数,它应分配使用 GlobalAlloc() 的内存,并获取指向使用 GlobalLock() 的缓冲区指针。 - 要求设备驱动程序初始化 DEVMODE 缓冲区使用默认设置。
该示例代码将调用 DocumentProperties() 第二次初始化分配的缓冲区使用当前的默认设置。 DocumentProperties() 填充称为 pDevModeOutput 参数了打印机的当前设置 fMode 参数中传递 DM_OUT_BUFFER 命令时的缓冲区。 - 对在 DEVMODE 的公共部分进行更改请求设备驱动程序通过调用 DocumentProperties() 所做的更改合并在 DEVMODE 的专用部分。
在初始化了在步骤 2 中的当前设置缓冲区后的代码示例对在 DEVMODE 的公共部分进行更改。 请参阅 Win32 SDK 文档的 DEVMODE 成员的说明。 此示例代码来确定是否可以使用方向和双面打印 (双面) 设置打印机,并相应地更改它们。
注意 : 在 DEVMODE 的 dmFields 成员 A 标志并只表示打印机使用相关的结构成员。 打印机具有各种不同的物理特征,因此,可能只支持 DEVMODE 的记录功能的子集。 若要确定 DEVMODE 的字段的受支持的设置,应用程序应使用 DeviceCapabilities() 。
该示例代码然后使第三个调用 DocumentProperties() ,pDevModeInput 和 pDevModeOutput 参数中传递 DEVMODE 缓冲区。 它还使用 OR("|") 运算符传递 DM_IN_BUFFER 和 DM_OUT_BUFFER fMode 参数中合并的命令。 这些命令告诉函数需要输入缓冲区中包含任何设置,并合并它们使用当前设置为该设备。 然后它会结果写入到输出参数中指定的缓冲区。
注意 : DocumentProperties() 指向特定打印机的打印机句柄: hPrinter。 从 OpenPrinter() ,它还阐释了示例代码获取此句柄。 OpenPrinter() 需要一个打印机通常是友好名称打印机的操作系统的外壳程序中显示的名称。 从 EnumPrinters() 、 返回 PrintDlg() , DEVNAMES 结构或默认打印机,可以获取此名称。
有关默认打印机单击下面的文章编号,以查看 Microsoft 知识库中的相应:
注意 : 在这篇文章,分配缓冲区的正确的大小和初始化该缓冲区的前两个步骤执行与 DocumentProperties() 。 您也可以使用 GetPrinter() 按照这些步骤。 有关其他信息和这种示例,请单击下面该文章编号,以查看 Microsoft 知识库中相应:
示例代码
<script type="text/javascript"></script> 示例代码遵循以下三个的步骤,有关获得和更改 DEVMODE 缓冲区。 该函数采用指定的打印机,并配置它支持这些功能的情况下打印双面和以横向方向的 DEVMODE。 返回到调用方的该结果 DEVMODE 是适用于使用 DEVMODE 缓冲区如 CreateDC() 、 SetPrinter() 、 PrintDlg() 或 ResetDC() 的其他 API 调用。 当调用方完成使用 DEVMODE 缓冲区时, 调用方负责释放内存。
LPDEVMODE GetLandscapeDevMode(HWND hWnd, char *pDevice)
{
HANDLE hPrinter;
LPDEVMODE pDevMode;
DWORD dwNeeded, dwRet;
/* Start by opening the printer */
if (!OpenPrinter(pDevice, &hPrinter, NULL))
return NULL;
/*
* Step 1:
* Allocate a buffer of the correct size.
*/
dwNeeded = DocumentProperties(hWnd,
hPrinter, /* Handle to our printer. */
pDevice, /* Name of the printer. */
NULL, /* Asking for size, so */
NULL, /* these are not used. */
0); /* Zero returns buffer size. */
pDevMode = (LPDEVMODE)malloc(dwNeeded);
/*
* Step 2:
* Get the default DevMode for the printer and
* modify it for your needs.
*/
dwRet = DocumentProperties(hWnd,
hPrinter,
pDevice,
pDevMode, /* The address of the buffer to fill. */
NULL, /* Not using the input buffer. */
DM_OUT_BUFFER); /* Have the output buffer filled. */
if (dwRet != IDOK)
{
/* If failure, cleanup and return failure. */
free(pDevMode);
ClosePrinter(hPrinter);
return NULL;
}
/*
* Make changes to the DevMode which are supported.
*/
if (pDevMode->dmFields & DM_ORIENTATION)
{
/* If the printer supports paper orientation, set it.*/
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
}
if (pDevMode->dmFields & DM_DUPLEX)
{
/* If it supports duplex printing, use it. */
pDevMode->dmDuplex = DMDUP_HORIZONTAL;
}
/*
* Step 3:
* Merge the new settings with the old.
* This gives the driver an opportunity to update any private
* portions of the DevMode structure.
*/
dwRet = DocumentProperties(hWnd,
hPrinter,
pDevice,
pDevMode, /* Reuse our buffer for output. */
pDevMode, /* Pass the driver our changes. */
DM_IN_BUFFER | /* Commands to Merge our changes and */
DM_OUT_BUFFER); /* write the result. */
/* Finished with the printer */
ClosePrinter(hPrinter);
if (dwRet != IDOK)
{
/* If failure, cleanup and return failure. */
free(pDevMode);
return NULL;
}
/* Return the modified DevMode structure. */
return pDevMode;
}