Modificar la configuración de la impresora con la función DocumentProperties()

En este artículo se muestra cómo modificar la configuración de la impresora con la DocumentProperties() función .

Versión original del producto: Impresora
Número de KB original: 167345

Resumen

El 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 solo la función puede modificar DocumentProperties() .

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

Más información

Una estructura DEVMODE, como documenta el SDK de Win32, contiene datos públicos o "independientes del dispositivo" y datos privados o dependientes del dispositivo. La parte privada de un DEVMODE existe inmediatamente después de la parte pública, definida por la estructura DEVMODE, en un búfer contiguo de memoria.

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

Para usar de forma confiable un DEVMODE con un controlador de dispositivo, creelo y modifíquelo siguiendo estos pasos:

  1. Determine el tamaño necesario del búfer desde el dispositivo y, a continuación, asigne suficiente memoria para él.

    DocumentProperties() devuelve el número de bytes necesarios para un búfer DEVMODE cuando el último parámetro se establece en 0. El código de ejemplo de este artículo usa esta técnica para determinar el tamaño correcto del búfer. A continuación, el código de ejemplo usa la función de asignación de memoria en tiempo de ejecución de C para malloc() asignar un búfer lo suficientemente grande. Dado que DocumentProperties() y funciona como ResetDC() y CreateDC() toman punteros a un DEVMODE como parámetro, la mayoría de las aplicaciones pueden asignar memoria que se aborda mediante un puntero.

    Sin embargo, funciones como los parámetros de toma comunes PrintDlg() que se necesitan para ser identificadores de la memoria global. Si un programa usa el búfer DEVMODE final como parámetro para una de estas funciones, debe asignar memoria mediante GlobalAlloc() y obtener un puntero al búfer mediante GlobalLock().

  2. Pida al controlador de dispositivo que inicialice el búfer DEVMODE con la configuración predeterminada.

    El código de ejemplo llama DocumentProperties() a una segunda vez para inicializar el búfer asignado con la configuración predeterminada actual. DocumentProperties() rellena el búfer al que se hace referencia como parámetro pDevModeOutput con la configuración actual de la impresora cuando se pasa el DM_OUT_BUFFER comando en el parámetro fMode.

  3. Realice cambios en la parte pública del DEVMODE y pida al controlador de dispositivo que combine los cambios en la parte privada del 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 DEVMODE. Consulte la documentación del SDK de Win32 para obtener descripciones de los miembros de DEVMODE. Este código de ejemplo determina si la impresora puede usar la configuración de orientación y dúplex (a doble cara) y los cambia correctamente.

    Nota:

    Una marca en el miembro dmFields de un DEVMODE es solo una indicación de que una impresora usa el miembro de estructura asociado. Las impresoras tienen una variedad de características físicas diferentes y, por lo tanto, solo pueden admitir un subconjunto de las capacidades documentadas de un DEVMODE. Para determinar la configuración admitida del campo de un DEVMODE, las aplicaciones deben usar DeviceCapabilities().

    A continuación, el código de ejemplo realiza una tercera llamada a DocumentProperties() y pasa el búfer DEVMODE en los parámetros pDevModeInput y pDevModeOutput. 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 a la función que tome cualquier configuración contenida en el búfer de entrada y que las combine con la configuración actual del dispositivo. A continuación, escribe el resultado en el búfer especificado en el parámetro out.

Nota:

DocumentProperties() hace referencia a una impresora específica mediante un identificador a una impresora: hPrinter. Este identificador se obtiene de OpenPrinter(), que el código de ejemplo también muestra. OpenPrinter() requiere el nombre de una impresora, que suele ser el nombre descriptivo de la impresora tal como aparece en el shell del sistema operativo. Este nombre se puede obtener de , de EnumPrinters()la estructura DEVNAMES devuelta por PrintDlg()o de la impresora predeterminada.

En este artículo, los dos primeros pasos para asignar el tamaño correcto del búfer e inicializar ese búfer se realizan con DocumentProperties(). También puede seguir estos pasos mediante GetPrinter().

Para obtener más información y un ejemplo de esto, vea Modificar la configuración de la impresora mediante la función 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 con nombre y configura un DEVMODE para imprimir a doble cara y en la orientación horizontal si admite estas características. El DEVMODE resultante que se devuelve al autor de la llamada es adecuado para otras llamadas API que usan búferes DEVMODE, como CreateDC(), SetPrinter(), PrintDlg()o ResetDC(). Cuando el autor de la llamada ha completado el uso del búfer DEVMODE, el autor de la llamada 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;
}