Modificare le impostazioni della stampante con la funzione DocumentProperties()

Questo articolo illustra come modificare le impostazioni della stampante con la DocumentProperties() funzione .

Versione originale del prodotto: Stampante
Numero KB originale: 167345

Riepilogo

L'uso di una struttura DEVMODE per modificare le impostazioni della stampante è più difficile rispetto alla semplice modifica dei campi della struttura. In particolare, una struttura DEVMODE valida per un dispositivo contiene dati privati che possono essere modificati solo dalla DocumentProperties() funzione.

Questo articolo illustra come modificare il contenuto di una struttura DEVMODE con la DocumentProperties() funzione .

Ulteriori informazioni

Una struttura DEVMODE, come documentato da Win32 SDK, contiene dati pubblici o "indipendenti dal dispositivo" e dati privati o "dipendenti dal dispositivo". La parte privata di un DEVMODE esiste immediatamente dopo la parte pubblica, definita dalla struttura DEVMODE, in un buffer contiguo di memoria.

Un programma non può stimare le dimensioni di questo buffer perché è diverso dalla stampante alla stampante e dalla versione alla versione del driver della stampante. Inoltre, una struttura DEVMODE dichiarata da un programma non contiene spazio sufficiente per i dati del dispositivo privato. Se un buffer DEVMODE privo di dati privati viene passato a funzioni come CreateDC(), ResetDC()e DocumentProperties(), la funzione potrebbe non riuscire.

Per usare in modo affidabile un DEVMODE con un driver di dispositivo, crearlo e modificarlo seguendo questa procedura:

  1. Determinare le dimensioni richieste del buffer dal dispositivo e quindi allocare memoria sufficiente.

    DocumentProperties() restituisce il numero di byte necessari per un buffer DEVMODE quando l'ultimo parametro è impostato su 0. Il codice di esempio in questo articolo usa questa tecnica per determinare le dimensioni corrette del buffer. Il codice di esempio usa quindi la funzione di allocazione della memoria di runtime C di malloc() per allocare un buffer sufficientemente grande. Poiché DocumentProperties() e funziona come ResetDC() e CreateDC() accettano puntatori a devmode come parametro, la maggior parte delle applicazioni può allocare memoria indirizzata da un puntatore.

    Tuttavia, funzioni come i parametri di take comuni PrintDlg() necessari per essere gestiti nella memoria globale. Se un programma usa il buffer DEVMODE finale come parametro per una di queste funzioni, deve allocare memoria usando GlobalAlloc() e ottenere un puntatore al buffer usando GlobalLock().

  2. Chiedere al driver di dispositivo di inizializzare il buffer DEVMODE con le impostazioni predefinite.

    Il codice di esempio chiama DocumentProperties() una seconda volta per inizializzare il buffer allocato con le impostazioni predefinite correnti. DocumentProperties() riempie il buffer denominato parametro pDevModeOutput con le impostazioni correnti della stampante quando il DM_OUT_BUFFER comando viene passato nel parametro fMode.

  3. Apportare modifiche alla parte pubblica di DEVMODE e chiedere al driver di dispositivo di unire le modifiche nella parte privata di DEVMODE chiamando DocumentProperties().

    Dopo aver inizializzato il buffer con le impostazioni correnti nel passaggio 2, il codice di esempio apporta modifiche alla parte pubblica di DEVMODE. Vedere la documentazione di Win32 SDK per le descrizioni dei membri DEVMODE. Questo codice di esempio determina se la stampante può usare le impostazioni di orientamento e duplex (fronte doppio) e le modifica in modo appropriato.

    Nota

    Un flag nel membro dmFields di DEVMODE è solo un'indicazione che una stampante usa il membro della struttura associato. Le stampanti hanno una varietà di caratteristiche fisiche diverse e, pertanto, possono supportare solo un subset delle funzionalità documentate di DEVMODE. Per determinare le impostazioni supportate del campo di un DEVMODE, le applicazioni devono usare DeviceCapabilities().

    Il codice di esempio effettua quindi una terza chiamata a DocumentProperties() e passa il buffer DEVMODE nei parametri pDevModeInput e pDevModeOutput. Passa inoltre i comandi combinati di DM_IN_BUFFER e DM_OUT_BUFFER nel parametro fMode usando l'operatore OR("|") . Questi comandi indicano alla funzione di accettare le impostazioni contenute nel buffer di input e di unirle alle impostazioni correnti per il dispositivo. Scrive quindi il risultato nel buffer specificato nel parametro out.

Nota

DocumentProperties() fa riferimento a una stampante specifica da un handle a una stampante: hPrinter. Questo handle viene ottenuto da OpenPrinter(), illustrato anche dal codice di esempio. OpenPrinter() richiede il nome di una stampante, che in genere è il nome descrittivo della stampante come appare nella shell del sistema operativo. Questo nome può essere ottenuto da EnumPrinters(), dalla struttura DEVNAMES restituita da PrintDlg()o dalla stampante predefinita.

In questo articolo vengono eseguiti i primi due passaggi per l'allocazione delle dimensioni corrette del buffer e l'inizializzazione del buffer con DocumentProperties(). È anche possibile seguire questa procedura usando GetPrinter().

Per altre informazioni e un esempio, vedere Modificare le impostazioni della stampante usando la funzione SetPrinter.

Codice di esempio

Il codice di esempio segue questi tre passaggi per ottenere e modificare il buffer DEVMODE. La funzione accetta una stampante denominata e configura un DEVMODE per la stampa su due lati e con orientamento orizzontale se supporta queste funzionalità. La DEVMODE risultante restituita al chiamante è adatta per altre chiamate API che usano buffer DEVMODE, ad CreateDC()esempio , SetPrinter(), PrintDlg()o ResetDC(). Quando il chiamante ha completato l'uso del buffer DEVMODE, il chiamante è responsabile della liberazione della 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;
}