如何:检索打印机设备上下文
本主题介绍如何检索打印机设备上下文。 可以通过直接调用 CreateDC 函数来检索打印机设备上下文,也可以通过 打印 通用对话框返回它。
显示“ 打印 ”常用对话框时,用户将能够选择打印机、文档页以及要打印的文档副本数。 “ 打印 通用”对话框在数据结构中返回这些选择。
本主题介绍如何使用以下方法获取打印机设备上下文。
调用 CreateDC
如果知道要打印到的设备,可以调用 CreateDC 并将该信息直接传递给函数。 CreateDC 返回一个设备上下文,你可以在其中呈现要打印的内容。
以下代码示例中显示了检索设备上下文的最简单调用。 此示例中的代码检索默认显示设备的设备上下文。
hDC = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
若要呈现到特定打印机,必须将“WINSPOOL”指定为设备,并将打印机的正确名称传递给 CreateDC。 如果要在创建设备上下文时为设备驱动程序提供特定于设备的初始化数据,还可以在调用 CreateDC 中传递 DEVMODE 结构。
以下示例演示了对 CreateDC 的调用,其中选择了“WINSPOOL”驱动程序,并且打印机名称由 name 指定。
printerDC = CreateDC( L"WINSPOOL", printerName, NULL, NULL);
可以通过调用 EnumPrinters 函数来获取要传递给 CreateDC 的确切打印机名称字符串。 下面的代码示例演示如何调用 EnumPrinters 并获取本地连接打印机和本地连接的打印机的名称。 由于无法提前知道所需缓冲区的大小, 因此枚举打印器 将调用两次。 第一次调用返回所需缓冲区的大小。 该信息用于分配所需大小的缓冲区,对 EnumPrinters 的第二次调用将返回所需的数据。
fnReturn = EnumPrinters(
PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL,
1L, // printer info level
(LPBYTE)NULL,
0L,
&dwNeeded,
&dwReturned);
if (dwNeeded > 0)
{
pInfo = (PRINTER_INFO_1 *)HeapAlloc(
GetProcessHeap(), 0L, dwNeeded);
}
if (NULL != pInfo)
{
dwReturned = 0;
fnReturn = EnumPrinters(
PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL,
1L, // printer info level
(LPBYTE)pInfo,
dwNeeded,
&dwNeeded,
&dwReturned);
}
if (fnReturn)
{
// Review the information from all the printers
// returned by EnumPrinters.
for (i=0; i < dwReturned; i++)
{
// pThisInfo[i]->pName contains the printer
// name to use in the CreateDC function call.
//
// When this desired printer is found in the list of
// returned printer, set the printerName value to
// use in the call to CreateDC.
// printerName = pThisInfo[i]->pName
}
}
显示“打印通用”对话框
可以从两个 “打印 ”常用对话框中进行选择,以便向用户显示;较新的对话框(可通过调用 PrintDlgEx 函数显示)和较旧的样式对话框(可通过调用 PrintDlg 函数显示)。 以下部分介绍如何从应用程序调用每个对话框。
使用 PrintDlgEx 函数
调用 PrintDlgEx 函数以显示 Print 属性表。 通过使用属性表,用户可以指定有关打印作业的信息。 例如,用户可以选择要打印的一系列页面、副本数等。 PrintDlgEx 还可以检索所选打印机的设备上下文的句柄。 可以使用句柄在打印机上呈现输出。
有关演示如何使用 PrintDlgEx 检索打印机设备上下文的示例代码,请参阅使用 公共对话框中的“使用打印属性表”。
使用 PrintDlg 函数
如果应用程序必须在不支持 PrintDlgEx 函数的系统上运行,例如在运行 Windows 2000 更早版本的系统上,或者不需要 PrintDlgEx 函数提供的额外功能,请使用 PrintDlg 函数。 以下步骤介绍如何显示旧样式 打印 通用对话框。
- 初始化 PRINTDLG 数据结构。
- 调用 PrintDlg 向用户显示 “打印 通用”对话框。
- 如果 PrintDlg 调用返回 TRUE,请锁定返回的 DEVMODE 结构内存。 如果 PrintDlg 调用返回 FALSE,则用户按下了“打印通用”对话框中的“取消”按钮,因此无需处理其他任何内容。
- 分配一个足够大的本地内存缓冲区,以包含 DEVMODE 结构的副本。
- 将返回的 DEVMODE 结构复制到本地分配的 DEVMODE 结构。
- 保存 PRINTDLG 结构中返回且需要处理打印作业的其他信息。
- 释放 PRINTDLG 及其引用的内存缓冲区。
以下示例代码演示如何使用 PrintDlg 函数获取设备上下文和所选打印机的名称。
// Display the printer dialog box so the user can select the
// printer and the number of copies to print.
BOOL printDlgReturn = FALSE;
HDC printerDC = NULL;
PRINTDLG printDlgInfo = {0};
LPWSTR localPrinterName = NULL;
PDEVMODE returnedDevmode = NULL;
PDEVMODE localDevmode = NULL;
int localNumberOfCopies = 0;
// Initialize the print dialog box's data structure.
printDlgInfo.lStructSize = sizeof( printDlgInfo );
printDlgInfo.Flags =
// Return a printer device context.
PD_RETURNDC
// Don't allow separate print to file.
// Remove these flags if you want to support this feature.
| PD_HIDEPRINTTOFILE
| PD_DISABLEPRINTTOFILE
// Don't allow selecting individual document pages to print.
// Remove this flag if you want to support this feature.
| PD_NOSELECTION;
// Display the printer dialog and retrieve the printer DC.
printDlgReturn = PrintDlg(&printDlgInfo);
// Check the return value.
if (TRUE == printDlgReturn)
{
// The user clicked OK so the printer dialog box data
// structure was returned with the user's selections.
// Copy the relevant data from the data structure and
// save them to a local data structure.
//
// Get the HDC of the selected printer
printerDC = printDlgInfo.hDC;
// In this example, the DEVMODE structure returned by
// the printer dialog box is copied to a local memory
// block and a pointer to the printer name that is
// stored in the copied DEVMODE structure is saved.
//
// Lock the handle to get a pointer to the DEVMODE structure.
returnedDevmode = (PDEVMODE)GlobalLock(printDlgInfo.hDevMode);
localDevmode = (LPDEVMODE)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS,
returnedDevmode->dmSize);
if (NULL != localDevmode)
{
memcpy(
(LPVOID)localDevmode,
(LPVOID)returnedDevmode,
returnedDevmode->dmSize);
// Save the printer name from the DEVMODE structure.
// This is done here just to illustrate how to access
// the name field. The printer name can also be accessed
// by referring to the dmDeviceName in the local
// copy of the DEVMODE structure.
localPrinterName = localDevmode->dmDeviceName;
// Save the number of copies as entered by the user
localNumberOfCopies = printDlgInfo.nCopies;
}
else
{
// Unable to allocate a new structure so leave
// the pointer as NULL to indicate that it's empty.
}
// Free the DEVMODE structure returned by the print
// dialog box.
if (NULL != printDlgInfo.hDevMode)
{
GlobalFree(printDlgInfo.hDevMode);
}
}
else
{
// The user cancelled out of the print dialog box.
}
有关 PrintDlg 函数的详细信息,请参阅 使用通用对话框中的“显示打印对话框”。