Cómo modificar la configuración de la impresora con la función DocumentProperties()


Resumen


Uso de una estructura DEVMODE para modificar la configuración de la impresora es más difícil que simplemente cambiar los campos de la estructura. En concreto, una estructura DEVMODE válida para un dispositivo contiene datos privados que sólo pueden modificarse mediante la función DocumentProperties() .

En este artículo se explica cómo modificar el contenido de una estructura DEVMODE con la función DocumentProperties() .

Más información


Una estructura DEVMODE , tal como se documenta en el SDK de Win32 contiene público o "datos independientes de dispositivo" y privado o "datos dependientes del dispositivo". La parte privada de una estructura DEVMODE existe inmediatamente después de la parte pública, que se define mediante la estructura DEVMODE en un búfer de memoria contigua.

Un programa no puede predecir el tamaño de este búfer porque es diferente de la impresora para la impresora y la versión del controlador de impresora. Además, una estructura DEVMODE que acaba de declarar un programa no contiene espacio suficiente para los datos privados del dispositivo. Si se pasa un búfer DEVMODE que carece de datos privados a funciones tales como CreateDC() se ResetDC()y DocumentProperties(), la función puede fallar.

Para utilizar de forma fiable una estructura DEVMODE con un controlador de dispositivo, crear y modificar siguiendo estos pasos:

  1. Determinar el tamaño requerido del búfer desde el dispositivo y, a continuación, asignar suficiente memoria para él.

    DocumentProperties() devuelve el número de bytes que se requieren para un búfer DEVMODE cuando el último parámetro se establece en 0. El código de ejemplo en este artículo utiliza esta técnica para determinar el tamaño correcto del búfer. El código de ejemplo, a continuación, utiliza la función de asignación de memoria en tiempo de ejecución de C de malloc() para asignar un búfer lo bastante grande. Porque DocumentProperties() y funciones como ResetDC() y CreateDC() se toman punteros a una estructura DEVMODE como parámetro, mayoría de las aplicaciones puede asignar memoria dirigido por un puntero.

    Sin embargo, funciones como comunes PrintDlg() toman parámetros que son necesarios para ser identificadores de memoria global. Si un programa utiliza el búfer DEVMODE final como un parámetro a una de estas funciones, debe asignar memoria mediante GlobalAlloc() y obtener un puntero al búfer mediante GlobalLock().
  2. Solicite el controlador de dispositivo para inicializar el búfer DEVMODE con la configuración predeterminada.

    El código de ejemplo llama a DocumentProperties() una segunda vez para inicializar el búfer asignado con la configuración predeterminada actual. DocumentProperties() llena el búfer que se conoce como el parámetro pDevModeOutput con la configuración actual de la impresora cuando el comando DM_OUT_BUFFER se pasa en el parámetro fMode.
  3. Realizar cambios en la parte pública de la estructura DEVMODE y solicite el controlador de dispositivo para combinar los cambios en la parte privada de la estructura DEVMODE llamando a DocumentProperties().

    Después de inicializar el búfer con la configuración actual en el paso 2, el código de ejemplo realiza cambios en la parte pública de la estructura DEVMODE. Consulte la documentación Win32 SDK para obtener descripciones de los miembros de la estructura DEVMODE . Este ejemplo de código se determina si la impresora puede utilizar opciones de dos caras (doble cara) y orientación y cambia de manera apropiada.

    Nota: una marca en el miembro de pantalla LCD de una estructura DEVMODE es sólo una indicación de que una impresora utiliza el miembro de estructura asociada. Impresoras tienen una variedad de características físicas diferentes y, por tanto, sólo admiten un subconjunto de capacidades documentadas de una estructura DEVMODE. Para determinar la configuración del campo de una estructura DEVMODE compatible, las aplicaciones deben utilizar DeviceCapabilities().



    A continuación, el código de ejemplo realiza una tercera llamada a DocumentProperties() y pasa el búfer DEVMODE en el pDevModeInput y el pDevModeOutput parámetros. También pasa los comandos combinados de DM_IN_BUFFER y DM_OUT_BUFFER en el parámetro fMode mediante el operador OR("|"). Estos comandos indican la función para tomar los valores contenidos en el búfer de entrada y combinarlas con la configuración actual para el dispositivo. A continuación, escribe el resultado en el búfer especificado en el parámetro de salida.
Nota: DocumentProperties() hace referencia a una impresora específica mediante un identificador para una impresora: hPrinter. Este identificador se obtiene de OpenPrinter(), que también muestra el código de ejemplo. OpenPrinter() requiere el nombre de una impresora, que normalmente es el nombre descriptivo de la impresora tal y como aparece en el shell del sistema operativo. Este nombre puede obtenerse desde EnumPrinters(), de la estructura DEVNAMES devuelto por PrintDlg()o de la impresora predeterminada.

Para obtener información adicional acerca de la impresora predeterminada, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

246772 cómo recuperar y establecer la impresora predeterminada de Windows
Nota: en este artículo, se realizan los dos primeros pasos de asignar el tamaño correcto del búfer e inicializar dicho búfer con DocumentProperties(). También puede seguir estos pasos utilizando GetPrinter(). Para obtener información adicional y un ejemplo de esto, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

140285 cómo modificar la configuración de la impresora mediante SetPrinter

Código de ejemplo

El código de ejemplo sigue estos tres pasos para obtener y cambiar el búfer DEVMODE. La función toma una impresora designada y configura una estructura DEVMODE para imprimir a doble cara y en la orientación horizontal si admite estas características. La estructura DEVMODE resultante que se devuelve al llamador es adecuada para otras llamadas a la API que utilizan búferes DEVMODE, como CreateDC() se, SetPrinter(), PrintDlg()o ResetDC(). Cuando haya finalizado el llamador utilizando el búfer DEVMODE, el llamador es responsable de liberar la memoria.

   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;

}