Como: Recuperar um contexto de dispositivo de impressora

Este tópico descreve como recuperar um contexto de dispositivo de impressora. Você pode recuperar um contexto de dispositivo de impressora chamando a funçãoCreateDCdiretamente ou este contexto pode ser retornado por uma caixa de diálogo padrão Imprimir.

Quando você exibe uma caixa de diálogo Imprimir comum, um usuário poderá selecionar a impressora, as páginas do documento e o número de cópias do documento que deseja imprimir. A caixa de diálogo comum Imprimir retorna essas seleções em uma estrutura de dados.

Este tópico descreve como obter um contexto de dispositivo de impressora usando os seguintes métodos.

Chamada CreateDC

Se você souber o dispositivo para o qual deseja imprimir, você pode chamar CreateDC e passar essas informações diretamente para a função. CreateDC retorna um contexto de dispositivo no qual você pode renderizar o conteúdo a ser impresso.

A chamada mais simples para recuperar um contexto de dispositivo é mostrada no exemplo de código a seguir. O código neste exemplo recupera um contexto de dispositivo para o dispositivo de exibição padrão.

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

Para renderizar para uma impressora específica, você deve especificar "WINSPOOL" como o dispositivo e passar o nome correto da impressora para CreateDC. Você também pode passar uma estrutura de DEVMODE na chamada para CreateDC se quiser fornecer dados de inicialização específicos do dispositivo para o driver de dispositivo ao criar o contexto do dispositivo.

O exemplo a seguir mostra uma chamada para CreateDC na qual o driver "WINSPOOL" é selecionado e o nome da impressora é especificado pelo nome.

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

Você pode obter a cadeia de caracteres exata do nome da impressora para passar para CreateDC chamando a função EnumPrinters. O exemplo de código a seguir mostra como chamar EnumPrinters e obter os nomes das impressoras locais e conectadas localmente. Como o tamanho do buffer necessário não pode ser conhecido antecipadamente, o EnumPrinters é chamado duas vezes. A primeira chamada retorna o tamanho do buffer necessário. Essas informações são usadas para alocar um buffer do tamanho necessário e a segunda chamada para EnumPrinters retorna os dados desejados.

    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
        }
    }

Mostrar uma caixa de diálogo comum de impressão

Você pode escolher entre duas caixas de diálogo Imprimir comuns para exibir a um usuário; a caixa de diálogo mais recente, que você pode exibir chamando a função PrintDlgEx e a caixa de diálogo de estilo mais antigo, que você pode exibir chamando a função PrintDlg. As seções a seguir descrevem como chamar cada caixa de diálogo de um aplicativo.

Usando a função PrintDlgEx

Chame a funçãoPrintDlgEx para exibir o Imprimir folha de propriedades. Usando a folha de propriedades, o usuário pode especificar informações sobre o trabalho de impressão. Por exemplo, o usuário pode selecionar um intervalo de páginas para imprimir, o número de cópias e assim por diante. O PrintDlgEx também pode recuperar um identificador para o contexto de dispositivo da impressora selecionada. Você pode usar o identificador para renderizar a saída na impressora.

Para obter um código de exemplo que ilustra o uso de PrintDlgEx para recuperar um contexto de dispositivo de impressora, consulte "Usando a ficha de propriedades de impressão" em Usando caixas de diálogo comuns.

Usando a função PrintDlg

Se o seu aplicativo deve ser executado em um sistema que não suporta a funçãoPrintDlgEx, como em um sistema que esteja executando uma versão do Windows anterior ao Windows 2000, ou não precisa da funcionalidade extra que a função PrintDlgEx fornece, use a função PrintDlg. As etapas a seguir descrevem como exibir a antiga caixa de diálogo comum do estilo Imprimir.

  1. Inicialize a estrutura de dados PRINTDLG.
  2. Chame PrintDlg para exibir a caixa de diálogo Imprimir comum ao utilizador.
  3. Se a chamada PrintDlg retornar TRUE, bloqueie a memória da estrutura DEVMODE retornada. Se a chamada PrintDlg retornar FALSE, o utilizador pressionou o botão 'Cancelar' na caixa de diálogo 'Imprimir' comum, pelo que não há mais nada para processar.
  4. Aloque um buffer de memória local que seja grande o suficiente para conter uma cópia da estruturaDEVMODE.
  5. Copie a estrutura DEVMODE retornada com para a estrutura alocada localmente com.
  6. Guarde outras informações que são retornadas na estrutura PRINTDLG e que necessitará para processar o trabalho de impressão.
  7. Liberte o PRINTDLG e os buffers de memória a que faz referência.

O código de exemplo a seguir ilustra como usar a função dePrintDlgpara obter o contexto do dispositivo e o nome da impressora selecionada.

// 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.
}

Para obter mais informações sobre a função PrintDlg, consulte "Mostrando a Caixa de Diálogo Imprimir" em Utilizando Caixas de Diálogo Comuns.