Ändern der Druckereinstellungen mit der DocumentProperties()-Funktion

In diesem Artikel wird gezeigt, wie Sie Druckereinstellungen mit der DocumentProperties() -Funktion ändern.

Ursprüngliche Produktversion: Drucker
Ursprüngliche KB-Nummer: 167345

Zusammenfassung

Die Verwendung einer DEVMODE-Struktur zum Ändern von Druckereinstellungen ist schwieriger, als nur die Felder der Struktur zu ändern. Insbesondere enthält eine gültige DEVMODE-Struktur für ein Gerät private Daten, die nur von der DocumentProperties() Funktion geändert werden können.

In diesem Artikel wird erläutert, wie Sie den Inhalt einer DEVMODE-Struktur mit der DocumentProperties() -Funktion ändern.

Weitere Informationen

Eine DEVMODE-Struktur, wie vom Win32 SDK dokumentiert, enthält öffentliche oder "geräteunabhängige Daten" und private oder "geräteabhängige Daten". Der private Teil eines DEVMODE befindet sich unmittelbar nach dem öffentlichen Teil, der durch die DEVMODE-Struktur definiert wird, in einem zusammenhängenden Speicherpuffer.

Ein Programm kann die Größe dieses Puffers nicht vorhersagen, da er sich von Drucker zu Drucker und von Version zu Version des Druckertreibers unterscheidet. Darüber hinaus enthält eine DEVMODE-Struktur, die von einem Programm deklariert wird, nicht genügend Speicherplatz für private Gerätedaten. Wenn ein DEVMODE-Puffer ohne private Daten an Funktionen wie CreateDC(), ResetDC()und DocumentProperties()übergeben wird, kann die Funktion fehlschlagen.

Um eine DEVMODE-Instanz zuverlässig mit einem Gerätetreiber zu verwenden, erstellen und ändern Sie ihn mithilfe der folgenden Schritte:

  1. Bestimmen Sie die erforderliche Größe des Puffers vom Gerät aus, und weisen Sie dann genügend Arbeitsspeicher dafür zu.

    DocumentProperties() gibt die Anzahl der Bytes zurück, die für einen DEVMODE-Puffer erforderlich sind, wenn der letzte Parameter auf 0 festgelegt ist. Der Beispielcode in diesem Artikel verwendet diese Technik, um die richtige Größe des Puffers zu bestimmen. Der Beispielcode verwendet dann die C-Laufzeitspeicherbelegungsfunktion von malloc() , um einen Puffer zuzuweisen, der groß genug ist. Da DocumentProperties() und wie ResetDC() funktionieren und CreateDC() Zeiger auf einen DEVMODE-Parameter verwenden, können die meisten Anwendungen Speicher zuordnen, der durch einen Zeiger adressiert wird.

    Funktionen wie die gängigen PrintDlg() übernehmen jedoch Parameter, die für handles in den globalen Speicher benötigt werden müssen. Wenn ein Programm den endgültigen DEVMODE-Puffer als Parameter für eine dieser Funktionen verwendet, sollte es Speicher mithilfe GlobalAlloc() von zuordnen und einen Zeiger auf den Puffer mithilfe GlobalLock()von abrufen.

  2. Bitten Sie den Gerätetreiber, den DEVMODE-Puffer mit den Standardeinstellungen zu initialisieren.

    Der Beispielcode ruft ein zweites Mal auf DocumentProperties() , um den zugeordneten Puffer mit den aktuellen Standardeinstellungen zu initialisieren. DocumentProperties() füllt den Puffer, der als pDevModeOutput-Parameter bezeichnet wird, mit den aktuellen Einstellungen des Druckers aus, wenn der DM_OUT_BUFFER Befehl im fMode-Parameter übergeben wird.

  3. Nehmen Sie Änderungen am öffentlichen Teil des DEVMODE vor, und bitten Sie den Gerätetreiber, die Änderungen mit dem privaten Teil von DEVMODE zusammenzuführen, indem Sie aufrufen DocumentProperties().

    Nach der Initialisierung des Puffers mit den aktuellen Einstellungen in Schritt 2 nimmt der Beispielcode Änderungen am öffentlichen Teil von DEVMODE vor. Beschreibungen der DEVMODE-Member finden Sie in der Win32 SDK-Dokumentation. Dieser Beispielcode bestimmt, ob der Drucker Ausrichtungs- und Duplexeinstellungen (beidseitig) verwenden kann, und ändert sie entsprechend.

    Hinweis

    Ein Flag im dmFields-Member eines DEVMODE-Elements ist nur ein Hinweis darauf, dass ein Drucker das zugeordnete Strukturelement verwendet. Drucker haben eine Vielzahl von unterschiedlichen physischen Merkmalen und unterstützen daher möglicherweise nur eine Teilmenge der dokumentierten Funktionen eines DEVMODE. Um die unterstützten Einstellungen eines DEVMODE-Felds zu bestimmen, sollten Anwendungen verwenden DeviceCapabilities().

    Der Beispielcode führt dann einen dritten Aufruf von DocumentProperties() durch und übergibt den DEVMODE-Puffer sowohl in den Parametern pDevModeInput als auch pDevModeOutput. Außerdem werden die kombinierten Befehle von DM_IN_BUFFER und DM_OUT_BUFFER im fMode-Parameter mithilfe des OR("|")-Operators übergeben. Diese Befehle weisen die Funktion an, alle im Eingabepuffer enthaltenen Einstellungen zu übernehmen und mit den aktuellen Einstellungen für das Gerät zusammenzuführen. Anschließend wird das Ergebnis in den puffer geschrieben, der im out-Parameter angegeben ist.

Hinweis

DocumentProperties() verweist auf einen bestimmten Drucker durch ein Handle für einen Drucker: hPrinter. Dieses Handle wird von OpenPrinter()abgerufen, was auch im Beispielcode veranschaulicht wird. OpenPrinter() erfordert den Namen eines Druckers, der in der Regel der Anzeigename des Druckers ist, wie er in der Shell des Betriebssystems angezeigt wird. Dieser Name kann aus EnumPrinters(), aus der DEVNAMES-Struktur abgerufen werden, die von PrintDlg()zurückgegeben wird, oder vom Standarddrucker.

In diesem Artikel werden die ersten beiden Schritte zum Zuordnen der richtigen Puffergröße und initialisieren dieses Puffers mit DocumentProperties()ausgeführt. Sie können diese Schritte auch mithilfe GetPrinter()von ausführen.

Weitere Informationen und ein Beispiel dafür finden Sie unter Ändern von Druckereinstellungen mithilfe der SetPrinter-Funktion.

Beispielcode

Der Beispielcode folgt diesen drei Schritten zum Abrufen und Ändern des DEVMODE-Puffers. Die Funktion verwendet einen benannten Drucker und konfiguriert einen DEVMODE so, dass er beidseitig und im Querformat gedruckt wird, wenn diese Features unterstützt werden. Das resultierende DEVMODE, das an den Aufrufer zurückgegeben wird, eignet sich für andere API-Aufrufe, die DEVMODE-Puffer verwenden, z CreateDC(). B. , SetPrinter(), PrintDlg()oder ResetDC(). Wenn der Aufrufer die Verwendung des DEVMODE-Puffers abgeschlossen hat, ist der Aufrufer für die Freigabe des Arbeitsspeichers verantwortlich.

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