Поделиться через


Практическое руководство. Получение контекста устройства принтера

В этом разделе описывается получение контекста устройства принтера. Контекст устройства принтера можно получить, вызвав функцию CreateDC напрямую, или он может быть возвращен общим диалоговым окном Печать .

При отображении общего диалогового окна Печать пользователь сможет выбрать принтер, страницы документа и количество его копий. Диалоговое окно Печать общих данных возвращает эти параметры в структуре данных.

В этом разделе описывается, как получить контекст устройства принтера с помощью следующих методов.

Вызов CreateDC

Если вы знаете устройство, на которое вы хотите напечатать, можно вызвать CreateDC и передать эти сведения непосредственно в функцию. CreateDC возвращает контекст устройства, в котором можно отобразить содержимое для печати.

Самый простой вызов для получения контекста устройства показан в следующем примере кода. Код в этом примере извлекает контекст устройства на устройство отображения по умолчанию.

    hDC = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);

Для отрисовки на определенном принтере необходимо указать "WINSPOOL" в качестве устройства и передать правильное имя принтера в CreateDC. Вы также можете передать структуру DEVMODE в вызове CreateDC , если вы хотите предоставить данные инициализации для конкретного устройства для драйвера устройства при создании контекста устройства.

В следующем примере показан вызов CreateDC , в котором выбран драйвер WINSPOOL, а имя принтера указывается по имени.

    printerDC = CreateDC( L"WINSPOOL", printerName, NULL, NULL);

Вы можете получить точную строку имени принтера для передачи в CreateDC , вызвав функцию EnumPrinters . В следующем примере кода показано, как вызвать EnumPrinters и получить имена локальных и локально подключенных принтеров. Так как размер требуемого буфера не может быть известен заранее, 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, предшествующей Windows 2000, или ей не требуются дополнительные функции, которые предоставляет функция PrintDlgEx , используйте функцию PrintDlg . Ниже описано, как отобразить диалоговое окно "Печать " в старом стиле.

  1. Инициализируйте структуру данных PRINTDLG .
  2. Вызовите PrintDlg , чтобы отобразить для пользователя диалоговое окно Печать общего.
  3. Если вызов PrintDlg возвращает значение TRUE, заблокируйте возвращенную память структуры DEVMODE . Если вызов PrintDlg возвращает значение FALSE, пользователь нажал кнопку Отмена в диалоговом окне Печать общего, поэтому больше ничего не нужно обрабатывать.
  4. Выделите буфер локальной памяти, который достаточно велик, чтобы содержать копию структуры DEVMODE .
  5. Скопируйте возвращенную структуру DEVMODE в локально выделенную структуру.
  6. Сохраните другие сведения, возвращаемые в структуре PRINTDLG и необходимые для обработки задания печати.
  7. Освободите 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 см. в разделе "Отображение диалогового окна печати" статьи Использование общих диалоговых окон.