Como modificar as definições de impressora com a função DocumentProperties()


Sumário


A utilização de uma estrutura DEVMODE para modificar as definições da impressora é mais difícil que apenas a alterar os campos da estrutura. Especificamente, uma estrutura DEVMODE válida para um dispositivo contém dados privados que só podem ser modificados pela função DocumentProperties() .

Este artigo explica como modificar o conteúdo de uma estrutura DEVMODE com a função DocumentProperties() .

Mais informações


Contém uma estrutura DEVMODE , como documentado pelo SDK do Win32, público ou privado e de "dados independentes de dispositivo" ou "dados dependentes do dispositivo." A parte privada de um DEVMODE existe imediatamente a seguir a parte pública, que é definida pela estrutura DEVMODE , numa memória intermédia contígua de memória.

Um programa não pode prever o tamanho desta memória intermédia, uma vez que é diferente da impressora para impressora e da versão em versão de controlador de impressora. Além disso, uma estrutura DEVMODE declarada apenas por um programa não tem espaço suficiente para os dados privados do dispositivo. Se uma memória intermédia de DEVMODE não possui dados privados é transmitida para funções como CreateDC(), ResetDC()e DocumentProperties(), a função poderá falhar.

Para utilizar eficazmente um DEVMODE com um controlador de dispositivo, crie e modifique-o seguindo estes passos:

  1. Determinar o tamanho necessário da memória intermédia do dispositivo e, em seguida, atribuir memória suficiente para o mesmo.

    DocumentProperties() devolve o número de bytes que são necessários para uma memória intermédia DEVMODE quando o último parâmetro é definido como 0. O código de exemplo neste artigo utiliza esta técnica para determinar o tamanho correcto da memória intermédia. O código de exemplo, em seguida, utiliza a função de atribuição de memória de tempo de execução C de malloc() para atribuir uma memória intermédia que seja suficientemente grande. Uma vez que funções como ResetDC() e CreateDC() e DocumentProperties() tomar apontadores para um DEVMODE como um parâmetro, a maioria das aplicações pode alocar memória que é resolvida por um ponteiro.

    No entanto, funções, tais como comum PrintDlg() ter parâmetros que são necessárias para ser alças para memória global. Se um programa utiliza a memória intermédia DEVMODE final como um parâmetro para uma destas funções, deverá atribuir memória a utilizar o GlobalAlloc() e obter um apontador para a memória intermédia utilizando GlobalLock().
  2. Solicite o controlador de dispositivo para inicializar a memória intermédia DEVMODE com as predefinições.

    O código de exemplo chamadas DocumentProperties() uma segunda vez para inicializar a memória intermédia atribuída com as predefinições actuais. DocumentProperties() preenche a memória intermédia referida como o parâmetro pDevModeOutput com as definições actuais da impressora quando o comando DM_OUT_BUFFER é transmitido no parâmetro fMode.
  3. Efectuar alterações a parte pública do DEVMODE e peça o controlador de dispositivo para intercalar as alterações a parte privada do DEVMODE ao chamar DocumentProperties().

    Após a inicializar a memória intermédia com as definições actuais no passo 2, o código de exemplo altera a parte pública do DEVMODE. Consulte a documentação do Win32 SDK para obter descrições dos membros DEVMODE . Este exemplo de código determina se a impressora pode utilizar a orientação e definições (verso) em frente e verso e alterada de forma adequada.

    Nota: um sinalizador de membro de dmFields um DEVMODE é apenas uma indicação de que uma impressora utiliza o membro associado de estrutura. Impressoras têm uma variedade de diferentes características físicas e, por conseguinte, só podem suportar um subconjunto das capacidades de um DEVMODE documentadas. Para determinar as definições de campo de um DEVMODE suportadas, aplicações devem utilizar DeviceCapabilities ().



    O código de exemplo, em seguida, faz com que um terceiro a chamada para DocumentProperties() e transmite a memória intermédia DEVMODE nos parâmetros de pDevModeInput e o pDevModeOutput. Transmite também os comandos combinados de DM_IN_BUFFER e DM_OUT_BUFFER no parâmetro fMode utilizando o operador OR("|"). Estes comandos indicam à função de tomar todas as definições estão contidas na memória intermédia e intercalá-las com as definições actuais para o dispositivo. Em seguida, escreve o resultado para a memória intermédia especificada no parâmetro de saída.
Nota: DocumentProperties() refere-se a uma impressora específica por um identificador para uma impressora: hPrinter. Este identificador é obtida a partir de OpenPrinter(), que também ilustra o exemplo de código. OpenPrinter() requer o nome de uma impressora, que é normalmente o nome amigável da impressora, tal como aparece na shell do sistema operativo. Este nome pode ser obtido de EnumPrinters(), a estrutura DEVNAMES devolvido por PrintDlg()ou a impressora predefinida.

Para obter informações adicionais sobre a impressora predefinida, clique no número de artigo abaixo para visualizar o artigo na Microsoft Knowledge Base:

246772 como obter e definir a impressora predefinida no Windows
Nota: neste artigo, os primeiros dois passos do tamanho correcto da memória intermédia a atribuir e inicializar da memória intermédia são executados com DocumentProperties(). Pode também seguir estes passos utilizando GetPrinter (). Para obter informações adicionais e um exemplo desta situação, clique no número de artigo abaixo para visualizar o artigo na Microsoft Knowledge Base:

140285 como modificar as definições da impressora através da utilização de SetPrinter

Código de exemplo

O código de exemplo a seguir estes três passos para a obtenção e alterar a memória intermédia DEVMODE. A função assume uma impressora com o nome e configura uma DEVMODE para imprimir nos dois lados e a orientação horizontal, se suportar estas funcionalidades. O DEVMODE resultante que é devolvido ao chamador é adequado para outras chamadas de API que utilizam memórias intermédias DEVMODE, por exemplo, CreateDC(), SetPrinter(), PrintDlg()ou ResetDC(). Quando o autor da chamada tiver concluído a utilizar a memória intermédia DEVMODE, o autor da chamada é responsável pela libertação de memória.

   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;

}